Friday, October 9, 2015

Industrial I/O + CO2/VOC Sensors + I2C + Random Rants

Whoa long time since my last blog post so figured that it was the time to talk about a few own-time projects that I have been working on. These are probably the most non-sense embedded crap since my lightning sensor driver that got upstreamed... of course I live in Oregon where a lightning strike panics people :)

Anyone that knows me knows I like easy and fun projects that haven't been popped into a kernel driver. So when I spotted a few I2C sensors that allowed you to detect VOC and CO2 levels for indoors air quality readings, and no "drivers "existed outside of Arudino Sketch code or "userspace" "drivers".... I had to act to make these available to a real kernel implementation which within the Industrial I/O subsystem.

Now there is no chemical sensor framework that existed in IIO before these drivers so it required a few new datatypes to be added, and as well some new modifiers for the gas types (CO2, VOC, etc)

Some basic chemistry revisiting was required to remember what a VOC is for instance, which is pretty much any carbon molecule other than CO or CO2. However the EPA regulations don't define the important VOCs such as methane and ethane as such, and which are typically sensed as VOCs.

Now annoyingly these sensors have few design issues because they are designed as low sample rate devices (1HZ or less updates), and to be accessed via a microcontroller bit-banged I2C rather than a real I2C bus controller.

IIO Additions:

Several new IIO channel types and modifiers were needed for these sensors

  • IIO_CONCENTRATION - percentage of a substance (see modifiers below) in a given volume/solution/etc
  • IIO_RESISTANCE - meh just another channel available and inversely related to the VOC channel.. important for data integrity checks referenced below  
  • IIO_MOD_VOC - tVOC gas channel modifier
  • IIO_MOD_CO2 - CO2 gas channel modifier

Now all VOC and CO2 sensors report back in parts-per-million/billion so to be sane we convert it via the scale value to IIO_CONCENTRATION and let the userspace care if they want to swap it back to ppm/ppb.

Now to explain the I2C bit-banging issue... mainly these sensors may ask for a transaction start command and you have to I2C byte data off the bus... now if you are doing a I2C bitbanging you can do the non-spec allowed ADDRESS READ_BIT [BYTE 0 1 2 3 ... ] with these devices. However it ends up being byte reads like ADDRESS READ_BIT BYTE 0, ADDRESS READ_BIT BYTE 1, ADDRESS READ_BIT BYTE 2, etc for a real I2C bus...

Before anyone tells me about smbus/i2c block reads.. these will not work with these devices at all because they have no concept of them, and the byte written for the buffer size could damage the factory calibration data.

This causes a issue because the device can update the values between the milliseconds the scheduler gives someone else to run before the next I2C byte read, and with the VZ89 this update resets the data pointer within the IC.

SGX VZ89x Sensors:
  • Cheapest VOC/CO2 I2C capable sensors out there.
  • 400-2000 ppm CO2, and 0-1000 ppb VOC range
  • Initial development of the chemical part of the IIO subsystem was using this sensor.
  • Horrible I2C hacks needed for the rare update in a middle of a read.
    • Basically confirm the high byte of the IIO_RESISTANCE reading is 0 (which it is always per datasheet) and the VOC_short is 13 (after warmup it will be).  If you are in this state you return -EAGAIN, and the next reading is valid.
  • Staged for 4.4 hopefully! Already in linux-next!
Xively Hipster Apartment Feed -> http://personal.xively.com/feeds/1040475808

Normally QA/unit testing is my least favorite part of any project but for this it was pretty easy and fun (aka beer was involved).

  • Unit Test #1 - Drink a beer a blow on the sensor lightly (CO2 + VOC): PASS
  • Unit Test #2 - Put my lighter over the sensor with the flint removed (VOC): PASS
  • Unit Test #3 - Leave apartment to the bar to see if the levels normalize (CO2 + VOC): PASS


Monday, May 5, 2014

2014 Embedded Linux Conference Trip Report

This year I got to attend Embedded Linux Conference, present my Sigrok talk from ELCE, and be part of the Debugging half-day's panel session.

Quick report of what talks I found interesting, takeaways, and various thoughts.

