coreboot GSoC 2014

We are excited to announce that coreboot has been selected for Google Summer of Code 2014.  As with previous years, coreboot will also support flashrom and SerialICE projects.

All the information you need is on the coreboot GSOC page and the following project ideas pages:

We are in the Get Familiar period before the Application Period opens. Join the mailing list and IRC #coreboot. Start to get familiar with coreboot, our development process, and with the coreboot community. Discuss project ideas and scope with coreboot developers.
Student Application Period: March 10 – March 21

To be a mentor, you must be a coreboot contributor in good standing (review and commit rights). If you would like to be a member, please add your name to the coreboot GSoC mentors section and signup and connect with coreboot in melange.

Feel free to contact me (IRC:marcj) if you have any questions.

Pencils down

This is it. The beginning for QiProg has ended. It has been a long and tedious journey to equip the Stellaris Launchpad for Low Pin Count mastering. The hardware is built, and it works. The software is there, although its contribution to the ecosystem is somewhat minimal — it is more of a bridge than a road in itself. The real value lies in the firmware. To the best of my knowledge, LPC bus mastering has not been implemented in a microcontroller without using ASICs or FPGAs. The vessels are here, and now it is time for the explorers to start their journeys.

Why do I talk like this is project is not over? It is not over. Although I have attained the minimal goals, there is a whole new world to explore. Integration in flashrom was one of the targets I had really hoped for, but was unable to complete. Is writing of the chip working? Yes. Is it reliable? Writing and verifying predetermined patterns works. Disturbingly, when I plugged in output from /dev/urand, the write did not verify. Some bits were simply not programmed, although the majority of the chip matched. Is it the LPC bus mastering that is at fault, is it the command sequence, or are we not giving the chip enough time to complete the operation? Will chips other than the SST 49LF080A work? Can we write a complete ROM image and boot a machine? This is the exploration phase: we have built it, now let’s make the most of it.

Time has been tight for the last month. I had forgotten to plan for the start of the fall semester, and my time since this event has been severely crippled. I wish I could have achieved more. I took the last two days off from the University to organize the last few weeks’ salad of stashed and uncommitted changes into readable patches.

I don’t feel sad, just tired. Exhausted, I have nothing left to keep me entertained but an Alec Bradley Presando cigar, which I have been saving for a special occasion. This is that occasion: QiProg has stopped being a commitment, and became a hobby, a child, something to care for. Now is the time to build your VultureProg, get the software, and start reporting those issues you know you will encounter. I’m in Houston, and I don’t have a problem.

GSoC [early debugging] closure

Time to stop coding was last week and I feel I have barely touched the surface of my original project proposal.

My biggest contribution comes in the form of usbdebug patches: Most mainboards with USB 2.0 EHCI controller should now be able to produce console logging on USB port. More importantly, one has now the option of using some low-cost ARM development kit boards as a replacement for the Net20DC dongle device. Digging into ARM was not really in my original plans and setting up the required environment took more time that I had hoped for.

I had the idea of collecting a trace of PCI configuration in CBMEM. Turned out I first had to do some cleanup on both PCI and CBMEM and while those have been submitted (with a minimal amount of testing) the tracing part I did not start at all. On the other hand, cleanup on CBMEM has enabled timestamp collection and CBMEM console for ramstage for most mainboards and I have a fairly clear vision what needs to be done to extend these to romstages as well.  I think there would be interest to have these features on ARMv7 too, just takes a bit of coordination and access to platform.

On the so-called “coreboot panic room” tasks I did not submit any code. I liked the idea of using some BeagleBone board as a proxy and having the possibility to switch between SerialICE debugging or GDB or pre-OS flash programmer. If time permits, there might even be some integration or interaction with radare coming up next months for SerialICE.


GSoC (coreboot): Test interface board complete

Apologies for the late update. The design that I posted in the last post was more challenging than I had thought. However I’m happy to announce that my test hardware that I call ‘coreboot test interface board’ (TIB) is now complete. Only some of the software interface part is remaining in the project. So let me share with you a very quick update of last month. Continue reading GSoC (coreboot): Test interface board complete

GSoC [early debugging] More connectivity

A substantial cleanup on CBMEM initialisation is now under review. Goal is to get timestamps and CBMEM console supported on more/most mainboards, but I do not expect to complete this during the official GSoC period, or within the next two weeks time.

One of the goals I originally had set was to have means to re-program the flash chip from pre-OS environment. It is now clear I will not have time to finish (or even start) this part of the project. The  decision to delay this part was made quite early on, actually. I learned similar work had already been developed as a combination of FILO+libflashrom, and I hope Stefan’s efforts on another GSoC project will help get this code published in near future. I might still try to get the FILO console appear over usbdebug, adding support of USB communication class (CDC / ACM) in libpayload should not be very difficult.

