"Porting" Coreboot to the Piesia N-Box T2
I got my hands on a couple of Piesia N-Box T2 mini-PC’s from a scrap pile.
They’re pretty cool little passively-cooled PC’s equipped with an Intel J1900 quad core processor (Bay Trail platform) running at 1.9 GHz, one slot of DDR3L memory, four gigabit ethernet ports and two mini-PCIe slots. One of the mini-PCIe slots is SATA-only, meant for the SSD, and the other one is PCIe-only with the SIM slot routed to it for a cellular modem. Pictures of the motherboard PCB are at the bottom of the article.
Since they were an unplanned acquisition then I had a bit of a hammer-in-need-of-a-nail situtation on my hands — mini PC’s aplenty, but no real use for them. Seeing as I like computers and free software then porting coreboot to the Piesia board seemed like a fun little side project. That way I’d have an almost-FOSS computer1 for future projects requiring a mini-PC.
I haven’t worked with x86/AMD64 firmware before, but the Bay Trail platform seems to be already supported by coreboot, so hopefully I can stand on the shoulders of giants and get something up and running.
I started writing this post back in February, but then personal life got in the way and the post was left sitting unfinished. Now, in October, I have some time again and decided to finish it. I’ll re-trace my steps on the latest coreboot branch, so hopefully I’ll manage to cover all of the steps I took without omitting anything important.
Prerequisites
Before getting myself into the coreboot code I checked whether I could even reasonably flash and debug the BIOS on this board.
Debugging the board looks to be easy, as it is reasonable to expect that the RJ45 port labeled COM
is a serial port.
The only problem is that I don’t have a RJ45-USB serial converter on hand, so I’ll have to order2 that and wait for a couple of weeks for delivery.
To figure out whether I could flash it I removed the mini-PC’s motherboard from its case and looked around for a flash chip.
On the underside of the PCB I could spot a Winbond W25Q64 flash.
Taking a look at its datasheet shows that it’s a 1.8V 64M-BIT SERIAL FLASH MEMORY WITH DUAL/QUAD SPI & QPI
.
Whether it has dual or quad SPI (or even the size) doesn’t really matter to us at this point, but we absolutely do care about the operating voltage.
Luckily I had a CH341A programmer with a 1.8 V level shifter attachment and the excellent flashrom
software supports that, so we’re all set on that front.
Getting started with coreboot
Building the coreboot image was pretty straightforward following the coreboot tutorial. Living on the edge and being lazy, I skipped step 3 (“Build the coreboot toolchain”) and decided to use the compiler from my distribution’s repositories to compile coreboot, which seemed to work out fine in my case.
I looked through the coreboot repository and found a very similar mainboard already supported, the Bostentech GBYT43.
Going by the mainboard source code, it looks to be very similar to the Piesia board I have. The Bostentech one has a different SuperIO chip, IT8728f, but the Piesia’s IT8613e is also already supported by coreboot, so that shouldn’t be a problem.
I copied the GBYT4 mainboard sources to src/mainboard/piesia/nm19ne4l
,
changed all references to gbyt4
to nm19ne41
,
changed the SuperIO chip from it8728f
to it8613e
and compiled it.
I’m not sure how much changes are required to the devicetree or GPIO maps, but I decided to flash the resulting build and run it on real hardware. After all, I have a whole bunch of these mini-PC’s, won’t be a huge loss if one should fry itself :-).
Flashing the coreboot build with the following command4:
$ flashrom --programmer ch341a_spi -l flashrom.layout -i bios -w build/coreboot.rom
gave me the following output on the serial port:
[NOTE ] coreboot-25.09-62-g560917478634 Sat Oct 04 04:09:40 UTC 2025 x86_32 bootblock starting (log level: 7)...
[DEBUG] FMAP: Found "FLASH" version 1.1 at 0x350000.
[DEBUG] FMAP: base = 0x0 size = 0x800000 #areas = 5
[DEBUG] FMAP: area COREBOOT found @ 350200 (4914688 bytes)
[INFO ] CBFS: mcache @0xfe002e00 built for 15 files, used 0x314 of 0x4000 bytes
[INFO ] CBFS: Found 'fallback/romstage' @0x330c0 size 0x64d8 in mcache @0xfe002e5c
[DEBUG] BS: bootblock times (exec / console): total (unknown) / 45 ms
[NOTE ] coreboot-25.09-62-g560917478634 Sat Oct 04 04:09:40 UTC 2025 x86_32 romstage starting (log level: 7)...
[DEBUG] Enabling VR PS2 mode: VNN VCC
[DEBUG] pm1_sts: 8100 pm1_en: 0000 pm1_cnt: 00000000
[DEBUG] gpe0_sts: 00000000 gpe0_en: 00000000 tco_sts: 00000000
[DEBUG] prsts: 05130900 gen_pmcon1: 00045079 gen_pmcon2: 00000200
[DEBUG] prev_sleep_state = S5
[DEBUG] FMAP: area RW_MRC_CACHE found @ 300000 (65536 bytes)
[NOTE ] MRC: no data in 'RW_MRC_CACHE'
[DEBUG] No MRC cache found.
[DEBUG] FMAP: area COREBOOT found @ 350200 (4914688 bytes)
[WARN ] CBFS: 'mrc.bin' not found.
[DEBUG] Couldn't find mrc.bin
[DEBUG] Romstage handoff structure not added!
[DEBUG] SMM Memory Map
[DEBUG] SMRAM : 0x0 0x800000
[DEBUG] Subregion 0: 0x0 0x700000
[DEBUG] Subregion 1: 0x700000 0x100000
[DEBUG] Subregion 2: 0x800000 0x0
[ERROR] Couldn't add var_mtrr_ctx setup in cbmem.
[EMERG] Unable to initialize postcar frame.
Cool!
Looks like it didn’t fry itself and even starts to boot but doesn’t get into SeaBIOS due to something called the mrc.bin
missing.
Obtaining the mrc.bin mrc.elf
It turns out that you need to add the memory reference code blob (mrc.bin
) into the coreboot image.
The memory reference code blob is used to initialize the memory and it seems like that’s required to boot up the motherboard.
Coreboot has a short document regarding mrc.bin for the Haswell platform, but there’s an additional nuance for the Bay Trail platform.
First you’ll have to find a Chromebook that uses the same platform as you have.
You can look it up from the Developer Information for ChromeOS Devices.
Since I have a Bay Trail processor then I’ll use the banjo
codename 5.
After that you can use that codename as the crosfirmware
argument to download the correct image:
make -C util/cbfstool
cd util/chromeos
./crosfirmware.sh banjo # Put your codename here
../cbfstool/cbfstool coreboot-*.bin extract -f mrc.bin -n mrc.bin -r RO_SECTION
After running the cbfstool extract command you should be presented with the following output and find a file named mrc.bin
in your working directory:
Found file mrc.bin at 0x18efc0, type spd, compressed 70168, size 70168
Now’s the part that took me some time: you should confirm whether you have an ELF file or just a plain blob.
$ file mrc.bin
mrc.bin: ELF 32-bit LSB executable, Intel i386, version 1 (SYSV), statically linked, stripped
In my case it was an ELF file and thus should be renamed to mrc.elf
before passing it to the coreboot build system.
This was a bit tricky to figure out and I spent quite some time on figuring out why the ripped MRC code didn’t work. I finally got a hint when I researched previous coreboot work on the plaform and read this coreboot blog post about libgfxinit on Bay Trail:
This binary is simply called “MRC binary” or mrc.bin (the file’s name). However, it is actually an ELF binary, and the Makefile in coreboot will place it at a different offset depending on the file extension. So, Bay Trail has a mrc.elf instead: using the mrc.bin name will place the binary at the wrong offset, and won’t work.
Now that the MRC blob has been identified and renamed to mrc.elf
we can configure coreboot to use it by going into menuconfig, enabling Chipset -> Add a System Agent binary
and entering the filename into Chipset -> Intel System Agent path and filename
.
Running the coreboot build with the mrc.elf
embedded resulted in:
[NOTE ] coreboot-25.09-62-g560917478634 Sat Oct 04 04:09:40 UTC 2025 x86_32 bootblock starting (log level: 7)...
[DEBUG] FMAP: Found "FLASH" version 1.1 at 0x350000.
[DEBUG] FMAP: base = 0x0 size = 0x800000 #areas = 5
[DEBUG] FMAP: area COREBOOT found @ 350200 (4914688 bytes)
[INFO ] CBFS: mcache @0xfe002e00 built for 16 files, used 0x354 of 0x4000 bytes
[INFO ] CBFS: Found 'fallback/romstage' @0x330c0 size 0x64d8 in mcache @0xfe002e5c
[DEBUG] BS: bootblock times (exec / console): total (unknown) / 45 ms
[NOTE ] coreboot-25.09-62-g560917478634 Sat Oct 04 04:09:40 UTC 2025 x86_32 romstage starting (log level: 7)...
[DEBUG] Enabling VR PS2 mode: VNN VCC
[DEBUG] pm1_sts: 8100 pm1_en: 0000 pm1_cnt: 00000000
[DEBUG] gpe0_sts: 00000000 gpe0_en: 00000000 tco_sts: 00000000
[DEBUG] prsts: 05130900 gen_pmcon1: 00045079 gen_pmcon2: 00000200
[DEBUG] prev_sleep_state = S5
[DEBUG] FMAP: area RW_MRC_CACHE found @ 300000 (65536 bytes)
[DEBUG] FMAP: area COREBOOT found @ 350200 (4914688 bytes)
[INFO ] CBFS: Found 'mrc.bin' @0x44edc0 size 0x11218 in mcache @0xfe0030d0
[DEBUG] SMBus controller enabled
BayTrail-MD MRC wrapper v5
C1.D0: SPD not present.
[many lines omitted]
Turning on vga text mode console
SeaBIOS (version rel-1.17.0-0-gb52ca86e)
PCI: XHCI at 00:14.0 (mmio 0xfd9f0000)
XHCI init: regs @ 0xfd9f0000, 7 ports, 32 slots, 32 byte contexts
XHCI protocol USB 2.00, 6 ports (offset 1), def 3018
XHCI protocol USB 3.00, 1 ports (offset 7), def 1000
XHCI extcap 0xc1 @ 0xfd9f8040
XHCI extcap 0xc0 @ 0xfd9f8070
XHCI extcap 0x1 @ 0xfd9f8460
XHCI extcap 0xa @ 0xfd9f8480
EHCI init on dev 00:1d.0 (regs=0xfd9ea020)
WARNING - Timeout at i8042_flush:71!
AHCI controller at 00:13.0, iobase 0xfd9eb000, irq 0
Searching bootorder for: HALT
Found 0 lpt ports
Found 1 serial ports
Searching bootorder for: /pci@i0cf8/*@13/drive@0/disk@0
AHCI/0: Set transfer mode to UDMA-6
Searching bios-geometry for: /pci@i0cf8/*@13/drive@0/disk@0
AHCI/0: registering: "AHCI/0: FORESEE 32GB SSD ATA-10 Hard-Disk (30533 MiBytes)"
XHCI no devices found
Initialized USB HUB (0 ports used)
All threads complete.
Scan for option roms
Press ESC for boot menu.
[GRUB logs omitted]
Nice! It looks like it boots up fine but, while I can see what’s going on in the serial console, there’s no display output on the HDMI port.
Getting graphics output
After some digging into the coreboot code I discovered that the Intel GPU initialization code the Bay Trail platform seems to be copied from the Intel GMA driver, with the added change that runtime configuration of the int15 handler has been removed and the driver defaults to eDP output.
This meant that I had to change the boot display device hook handler in src/soc/intel/baytrail/int15.c
to configure the HDMI output to be the boot device:
static int int15_handler(void)
{
[...]
switch (X86_AX) {
[...]
case 0x5f35:
/*
* Boot Display Device Hook:
* bit 0 = CRT
* bit 1 = TV
* bit 2 = EFP (HDMI)
* bit 3 = LFP (eDP)*
* bit 4 = CRT2
* bit 5 = TV2
* bit 6 = EFP2
* bit 7 = LFP2
*/
[...]
// X86_CX = 0x0008; // Default, for eDP
X86_CX = 0x0004; // Bit 2 set, for HDMI
res = 1;
break;
[...]
}
}
Finally! After that the board boots up fine and has display output.
There are some warnings in BIOS about the kernel’s PCI driver being unable to claim BAR mappings due to the lack of a compatible bridge window, but everything I’ve tested seems to work just fine:
- CPU didn’t fry itself running at load;
- All NIC’s work;
- Serial port works (the RJ45 labeled
COM
on the case); - HDMI displays graphics output;
- USB ports work;
- Power and disk access LEDs light up as expected;
- Bottom fan header spins the fan;
- Power and reset button do what they’re supposed to.
Just for future reference, I haven’t tested:
- eMMC (not populated on any of my boards);
- Audio input/output;
- GPIOs;
- Top fan header (didn’t have anything to plug into it);
- Anything related to the motherboard pin jumpable pin headers.
I’d guess that these Bay Trail mini PC’s are probably built on some Intel reference design, so the the “porting” process was more about figuring out the badly communicated expectations of coreboot, rather than writing any code :-). That was a lot easier than I expected.
Originally the word “porting” in the title of this post was not in quotes, but I quoted it after looking back at it and realizing there really wasn’t much besides looking through forums, source code and documentation that I had to do.
This mainboard doesn’t seem like something worth contributing, so I’ll just distribute the patch file here in case someone wants to take a look at it:
Download the patch file for Piesia N-Box T2 mainboard.
Just for future reference this post was written running coreboot commit 5609174786343b9c76e40dcc6d0d6575f28935ff
.
Weird hand-written characters on the CPU
One of the units didn’t show any signs of life. Given that the computers were from a scrap heap then that was expected. But what was unexpected for me was the hand-written text on top of the dead mini-PC’s CPU.
I have no idea what this says.
Motherboard PCB images
For anyone curious who wants to know how this board looks like then I’ve taken pictures of the motherboard from both sides.
-
Yes, I know that the final coreboot binary contains non-free Intel blobs. No point in letting perfect get in the way of good :). ↩︎
-
If you’re in a hurry then you could of course make your own RJ45 serial cable, but that would’ve been unfun busywork. ↩︎
-
The only references to this GBYT4 motherboard I could find were from the coreboot project. So I guess that it’s a similar mini-PC with the name on the motherboard, but listed on Alibaba with titles similar to “fanless industrial mini pc Intel”. ↩︎
-
I’m not sure what went wrong, but flashrom’s IFD detection mechanism seemed not to work for me and gave me errors about image size not matching the region size. So I had to resort to using a re-touched layout file. ↩︎
-
The decision to use
banjo
instead oframbi
was mostly random. I’m not familiar with the differences in memory reference codes between different codenames. ↩︎