April 29th - Conference Day One

USB and the Real World
Alan Ott - Signal 11 Software

Alan went into how USB can be odd based on device used, packet type + size, modes, and general weirdness can affect performance. USB is one of those things we all have to deal with and likely will for a long time.

Update on Boot Time Reduction Techniques, with Figures
Michael Opdenacker - Free Electrons

According to the Michael the bootup time performance hasn't improved much over the last few years with a ~8 second bootup time will be the fastest you can expect. Simple hacks like ripping out un-need drivers to avoid a useless driver probe() call, execute-in-place,  recycled "old data" on reboots, and reduced kernel sizes.

Userspace Drivers in  Linux - Pros, Cons, and Implementation Issues
Micheal Christofferson - ENEA

This talk I admittedly left a quarter the way in because it was blatantly the incorrect way to view writing a hardware level interface. Speaker was saying in as much words as "writing kernel level drivers is hard" and we shouldn't rule out using userspace for writing them. This is wrong on so many levels from userspace polling, being non-deterministic, and really creates another non-upstreamed API.

On a side note if I had known Greg Kroah-Hartman was in the audience I would have stuck around for his quips on how this is a horrible idea and any "performance" gains are whitewash for bad codes and losing determinism.

How to Build a Linux Based Robot
Michael Anderson - PTR Group

This talk went into how to use a Beaglebone Black/Raspberry Pi/Arduino for low cost robotics and RC applications.  He had a robotic demo driven by a BBB on technical showcase later in the night.

April 30th - Conference Day Two

Keynote: IoT and the Role of Embedded Linux and Android
Tim Bird - Sony, Karim Yaghmour - OperSys, Benjamin Jones - Alcatel-Lucent, Matt Porter - Linaro, and David Anders - CircuitCo

What I gathered from this keynote is everyone has a different sense of what the buzzword "The Internet of Things" means, and no general consensus outside of your toaster being wired up. Security will be a huge issue in the near term, and I look forward to using my SDR card to probe for weaknesses around my flat.

Linux for Microcontrollers: Spreading the Disease
Vitaly Wool - Softprise Consulting OU

Vitaly went into how it can be a challenge to deal with the space, loading, and computing issues with using Linux on a microcontroller.

Debugging - Linux Kernel Testing
Matt Porter - Linaro

Despite how the session was labeled this was a Birds of Feather that went into how the audience debugs their kernels. The short list of it all was from the almighty printk, JTAG debuggers (everyone loves the BDI2000/3000 still), unit tests like LTP + lmbench + bonnie++, and good old LEDs on pins.

Debugging - Hardware Debugging Tools
David Anders - CircuitCo

David was the first part of this half session with me. He described all the low level debugging techniques using JTAG, brief logic analyzers overview, and how to use various other hacks (LED on interrupt line), etc.

Debugging - Sigrok: Using Logic to Debug Logic
Matt Ranostay - Intel Open Source Technology Centre

This was my talk on introduction of the Sigrok project which allows you to break free of closed source and generally Windows-only logical analyzer/DSO/DMM software. Showed how you can use it on various devices, protocol decoding, and a simple demo of decoding SPI data outputted to a LED string driven by a Beaglebone.

Debugging Panel
Matt Ranostay - Intel Open Source Technology Centre, Matt Porter - Linaro, David Anders - CircuitCo, Karim Yaghmour - OperSys

This debugging panel again was more like a Birds of Feather, and the audience had a wide range of questions for the panelists (including me). Karim fields some Android debugging questions, David various JTAG + OpenOCD, Matt Porter a mix of hardware meets software, and mine were targeted at the Sigrok + DSO/DMM/LA field.

May 1st - Conference Day Three

Open-Source Tools for Software-Defined Radio on Multicore ARM+DSP
Philip Balister, OpenSDR

Nice overview of GnuRadio usage was in this talk which appealed to me since I recently got a USRP for getting more into SDR research.

Porting Linux to a New Architecture

Marta Rybczynska - Kalray

Like a colleague of mine said this one of the few times you wanted more marketing slides in a talk. Her presentation was a generic bringup on Linux but the processor from Kalray is 256 cores (not sure they all worked.. I suspected locking issues). Could have some major SDR processing potential!