I have saved some of the most interesting and challenging parts last: having SerialICE and GDB run over usbdebug. Hopefully I get to report about those next week.

GSoC [early debugging] Bridging the gap

ARM is now on the table, as I am bridging the coreboot console from USB to gigabit ethernet, using a BeagleBone board equipped with the USB debug device gadget driver. At first I was a bit concerned of all the latency having an USB-to-ethernet bridge software solution on the communication, so it was now good time to do some measurements.

I used daemon called ser2net to redirect coreboot console TTY to TCP (telnet) and enabled timestamping to estimate the time it takes from power-on to entering payload on amd/persimmon with maximum logging (level=spew).

First, connecting with serial UART @115200bps on x86 host this was total of 15 seconds. Of this it spent 4 seconds in AGESA doing some SPI flash operations and during that time there was no console output.

Repeating same using usbdebug on the BeagleBone OTG port, total time was 9 seconds and again 4 seconds was waiting for SPI completion.  I would say we have a rough figure that console output on usbdebug is twice as fast as what super-IO can typically offer.

Driver compilation and patches are updated here:

To use BeagleBone some additional work was needed on coreboot side but BeagleBone Black and other ARM boards where there is no hub between OTG connector and controller should already work.

Retrofitting QiProg for the space age

In the previous two posts, I was developing a bigger issue that has became more and more apparent. The USB QiProg protocol is not completely specified. I didn’t think much of the “TODO” items in Peter’s original protocol. I figured I’ll figure them out as I go along, and I did figure out a lot of little details as I went along. Of course, none of those details related to implementing the big TODOs. So, here I am in week 11(?) with an incomplete protocol.

Last week did not see much coding. I spent some quality time with premium cigars, a pen, and engineering paper. I wrote the name of each function I needed to implement, left a blank space, wrote the name of the next function, and so on. Then, I drew the packets, laid out their structure, went through the process of thought experimentation, crumpled the piece of paper, threw it again, and started from scratch. I eventually settled on a protocol “completion” which I though was acceptable. I wrote it up in digital form and submitted it to Peter for review.

Communication with Peter is asynchronous. Very rarely do we both meet up on IRC to discuss the details in real time. Therefore, I decided to implement the “completion” protocol as-is, and modify the implementation later should the protocol change. This should keep me occupied with coding. I am very happy I can get back to coding. Working out protocol details is exhausting and boring.

It is a bit frustrating. We have firmware code to read, erase, and byte-program, yet the puzzle is not complete. I was expecting the LPC bus mastering to be the most demanding, and USB communication to be an almost transparent add-on. That would have been fun! The reality is the opposite, but, besides the aforementioned frustration, it’s still fun — albeit a different type of “fun”. It’s time to scrap weekend plans for the next couple of weeks, and kick in the overtime. Until next time, get your Stellaris Launchpads, order your VultureProg PCBs, and stay tuned. This baby is going to run smokin’ hot.

A brief progress sheet

Last week, I laid out a list of things to do in order to get more of the protocol finalized. Most of the items are crossed off, however, one little item remains standing. This item, while innocent and seemingly harmless is more painful than falling on your buttocks from a 10 story building on solid granite. Let’s have a look at why this small item is of such significance.

  • new API call set_chip_size()

When people think of QiProg, they think of one gadget with one flash chip connected. This is the common case, and, for the foreseeable future, will be the de-facto way of using QIProg. However, the original USB specification was intended for a broader use case: a programmer with several, individually addressable chips connected. One who observes the qiprog_read_chip_id() call will notice that it translates to a READ_CHIP_ID request over USB. This request will return identification data for up to nine chips. Aye, there’s the rub.

How does this play into set_chip_size()? Simple, set_chip_size for which chip? Do we send a flat list of nine uint32_t sizes, thus only needing one round-trip (control request) for all chips? Do we use the wIndex field of the round-trip, at the cost of needing one such trip for each chip? Once this question is answered, it will determine the answer for set_[erase/write]_[size/command] call and their respective USB round-trips, thus completing the USB protocol, and bringing QiProg to a usable state.

It’s easy to see why this one little detail is a blocker for all other remaining issues. I am leaning towards the use of wIndex (not the glass cleaner). Implementing a new control request in software and firmware is a matter of minutes. Testing it, and making sure it works properly is, at most, a two hour endeavor. Getting the design right: priceless.

GSoC [early debugging] USB submission

Seems I am reaching one of my goals of my original GSoC proposal in bringing usbdebug available as a compile option for most the mainboards with compatible chipset.

As I wrote in an earlier blog, it has been more of a refactoring job on existing code rather than creating something entirely new. There are a series of protocol details where I spotted the implementation took some shortcuts and I have attempted to fix those. I also made improvements to better control how the possible debug dongle connection is probed. There is more testing needed there and also it needs to be fixed to not become excessively slow when dongle is not connected or if it is disconnected before OS is loaded.

