Despite vaguely reading the opposite, it is possible to truncate the ME region to the last byte that me_cleaner left untouched. This (on my image) freed about 4 MiB of flash – combined with the fact that coreboot’s default size is 1 MiB (when the region is 3 MiB wide) meant that I now have 7 meg of space to screw around with in CBFS.

Here’s how:

Preparation

Dump the rom

Run me_cleaner on the rom

Use ifdtool to extract the individual regions

ifdtool -x <image>

Truncation

Find the last relevant byte

Hexdump will automatically hide large sections of 0xFF – use hexdump on the ME region file:

hexdump <me_region>

Here you can see the last relevant line starts with 0x00dbef0 – therefore the last byte is 0x00dbeff.

Truncate the ME region file

We can use dd to truncate the file – but first we need to convert the hex value into a decimal number. Use your calculator of choice (google in my case). For 0x00dbeff it’s 900863

dd if=x220_me.bin of=x220_me_trunc.bin bs=1 count=900864

Just double check the size using ls:

-rw-r--r-- 1 nroach44 nroach44 900864 Jan 24 15:50 x220_me_trunc.bin

Adjust the Firmware Descriptor

We’ve shrunk the ME region, but we need to inform the chipset that the BIOS region can be bigger.

You need to edit it so that the ME region ends earlier. The file is simply

<Start address>:<End address> <region type>

So, we need to change the end address for the ME region, and the start address of the BIOS region.

The ME end address needs to be 0x3000 with 0xDBEFF added – so again using your calculator of choice, this comes to 0xDEEFF.

The BIOS start address needs to be one more than that – so 0xDEF00.

Note: The end addresses should end in 3 Fs, and starts should end in 3 0s – https://github.com/corna/me_cleaner/issues/20 – You’ll need to ensure that your addresses comply with this rule. This means the start address of the BIOS region should be one more than the new end address of the ME region

IFDTool will spit out some info that you should sanity check, and also warn you that the ME region is shrinking, this is the whole point.

Then extract the new descriptor:

ifdtool -x <full image>

Build coreboot again

Use the new descriptor that you just extracted, and the truncate ME region file in your coreboot config.

You will also need to adjust the CBFS_SIZE option – this can be the size of the BIOS region – you shouldn’t need to do any maths here for padding or overhead. I simply just used 0x700000 as it was easier, but you should be able to just use the whole size. So that would be 0x7fffff – 0xDF000 = 0x720FFF

Flash the image and reboot – you shouldn’t have any issue with the ME forcing a reboot after 30 minutes.

Addendum

Using the 1.5MiB image from the coreboot wiki (thanks github/u/alegru here) it is possible to shrink the region down to ~300KiB:

Introduction

Background

I have a 2006 Mazda 3. It’s a nice car, but the more I learnt about the 3 I get ever so slightly more annoyed with Mazda Australia. There’s multiple things that the car “supports” but wasn’t sold with in Australia.

One of them (and the easiest of which to enable) is DIS – Driver Information System.

DIS lives on the left side of the LCD above the radio – it’s the clock by default. It can display the following:

Current Fuel Consumption (Averaged over the last few seconds)

Average Fuel Consumption

Average Speed

Remaining Distance (based on fuel in tank and average consumption)

There’s an official way to enable this – Hold down a few buttons, turn the key, and it’s on [1]! Unfortunately this only works for a few 3s, and not the base trims, or the later 2006 models (BKs2).

So if you can’t follow that guide, or are curious to see how it works I’ll explain how that button combination turns it on.

Theory

The Mazda 3 uses a CAN bus – this is a network not unlike a conventional computer network (think blue cables) but with a few differences:

It’s a bus – there’s no “Hub” or “Switch” – every device on the network is directly connected to each other via a common set of wires. Shorting this bus will stop any device from talking to another.

There’s no “Source” or “Destination” – only an ID, a flag or two, the data, and then a checksum.

The Mazda 3 has two of these buses – one is the “High Speed” bus for the Engine, ABS, Traction Control, Transmission, and Instrument Cluster computers, and the other is the “Medium Speed” bus in the cabin, for the LCD, Radio, Body Control (BCM – door locks, windows etc), Climate Control, and Instrument Cluster computers. The Instrument Cluster will pass some messages from the Engine network into the Cabin network, and may also do some passing the other way.

I’m pretty sure that the DIS is controlled either in the BCM or Instrument Cluster. Regardless, when you are holding down the Buttons, the Radio sends a message onto the Cabin network, and that somehow tells both the LCD and something else that DIS is now on. (from my testing this setting is not stored in the screen, as the screen does not seem to have any permanent memory and forgets everything on power loss, but I can’t see any other message responding to the button press)

Messages sent regarding DIS

From both a combination of reading Madox’s handy reference [2] and using my home made Arduino CAN tool [3] I was able to figure out the following messages relating to DIS and the screen:

0x28F: A formatting and misc message for the screen, sets locations of colons and commas, does the CD/ST etc fixed segments on the screen. Also is the state of the buttons on the face of the Radio.

0x290: The first 7 characters of the LCD

0x291: The last 5 characters of the LCD (depending on the other values, it might be possible to implement scrolling)

0x400: The trip computer data above. Funnily enough this data is present regardless of the state of DIS.

0x401: Beeps emitted by either the Radio or LCD for the Radio to beep through the main speakers.

When you’re holding down CD and AM/FM, the expected combination of bits are flagged in 0x28F’s fifth byte (as in, bit-wise the correct bits are 1 while the buttons are being held). However, after the time out occurs, this byte switches to the DIS byte:

0x28F:128, 0, 0, 0, 32, 0, 0, 0 #Radio Face Idle

0x28F:128, 0, 0, 0, 160, 0, 0, 0 #DIS ENABLE

The Radio then writes the “DIS ON” message to the LCD, with 0x290 and 0x291

The LCD responds with an 0x401 message for the beep.

DIS is now enabled. As you can see, I’ve not found any evidence that the LCD and something else communicate during this process, so I presume that the LCD and BCM/Cluster both read the DIS ON message, and the BCM/Cluster remembers and tells the LCD when necessary.

The SET and CLOCK keys are similar with SET being 0x28F[4] = 40 (+8) and CLOCK being 0x28F[4] = 48 (+16)

The key is however, that the “Radio Face Idle” message MUST BE SENT AFTERWARDS – as these buttons are held to reset the clock/DIS, they only trigger off the release (falling edge) of the button.

Final Notes:

If the original Radio did not permit you to enable DIS through the button trick, the Radio will continue to block DIS usage until ACC power is turned off, and the Radio is removed. Probably something about the initial 0x28F message.

The MS CAN bus is easily accessible by pushing breadboard cables into purpose designed holes on the harness-side plug for the LCD.

There’s a nice little hole above/behind the centre vents that you can stash your micro, if you wish to leave it there permanently. You can run a USB cable down behind the LCD, Radio and HVAC controls, and then out through the cigarette ash holder to allow easy debugging.

You can switch the units used on DIS by using the following method:

Enter test mode on the Instrument Cluster (Hold the Trip reset button, and then switch the key to ON)

Press the trip button until the IC LCD is on page “60” and is showing “DIS”

Hold SET to switch the modes (It depends on which page you are on – just hold SET for ~5 seconds per page until the units switch)