What's going on with SPI
Mark Brown - Linaro
Not much to go into detail about this talk but it had a good overview of using SPI device with the Linux Kernel API and limitations.

Kernel USB Gadget Configfs Interface
Matt Porter - Linaro

Last talk of the day getting in the way of beer time.. I'm kidding mostly :P. But no Matt went into detail how to use functionfs to create composite USB gadgets dynamically. 

Monday, March 17, 2014

Open Lighting Architechure





Two BeagleBones driving two LED panels  at 140 fps, and the LED strip at 60 fps

Introduction

What is the Open Lighting Architecture project? Well basically it adds DMX over IP in a Open Source project. What is DMX you say? If you have been to any concert in the last 30 years you've seen DMX at work, and it is slightly younger than the MIDI standard still in use today.

DMX like MIDI is an serial connection which MIDI is RS-232 @ 31500 baud, DMX is RS-485 and runs at 250 kbps. DMX however has its own standard for marking the start of a lighting frame 513 slots (each slot is one byte), first slot is a command, and the 512 are data ones. However vendors may take more than slot as command if they choose.  These 513 slots are called a universe, and you can have multiple of these which is good for our use case of pure RGB or GRB values.

Now today pure DMX over RS-485 is getting rarer since UDP/IP is cheaper to setup and use.. and not to mention you can have DMX to TCP/IP convertors if need be.

Doing Networked DMX Cheap

In a previous post I showed BeagleBones driving LED panels at a high speed at mostly low CPU usage (about 20%).. other projects show 2% but they are hiding the real CPU hit with PRU stalls.. aka the wrong way to do it.

Now the OLA project supports all the major standards for DMX over IP.. I'll go into the few I've used
  • ArtNet - only 4 universes per IP is supported so it is useless for large light shows
  • e1.31 - up to 63999 universes per IP so you drive a large light show
Each 16x16 LED panels is a total of 256 LEDS which is GRB values so effectively 768 slots, and this will clearly not fit in one universe so we split each panel into two parts of 384 slots or 128 LEDs.

Last panel is the latch panel (aka all data gets written out for all panels when data is written here) and is shown in my last post.

Cheap BeagleBone Setup

DMX Protocape

The protocape above exposes the PRU pins unbuffered to the LED strips or panels. So be sure not to hit the +5V power line on the data line or you may burn out a pin. Buffering wouldn't hurt and probably would increase the actually framerate a bit but after the first WS28xx part it is at +5V anyway.
Universe Pin Mappings on Beaglebone Black/White:
  • 0 -> P8_45 (PRU1 R30_0)
  • 1 -> P8_46 (PRU1 R30_1)
  • 2 -> P8_43 (PRU1 R30_2)
  • 3 -> P8_44 (PRU1 R30_3)
  • 4 -> P8_41 (PRU1 R30_4)
  • 5 -> P8_42 (PRU1 R30_5)
  • 6 -> P8_39 (PRU1 R30_6)
  • 7 -> P8_40 (PRU1 R30_7)
  • 8 -> P8_27 (PRU1 R30_8)
  • 9 -> P8_29 (PRU1 R30_9)
  • 10 -> P8_28 (PRU1 R30_10)
  • 11 -> P8_30 (PRU1 R30_11) (clock line for WS2801)

Open Lighting Architecture Setup

Open Lighting Architecture has various plugins to control USB, SPI, and other propriety protocol devices.

However for the BeagleBone PRU applications we fake a SPIDEV device with ioctls so we can use the SPI plugin of OLA at run at a high speeds.  

Mainly you drive the OLA with external software over the network but you can use a few APIs locally or remotely. Like for instance my WS2801 strips are driven using the Python API for OLA, and it allows you generate raw DMX packets to be sent directly to OLA (not ArtNet or e1.31 but OLA wire protocol).

PixelController

PixelController driving two 16x16 WS2812 LED panels via e1.31

PixelController is a java application that generates awesome visuals that can export with the common DMX over IP protocols.

