Friday, December 13, 2019

rust, oxide, corrosion,....


Miguel de Icaza (@migueldeicaza)
All of us writing C and C++ are living on borrowed time.

The only safe future is Rust.

Prepare your code to go out of scope.
 
inspired me last night to share some of the EDKII Rust work underway. I filed https://bugzilla.tianocore.org/show_bug.cgi?id=2367 to motivate the posting of
https://github.com/tianocore/edk2-staging/tree/edkii-rust.

Within this package you can find https://github.com/tianocore/edk2-staging/tree/edkii-rust/RustPkg which includes https://github.com/tianocore/edk2-staging/tree/edkii-rust/RustPkg/MdeModulePkg/Universal/CapsulePei 
as an example of using Rust to build an EDKII capability. The idea is not to fork-lift upgrade the entire 1 million LOC EDKII upstream to Rust but instead to migrate critical flows and libraries to a safer language. The capsule example is especially important since the capsule is an attacker controlled data object and the parsing flows are quite complicated https://github.com/tianocore-docs/Docs/raw/master/White_Papers/A_Tour_Beyond_BIOS_Capsule_Update_and_Recovery_in_EDK_II.pdf. The UEFI PI modularity of PEIM's and DXE drivers, along with the language interop of the FFI of Rust to other languages, naturally lend themselves to this evolutionary approach.

And listening to folks like Alex https://hardwear.io/berlin-2020/training/hunting-uefi-firmware-implants.php reminds me of the value of assurance. Thanks Alex for the discussion on language-based-security, including Ada/Spark discussion. It also reminded me of my conversation with Aucsmith in DC http://vzimmer.blogspot.com/2018/09/.

Also interesting to see other plays on "Rust" in the market, such as 'oxide'
https://oxide.computer/blog/introducing-the-oxide-computer-company/
or my favorite 'corrode' https://github.com/jameysharp/corrode for converting C code to Rust. It'll be interesting to see usage of Rust for Oxide's firmware endeavors.

When I look at the above EDKII Rust work, I ask myself if it's a 'sustaining evolution' or 'disruptive innovation' https://online.campbellsville.edu/business/sustaining-innovation-vs-disruptive-innovation/.
Specifically, do examples of disruptive innovations regarding Rust and firmware include things like https://www.ics.uci.edu/~aburtsev/doc/redleaf-hotos19.pdf  with formal or https://github.com/oreboot/oreboot with all Rust and no blobs?

Interesting times.

I try to not to rewind the history machine, but I invariably find myself assessing my engagement with system software during pivots like this. Specifically, when I started working full time I joined a time chartered with writing firmware for a remote telemetry unit (RTU). It was essentially an embedded computer that would be strapped to a gas pipeline to control valves, measure gas flow, etc. It was IOT before IOT was vogue.

My first team requested that I write the code for an 8051 microcontroller in assembly. I asked for requirements and then requested purchase of a C compiler. I was able to produce the features in C and evolve quite readily with the ever changing requirements. Over time I bounced back to assembly for some severely resource constrained usages, but C has become my language of choice.

And worse I was afflicted by large legacy assembly code bases with rich algorithmic capability. For example, there was a PCI resource allocator written in assembly that had down bottom-to-top allocation based upon a specific hardware requirement. When the next generation design required top-to-bottom, the schedule became imperiled by having to rework thousands of lines of assembly to unwind this assumption. Although C doesn't necessarily yield 'better code'', it proved much easier to factor than assembly.

So C has made sense for development efficiency, but the last couple of decades have posed other challenges, such as making assurance claims. Modula-2 never made it https://cseweb.ucsd.edu/~savage/papers/Sosp95.pdf mainstream, nor has C# for OS's https://en.wikipedia.org/wiki/Singularity_(operating_system). And I've already mentioned my own less-than-successful earlier investigations into type safety for firmware http://vzimmer.blogspot.com/2016/12/provisioning-porting-and-types.html.

So nearly 30 years onward I'm happy to have another language transition, namely a assembly-to-C moment with C-to-Rust change.

Thursday, December 5, 2019

10 years on and a small exercise in package dependencies

This post marks the 10th anniversary of my first blog posting https://vzimmer.blogspot.com/2009/12/good-reading-on-firmware-uefi.html. It also represents the 80th post.

Since a blog entry whose sole purpose would be to designate this milestone might not be so, er, 'interesting', let's add a little meat to this posting. Specifically, lets talk about package dependencies in the EDKII project. This is an interesting exercise since a large, package-based project might be daunting to new-comers trying to discern relationship among components. Correspondingly, long-term participants in the project working on refining the implementation, such as cleaning up packages to be more independent and maintainable (aka paying down technical debt) might find a higher level view interesting.

To help in these various causes, below is a recipe for generating dependency graphs across the packages. The steps include:

0. Clone https://github.com/tianocore/edk2 locally
1. Install graphviz from http://www.graphviz.org/
2. Go to the edk2 root
3. Run the following command in Windows shell:
     findstr /S /R /N /C:"^ *[^ #]*\.dec$" *.inf > all_packages.dot
4. Open the file all_packages.dot with an editor with regular expression support, such as https://notepad-plus-plus.org/, and perform a text replacement like below:
    Replace: ^([^\\]+)\\.+: *(.+\.dec)
    With: "\1/\1.dec" -> "\2"
5. Add the following text around replaced text in the all_packages.dot file:

      strict digraph PackageDependency {
           graph [rankdir=TB];
           node [fontsize=9,shape=box];
           edge [arrowhead=vee,arrowsize=0.5,style=dashed];
      …
      …
      }

6. Run the following command in Windows shell:
      graphviz\bin\dot.exe -Tsvg all_packages.dot -Oall_packages.svg

Below is a sample output of this exercise.



So what?

This is an interesting exercise since it shows the strong dependency most EDKII packages have on the MdePkg at the bottom, which is the package containing generic interfaces and library classes. Not surprisingly, the second most leveraged package is the MdeModulePkg, which is the generic set of implementations based upon interfaces in the MdePkg. It's also useful to discover if there are any circular dependencies, such as between the ArmPkg and the embeddedPkg. And finally, it shows opportunities for clean up, such as removing the dependency of the NetworkPkg upon the ShellPkg. The latter is based upon the existence of some network-related shell commands that should really rely upon API definitions of the MdePkg instead of instances in the NetworkPkg.