At the time of writing, my patches have not yet been submitted to master but are available on the gerrit review board. It is likely there will be some minor fixes, so I will not give exact commit hashes one should checkout and merge. In short: checkout and merge the two topic-branches usbdebug-cfg and usbdebug-lib. In addition, for AMD Agesa boards one needs  “AMD AGESA: Place CAR_GLOBAL in BSP stack”.

Now if you only had something to connect it with, I could ask for your help actually testing these changes and finding out if it works! I am still waiting for my BeagleBone Black to arrive to make some fixes to the kernel EHCI debug gadget driver, and the situation with the choice of debug dongles will then improve quite radically. I do have the older BeagleBone and have built custom kernel modules for it and I have started to study how g_dbgp driver interacts with the gadget serial port framework.

What I discovered after picking up a second-hand original BeagleBone was that it does not have its USB port directly connected to the ARM chip, but there is an USB hub chip in between. It might be possible to configure that hub even though our USB requests are limited to a length of max 8 bytes per transaction. The EHCI debug specs do not allow a hub there, but if we can make it work, why not do it?


Experiments of mind

The time for writing code is over. The time to design hardware is over. After seven weeks, the vultureprog_action_shotbeginning has come to an abrupt end. I am severely behind schedule. In week seven I was supposed to implement erase functionality — tell the programmer how to erase the chip. This is not done. On the other hand, I have had code for weeks 8 and 9 almost ready, and just merged most of it last week. So, where am I? Am I ahead or behind schedule?

The fallacy of preemption

One of the requirements for applying as a GSoC coreboot student was to have a fully established, vultureprog_probingschedule from day[-1]. Establishing this schedule was a great experience, and it allowed me to think in depth about the problem and possible solutions — to a certain degree. I picked the steps I considered logical, in the order which I saw logical. Development is never about writing code in the order in which it will be executed. In this particular case, it was much easier to implement bulk writing without a predefined erase/write strategy, opting instead for a default just-do-it approach.

Why is this approach better than following the schedule, from a development point of view? We have had bulk read partially working for a while now. From the host point of view, reading and writing are symmetrical operations. The bulk of the code (pun definitely intended) is shared between the read and write operation. They both juggle data on the same endpoint. The only difference is the endpoint direction bit. It therefore made sense, once bulk reading was fixed for corner cases, to uses the same code to send data to the programmer. Making the programmer write that data was a matter of a couple of hours. There was no sensible reason to wait an additional two weeks before implementing this last bit.

Software development work is as much about making things work, as it is about the application of programming principles with unquestionable moral authority and correctness. In this case, implementing a trivial extension reusing code fresh in my mind was the preferred approach. Not only did it save me time by not having to re-examine the situation a few weeks from now, it also allows me to have a working program/verify scenario when implementing the erase strategies. As one might imagine, this makes the problem a lot easier. Attempting to preempt and enforce a schedule before the problem is thoroughly explored, occasionally conflicts with best practices of development. With this in mind, I am neither behind, nor ahead of schedule. I am precisely where I need to be.

A matter of experimentation

Most of the infrastructure and code is already in place. Bringing QiProg to completion is no longer an issue of adding functionality through code, but rather completing functionality by connecting the existing code. One issue I discovered after testing the bulk program code was a terrible race condition between read prefetching and the write loop. The prefetch logic incremented the internal address before data arrived. As a result, the new data would get written at the wrong address. Choosing the best solution to the problem is a matter of experimentation.

The “this won’t work because of that” and “what if this” turned into a series of exhausting thought experiments. I have been bugging Peter a lot in the past few days about a series of potential issues. Through tiring thought experimentation, we eventually agreed that the best way to proceed was to abstract a lot more through the API. This is a non-exhaustive list of the decisions we’ve made in the past week:

  • set_address() is hidden from the API
  • the internal address range is not exhausted once read or written
  • read and write operations must not be interdependent, the internal read and write pointers will be distinct (as a side effect, this change also eliminates the race condition depicted above)
  • set_address() + readn() turns into read(dev, where, n)
  • All API addresses begin at 0. The programmer translates that into an absolute address
  • new API call set_chip_size()
  • new API call to explicitly erase blocks or sectors (to be defined)
  • implicit erase on write can be enabled or disabled (to be defined)
  • implicit erase will erase the sector/block right before the first byte of the sector is written
  • exposing any USB specific dependencies in the API is strictly forbidden

My focus for the remainder of this week will be to shorten this list as much as possible. Once the dependency between read and write is unshackled, I will be able to erase/program/verify my faithful SST 49LF080A. From here, it will be a matter of finalizing and implementing the last obscure bits of the specification.

The state of QiProg for flashrom

As QiProg is still being finalized, implementing it as a flashrom programmer is still a long ways ahead. I do estimate that weeks 11 and 12 will provide ample time to integrate everything into flashrom, hopefully, in time for the 0.9.8 release.