Taxes the hell out of your CPU and I suggest using ola_recorder on your device to record a given set sequence and play it back at a much lower CPU cost.

References

https://github.com/mranostay/ws28xx-lighting-pru
http://www.opendmx.net/index.php/Open_Lighting_Architecture
https://github.com/neophob/PixelController

Tuesday, December 24, 2013

Adventures in AM335x PRU Lighting

For those that don't know me I'm a big fan of the AM335x SoC series since it really allows you do anything you want professionally or hobby-wise.

Lately in my own-time I've been interested in high-end lighting systems and how I could do it better than the current projects that exist using the Beaglebone. Namely using ones the PRU the wrong way and touching the pinmux and not using the GPO/GPI exposed on the R30  + R31 registers.

Required ingredients for this all to work:
To begin we need to understand all the components that come together to make driving WS281x LEDS at 100 FPS and better.

Basically we have firmware that is loaded on the PRU cores 0 + 1 , and a slim kernel interface to talk to the output pins with WS281x LEDS.

Clocking for the WS281x chipset is slightly modified from the datasheet to allow syncing of high and low bits timing on the outputs.

low bit   -> 1.25 microseconds high (start sequence) + 1.25 microseconds low
high bit  -> 1.25 microseconds highs (start sequence) + 1.25 microseconds high
latch      -> 50+ microseconds low all outputs

Currently this firmware supports 256 RGB slots on 12 outputs for a total of 3072 LEDS... however if you use true DMX you'll need split the 256 LEDs into at least 2 DMX universes of no more than 170 LEDS each (3 x 170 = 510 slots + 2 bytes commands and padding).  The less LEDs driven overall from each output the fastest the frame rate can be.

First you need load the ws281x-pru0 and ws281x-pru1 binaries into /lib/firmware and run "echo BB-BONE-PRU-05 > /sys/devices/bone\_capemgr.\*/slots" to load the remoteproc firmware on both PRU cores. These come from building the ws28xx-lighting-pru project or getting the binaries located in the repository.

Two interfaces are exposed for controlling the LEDs first is the virtio-serial which is really low bandwidth and not a serial port interface (think no flow control or termios), but the second is a faux spidev interface which is high speed and allows using Open Lighting Architecture to control them.

Now you may say you can only run 3072 RGB LEDs (currently with the latest firmware, saving a little memory and a future alpha/white channel for another part selection) and LEDscape can drive 500 meters of WS2812 LEDS at 30 FPS (30k LEDS)... but isn't the full cost isn't the Beaglebone by far but having ~18 DMX universes with 170 RGB LEDS that are ran deterministically.

Now this is all fine but you want to something useful with this.. and here is where OLA + spidev comes into play.

root@pru:~$ opkg install
root@pru:~$ adduser ola
root@pru:~$ su ola

*write the following to ~/.ola/ola-spi.conf*
base_uid = 7a70:00000100
device_prefix = spidev
enabled = true
spidev0.0-0-dmx-address = 1
spidev0.0-0-personality = 1
spidev0.0-0-pixel-count = 128
spidev0.0-1-dmx-address = 1
spidev0.0-1-personality = 1
spidev0.0-1-pixel-count = 128
spidev0.0-backend = software
spidev0.0-ports = 2
spidev0.0-spi-ce-high = false
spidev0.0-spi-speed = 100000
spidev0.0-sync-port = 0

ola@pru:~$ olad -f
*now you can use the OLA web interface or the various language APIs*


Example of light show on 16x16 array with 2 universes of 128 LEDS each (384 slots per universe).



References:

Tuesday, October 29, 2013

2013 LinuxCon Europe + Embedded Linux Conference Europe Trip


So this year I got to attend LinuxCon EU and speak at the Embedded Linux Conference Europe, drink beer, eat haggis (which is so good the Customs agents will ask if you are carrying any when re-entering the US :)), see coworkers wearing kilts (you know who you are) and catch up with my European colleagues.

However this year's LinuxCon has a lot of cloud focus which personally being an embedded guy bores me easily, but however I attended a few interesting sessions.

Day one started with a few suits giving keynotes that really weren't interesting or useful, but Chris Aniszczyk gave a great keynote on scalability of the Twitter service and how they managed to offload high CPU bound tasks to the network stack. Reducing capital costs and devops costs greatly and maximizing the total utilization of the server cluster.

LinuxCon EU Day One Talks:


Jake Edge - Namespaces for Security

This talk went into depth about the various levels of container security and how can securely segment various tasks, network + mounts sharing between "master" and slave containers. Loosely this can be applied to "the Cloud" in a tenant application based segmentation.

Matthew Garrett - Exploring the Dustier Corners of System Firmware

Missed a good part of this talk due to a schedule shift for the keynotes + registration but what I caught was a good war story on how not to totally trust all you sent to the UEFI interface binary blob.

Lev Iserovich - Using Linux to Support a Specialized Computer

Lev explained an interesting setup of PowerPC core controlled by x86 server to do molecular research, and quite a few slides were above my head...


LinuxCon EU Day Two Talks:


Joao Paulo Rechi Vita - Bluetooth Smart Devices and Low Energy Support on Linux

Bluetooth Low Energy is the future for device communications that NFC simply cannot handle. Joao gave an overview how this stack functions within the kernel.

Ruth Suehle - Raspberry Pi: Getting Started and Creative Applications

Now before getting too harsh on this talk.. the author should disclose his great dislike for the Raspberry Pi platform.  Especially since all the fame seems to be targeted at this platform and the Beaglebone is mostly ignored..

My Luther's list of grievances:
  • Not Open Source Hardware at all... you can't even get gerbers or even the processor part in low volume..
    • Compared to the MinnowBoard or Beaglebone Black which you can get all parts in single part quantities
  • 90% of people that have one have said to me "Well it is only $35..", like that is valid reason to buy something. Save your money and get the Beaglebone Black for $10 more...
  • Binary blob loaded on the GPU is needed to even boot the damn thing...
  • Promotes horrible practices like bitbanging SPI and I2C through GPIOs
  • Want to hear the other 91 ones buy me a beer at the next conference and hear me rant :)
Ruth went into various cool things you could do with a RPI, various projects, and how you could violate FCC regulations (among pretty much everywhere except on the high seas) with one :).

My colleague Attila Kinali pointed out the FM radio broadcasting over a GPIO pin wasn't only illegal in the range it can reach (over 200 meters ), additionally frequency harmonics will totally take out any HAM radio nearby, and even worse interfere with pacemakers!

Somehow this got on the Maker magazine website as a project, and the moral of the story is don't trust everything you read that is legal. These FCC broadcast violations can add up to tens of thousands in fines...

There is a reason SDR cards cost $700-1500 with all those fancy passband filters...

Jonathan Corbet - The Kernel Report

Jonathan did his typical report on how the kernel is progressing with patchset velocity and functionally that has been added since his last talk.


LinuxCon EU Day Three Talks:


Dirk + Linus Show

Typical Dirk and Linus banter, and unless I read Linus wrong he hates embedded less than last year :).

Jacob Pan - Power Capping: Keeping Linux Within Power Limits Efficiently  

In-depth talk on how on using forced idle to both control thermals and power consumption on x86. However this could be applied to most architectures and in theory agnostic to the platform.

Sarah Sharp - OPW: Bringing Women into the Linux Kernel

Sharp discussed how important it is to bring a diverse crowd especially women into Linux, and how to make the community more open.

Three interns from the OPW program gave short presentations on what they were tasked with and accomplished.


Embedded Linux Conference Day One Talks:


Now ELC had a lot more interesting talks but in the shortened 2 day format resulted in 2-3 interesting talks in the same slots...

Chris Simmonds - Timeline for Embedded Linux 

Chris gave a tour back in time on how Linux has evolved in the embedded world from old phone like Zaurus, media players to modern day embedded systems including phones + tablets.

Darren Hart - How Not to Write x86 Platform Drivers

Darren gave a war story on how he got Minnowboard patches into upstream with the struggles of moer

Also went into the complex ACPI bindings that will be needed in the future for daughter-cards (aka lures) and mixture of current drivers than only support ACPI or DT data..

Russ Dill - Extending the swsusp Hibernation Framework to ARM

Russ detailed how the AM335x suspend support was implemented and gave a demo on a Beaglebone.
This included disk suspend, and low microamp ram suspend, and restoring everything from the bootloader.

Mark Rutland - Devicetree: The Disaster so Far

Mark proposed that device tree should be be treated as an API and changes to it in the future can be planned for and should be expected. This is sure to stir the kettle in the DT word since it adds yet another thing to worry about device trees being foward-compatible and could possible turn into the same issue with board files now...

Matt Ranostay (me!) - Sigrok: Using Logic to Debug Logic

My talk was brief introduction on what sigrok is and why you should care about this project and how the community could further its development.

sigrok (lower case is correct) allows the community to break free of horribly vendor closed and incompatible software for logic analyzers + digital oscilloscopes + multimeters.

Demoed a few simple use cases of sigrok and how the magic is in the protocol decoding, and device agnostic signal output.

My slides are up -> sigrok presentation talk

Sigrok Technical Showcase Booth

Later in the evening the sigrok gang (me + Joel Holdsworth + Bert Vermeulen) showed off the functionality using the suite of applications, and a simple trace + decoder demo in Pulseview.

Several people came up to booth expressing great interest in using sigrok and their horror stories of using closed vendor applications...


Embedded Linux Conference Days Two Talks:


This last day was a little more laid back with a ton of hallway sessions between old colleagues and attending their sessions.

Embedded Build Systems Panel - Tim Bird, Sony Mobile; Ross Burton, Intel; Thomas Petazzoni, Free Electrons; Karim Yaghmour, Opersys; Jeff Osier-Mixon, Intel (Moderator)

Keynote went into why everyone thought their buildsystem of choice was better than everyone elses... included some valid points on why one was worse or better than other, but more of political/pride reasons than anything else.

Some of the buildsystems discussed were:
  • Flavor-of-the-day ones at companies and their success or failure rates
  • Buildroot
  • Yocto Project's Poky
  • OpenEmbedded
  • Android's buildsystem

Pantelis Antoniou - Board File to Device Tree Migration: War Story

Everyone in the ARM world's favorite subject to hate or love. Personally I think device tree is so much cleaner than a "file" for every board and avoids recompiling the damn kernel everytime you add a peripheral.

Pantelis went into the dynamic aspects of DT which he has added with capebus as well the war stories of supporting the transition of board files to device tree.

Attila Kinali - Debugging Electronics for the Software Engineer

First talk I've attended of Attila's and for sure won't be my last. First off the slides had no text at all it was all graphical cues on what to discuss. His talking style was rather laid back, informative, and explained the various hardware debugging techniques for the software layman. Being the weird breed of understanding hw + sw rather well I still picked up a few pointers for hw design..

Also he gave a plug to the sigrok project and the Open Logic sniffer!

Thursday, August 8, 2013

Minnowboard SPI EEPROM UEFI Recovery

So lets say your UEFI upgrade goes horribly wrong... power outage... bad checksum... wanted to test if that "DO NOT POWER OFF" warning really wasn't lying... whatever... so how do you recover?

Your choices are either RMAing the board or order a DediProg SPI flasher (~$250) both of which can be costly and time consuming for the average hobbyist. Another option is you can prove to be the professional you are and dig out that BeagleBone and few breadboard cables.

Sidenote: The title should read any board with a DediProg header can be saved this way. But really important to pay attention to logic level of the SPI flash, since it can be 1v8, 3v3 (Beaglebone/Minnowboard IO logic level), or even 5v. But don't fret even in that case you can use a few cheap logic shifters (https://www.sparkfun.com/products/8745) since the BeagleBone header provides all those 3 common logic level voltages on the expansion headers.

Now the DediProg header on the Minnow is labeled J11 on the silkscreen (has PROG as well) which the pinout is as below. Additional note be sure the power supply is completely disconnected from the Minnowboard's barrel plug or you MAY LET out the magic smoke.




DediProg header
3V3 GND
CS (Chip Select) CLK (Clock)
MISO (Master In - Slave Out) MOSI (Master Out - Slave In)
NC DEDIPROG_IO3_N (tie to GND)


Now only listing the important pins on BeagleBone you'll need to connect up to the DediProg header.

Beaglebone Expansion Header
P9.1 GND -> GND
P9.2 GND -> DEDIPROG_IO3_N
P9.3 3V3 -> 3V3
P9.28 SPI1_CS -> CS
P9.29 SPI1_D0 -> MISO
P9.30 SPI1_D1 -> MOSI
P9.31 SPI1_CLK -> CLK



Now with everything hooked up accordingly run the following commands on the Beaglebone. This all assumes you have flashrom installed from source or a binary build.

Enabled SPIDEV SPI1 Device Tree overlay

bbb# echo BB-SPIDEV1 > /sys/devices/bone_capemgr.8/slots

Backing up UEFI before a upgrade attempt...

bbb# flashrom -p linux_spi:dev=/dev/spidev1.0 --read backup-uefi-spi.img
Calibrating delay loop... OK.
Found Winbond flash chip "W25Q32.V" (4096 kB, SPI) on linux_spi.
Reading flash... done. 


Writing a UEFI image to the device...

bbb# flashrom -p linux_spi:dev=/dev/spidev1.0 --write backup-uefi-spi.img
flashrom v0.9.6.1-r1705 on Linux 3.8.13-00702-g8ed5354 (armv7l)
flashrom is free software, get the source code at http://www.flashrom.org
Calibrating delay loop... OK.
Found Winbond flash chip "W25Q32.V" (4096 kB, SPI) on linux_spi.
Reading old flash chip contents... done.
Erasing and writing flash chip...
Erase/write done.
Verifying flash... VERIFIED.

Slight Update - 08/09/2013


My colleague +Darren Hart brought up a good point that if you are doing this from a non-backup UEFI image it will not have the EFI variable defined MAC address within the firmware(offset 0x3B7000 - 0x3B7005)...

Below I created a simple python script that allows you alter the MAC address within the UEFI firmware image. Note I haven't really tested this step by writing the altered image to a board but there is no reason it shouldn't work.


mranostay@flasher:~# cat mac_uefi.py
#!/usr/bin/env python

import sys
OFFSET = 0x3B7000

def usage():
    print "./mac_uefi.py [read|write] minnow.fd"
    sys.exit(0)

def dump_macaddr(file):
    with open(file) as f:
        f.seek(OFFSET)
        mac_data = f.read(6)

    mac_addr = ""
    for i in mac_data:
        mac_addr += hex(ord(i))[2:] + ":"

    print "MAC Address: " + mac_addr[:-1]

def get_mac_addr():
    data = raw_input("Enter MAC address from sticker on board (format 00:13:20:xx:xx:xx) : ")
    data = data.strip()
    data = data.split(":")

    if not len(data) == 6:
        return

    digits = []
    for i in data:
        number = int("0x" + i,16)
        if not number in range(256):
            return
        digits.append(chr(number))

    return digits

def write_mac_addr(mac_addr, file):
    global OFFSET

    with open(file, "rb") as f:
        data = f.read()

    with open(file, "wb") as f:
        process = data[:OFFSET]
        process += "".join(mac_addr)
        process += data[OFFSET + 6:]
        f.write(process)
         
     
def main():
    if not len(sys.argv) == 3:
        usage()


    if sys.argv[1] == "read":
        dump_macaddr(sys.argv[2])


    mac_addr = ""

    if sys.argv[1] == "write":
        while True:
            mac_addr = get_mac_addr()
            if mac_addr:
                write_mac_addr(mac_addr, sys.argv[2])
                break


if __name__ == '__main__':
    main()


mranostay@flasher:~# python mac_uefi.py read MINNOW.fd
MAC Address: ff:ff:ff:ff:ff:ff

mranostay@flasher:~# python mac_uefi.py write MINNOW.fd
Enter MAC address from sticker on board (format 00:13:20:xx:xx:xx) : 00:13:20:11:22:33

root@flasher:~# python mac_uefi.py read MINNOW.fd
MAC Address: 0:13:20:11:22:33