19 KiB
+++ title = "BC-Zero - Board Testing" summary = "From an old mining board to a console and AI server" date = "2026-11-08"
tags = ["BC-250", "PS5", "Unlock", "BIOS", "CPU", "GPU"] categories = ["Projects"] series = ["BC-Zero"] series_order = 1 +++
On February 5th, Soffio, a friend and fellow LUGMan member, made me discover a peculiar board: the BC-250.
The BC-250 is a board that comes from an ASRock cryptocurrency mining rig, which housed twelve of them.
Inside each of these boards there's a binned chip derived from the AMD APU of the PlayStation 5, with 6 of the 8 CPU cores and 24 of the 36 GPU CUs enabled, along with 16GB of GDDR6 RAM unified between CPU and GPU, an M.2 slot (PCIe 2.0x2 or SATA III), and just a few ports: two USB 2.0, two USB 3.0, one Gigabit Ethernet, and one DisplayPort. Power is supplied through an 8-pin PCIe connector.
At first I wasn't really convinced, especially seeing a third of the CUs cut off and knowing that it's a board with a custom, partially locked chip (on top of the locked cores, some features like video encoding/decoding are missing), coming from cryptocurrency mining and with no support or community behind it. But the price was definitely interesting, and apparently this board has a very active community that works hard to squeeze 100% of its potential out of it on Linux.
Things changed when, on the morning of May 30th, I got this message:
And good old Soffio also pointed out that the AliExpress sales were about to start. Intrigued by the whole thing, I asked him if he could lend me his board for a few days, just to try it out and see what could be done.
And oh boy, did this board convince me.
Step 0: Preparation
One downside of the BC-250 is that it's not exactly plug-and-play. At the very least, you need to:
- Find a power supply that can really deliver at least 300W on the +12V rail, with cables that can handle all those amperes;
- Have a monitor with DisplayPort (or buy an adapter);
- Find a way to cool the damn thing;
- Flash the BIOS.
My test setup was:
- The first "el cheapo" power supply I could find lying around (which "will surely be fine, it says 500W");
- A passive DP ➜ HDMI adapter;
- A portable air conditioner for cooling (it was summer and it was starting to get hot);
- A CH341 SPI programmer (which I already had).
Not exactly the best setup for testing the board, but you work with what you have.
Step 1: Flashing the BIOS
The first step in the community documentation is flashing the BIOS. Without a custom BIOS you don't get essential features like dynamic VRAM allocation (remember, the 16GB of RAM are shared) and proper fan control.
At first I installed the one recommended by the guide, the one by TuxThePenguin0, but later on I discovered another BIOS, the one by Forbidden Darkness, which, on top of unlocking the dynamic allocation menu, offers a selection of custom splash images and, most importantly, unlocks all 8 CPU cores.
"Wait, weren't they locked down?" Apparently not enough.
The APU has all cores on the silicon, they're just disabled via firmware. A similar principle also applies to the GPU CUs, but we'll get to that later.
The installation is even simpler and doesn't require a BIOS flasher: just copy
the files from the .7z archive in the releases to a USB stick formatted in
FAT32 and boot from it. The installer asks which splash image we want (the
07
is the best one, imho) and proceeds with the flashing.
{{< alert icon="triangle-exclamation" cardColor="#e6d237" iconColor="#1d3557" textColor="#1d3557" >}} Flashing the BIOS is a dangerous operation. Make sure the board doesn't turn off. {{< /alert >}}
Once the flashing is done, you need to reset all the BIOS settings. To do that,
just unplug the power and bridge pin 2 and 3 of the CLRCMOS1 header for a few
seconds. Once that's done, we can put the header back on pins 1 and 2 and plug
the power back in. By entering the BIOS with the Del key at boot we'll see a
lot more options.
First, let's make the VRAM allocation automatic. To do that, we need to go to
Chipset > GFX Configuration > GFX Configuration and set Integrated Graphics Controller to Forces, then UMA Mode to UMA_SPECIFIED, and
finally UMA Frame buffer size to 512M.
Then in NB Configuration disable the IOMMU (it doesn't seem to work on this
board).
Finally, we enable all the cores by going to Advanced > MeiMeiDXEv3 Menu and
enabling everything.
{{< alert icon="triangle-exclamation" cardColor="#e6d237" iconColor="#1d3557" textColor="#1d3557" >}} There's no guarantee that all the cores will work. Damaged cores could cause sudden crashes.
To avoid that, we'll run a stress test on all the cores and check that no
Machine Check Exception shows up in the kernel logs before enabling this
setting in production.
{{< /alert >}}
Once the BIOS is properly configured, we're ready to install an operating system and test this board for real.
Step 2: Installing a OS for testing
To do some CPU stress testing and run some tests on the GPU, I'll install Arch Linux.
It won't be the final distro I'll install, but the choice isn't random: development for this board is bleeding-edge, and for now almost all the scripts assume you're running Arch or Fedora, so you have the latest package versions.
Testing the 8 cores
First of all, let's test whether all 8 cores work as they should. To do that,
install the stress-ng package and run a stress test:
stress-ng --cpu 16 --cpu-method all --verify --timeout 2h --metrics
Then we check that there were no errors with:
sudo dmesg | grep -iE "mce|machine check|hardware error"
If the kernel doesn't report any errors, we've just gone from 6 to 8 cores for free. If there is an error you can change which cores to enable from the BIOS.
Stress-testing the GPU
Next, let's stress test the GPU to get a performance baseline before installing the governor or enabling all the CUs. To do that, I installed Furmark and ran the 1080p test.
I'd say 70 FPS isn't that bad for the board out-of-the-box, but we can definitely do better, much better.
A small note I feel I should add: if during the stress test the screen goes black and the board doesn't respond in any way, check your power supply. The little foreshadowing I did in step 0 about the power supply is because during my tests I ran Ollama and completely fried the PSU since (apparently) it couldn't really handle the whole load on the +12V rail. I then bought the PSU recommended by the community on AliExpress, along with the board, the Metalfish 500W FlexATX, and I haven't had any problems since.
Installing the GPU Governor
By default the GPU always runs at 1500MHz: a governor lets you raise the clock when the GPU is under load and lower it when it isn't, to save power.
We'll install cyan-skillfish-governor-smu, a community project that talks
directly to the board's System Management Unit. It's also already packaged in
the AUR, so to install it you just need to run:
paru -S cyan-skillfish-governor-smu
systemctl enable --now cyan-skillfish-governor-smu
We can check that it works with:
$ cat /sys/class/drm/card1/device/pp_dpm_sclk # If it doesn't work, try card0
0: 1000Mhz *
1: 1500Mhz
2: 2000Mhz
The first and last lines are, respectively, the minimum and maximum GPU frequency, while the middle line can change. The asterisk marks the frequency currently in use. An example under load:
$ cat /sys/class/drm/card1/device/pp_dpm_sclk
0: 1000Mhz
1: 1850Mhz *
2: 2000Mhz
We should see the GPU automatically use a higher frequency under load and a lower one when idle.
Small note: unlocking the 8 cores affects how the SMU values are read. It's a known issue and we'll fix it later on, when we'll deal with the operating system. Without any fix, the frequency values are wrong, for example:
$ cat /sys/class/drm/card1/device/pp_dpm_sclk
0: 1000Mhz *
1: 4575Mhz
2: 2000Mhz
# Not a bad overclock for a chip that tops out at 2230MHz
With that said, let's run a stress test now, with the governor installed.
Now that we can scale up to 1850MHz, our GPU manages to reach 83 FPS at 1080p, not bad!
1850MHz is by no means the most this chip can handle, but for now we'll settle
for it. For the curious, the frequency and voltage curves are fully customizable
and live in /etc/cyan-skillfish-governor-smu/config.toml. With a bit of trial
and error you can push the hardware to its limits while minimizing power draw,
but we'll do that when we set up the final operating system.
Unlocking the 40 CUs
As we said at the beginning, this board only exposes 24 CUs to the kernel, even though the PS5 has 36 and there are actually 40 on the silicon. We can verify this with:
$ sudo dmesg | grep active_cu_number
[ 6.882856] amdgpu 0000:01:00.0: SE 2, SH per SE 2, CU per SH 10, active_cu_number 24
To test and then unlock all the CUs, we'll use duggasco's repository. The mechanism is similar to the core unlock: here too you just need to change a few values, because the CUs aren't locked at the hardware level, they're just disabled by the firmware.
Two registers in the GPU decide how many CUs are active. What this script does
is patch the amdgpu driver and write the right values into those registers
while the driver starts up, waking up the disabled CUs.
$ git clone https://github.com/duggasco/bc250-40cu-unlock.git
$ cd bc250-40cu-unlock/
$ sudo pacman -S linux-headers vulkan-headers
$ sudo scripts/bc250-enable-40cu-arch.sh build
# Wait for the `amdgpu` module to be recompiled
$ sudo scripts/bc250-enable-40cu-arch.sh enable
Once the BC-250 has rebooted, we can check that the patch worked using the same command as before:
$ sudo dmesg | grep active_cu_number
[ 8.004012] amdgpu 0000:01:00.0: SE 2, SH per SE 2, CU per SH 10, active_cu_number 24
Apparently the script doesn't load the custom module automatically. That's not a problem: let's regenerate the initramfs and reboot manually:
$ sudo mkinitcpio -P
$ reboot
# Once it has rebooted
$ sudo dmesg | grep active_cu_number
[ 8.058999] amdgpu 0000:01:00.0: SE 2, SH per SE 2, CU per SH 10, active_cu_number 40
Much better!
Once the custom module is installed, we can move on to testing the CUs:
$ sudo scripts/bc250-cu-health-test.sh start
During the test the PC will automatically reboot twenty times. Once the PC stops rebooting on its own, we can see the test results with:
$ scripts/cu_map.sh
BC-250 CU Map + Health
SE0 SH0: ■■■■■■■■■■
SE0 SH1: ■■■■■■■■■■
SE1 SH0: ■■■■■■■■■■
SE1 SH1: ■■■■■■■■■■
40/40 CUs active, 0 harvested
BC-250 CU Map + Health
SE0 SH0: ■■■■■■✓✓✓✓
SE0 SH1: ■■■■■■✓✓✓✓
SE1 SH0: ■■■■■■✓✓✓✓
SE1 SH1: ■■■■■■✓✓✓✓
40/40 CUs usable (0 defective, masked)
Apparently I won the silicon lottery and have 8 cores and 40 working CUs. Hurray! 🎉
If there had been any defective CUs I could have masked them using the
bc250-cu-mask.sh script.
Running the last stress test with Furmark:
We went from the bare board, without any additional software, running at an average of 70 FPS, to having a governor and all the CUs unlocked, with peaks of 138 FPS, twice as much!
Of course, this approach to unlocking the 40 CUs has a pretty obvious problem, especially on rolling distributions like Arch: you have to recompile the module every time you update the kernel. This is another problem we'll solve later on, when we stop using a test OS, but if after an update the GPU isn't as fast as before, it might be worth taking a look.
Sensors and Other Essential Configurations
Once the essentials like CPU and GPU are sorted out, there are still a few small things to take care of, such as sensor management, fans, swap, VRAM split, etc...
I could go on about it for hours, but I'll point you to the community documentation, which is very thorough.
What I'd like to do now is point out one thing: using the sensors command, we
get very little data OOTB:
$ sensors
amdgpu-pci-0100
Adapter: PCI adapter
vddgfx: 799.00 mV
vddnb: 799.00 mV
edge: +39.0°C
PPT: 41.41 W (avg = 40.85 W)
sclk: 1000 MHz
k10temp-pci-00c3
Adapter: PCI adapter
Tctl: +41.6°C
To get more data we need the nct6683 module (read-only) or nct6687 (you can
create custom curves with it, but it's out of tree). Since nct6683 is
already available, we can enable it with:
$ echo 'options nct6683 force=true' | sudo tee /etc/modprobe.d/sensors.conf
$ echo 'nct6683' | sudo tee /etc/modules-load.d/99-sensors.conf
$ sudo mkinitcpio -P
$ reboot
After rebooting we'll see a lot more data:
$ sensors
k10temp-pci-00c3
Adapter: PCI adapter
Tctl: +46.9°C
amdgpu-pci-0100
Adapter: PCI adapter
vddgfx: 799.00 mV
vddnb: 799.00 mV
edge: +41.0°C
PPT: 42.61 W (avg = 40.75 W)
sclk: 1000 MHz
nct6686-isa-0a20
Adapter: ISA adapter
VIN0: 800.00 mV (min = +0.00 V, max = +0.00 V)
VIN1: 1.01 V (min = +0.00 V, max = +0.00 V)
VIN2: 992.00 mV (min = +0.00 V, max = +0.00 V)
VIN6: 1.39 V (min = +0.00 V, max = +0.00 V)
VIN7: 800.00 mV (min = +0.00 V, max = +0.00 V)
VIN16: 896.00 mV (min = +0.00 V, max = +0.00 V)
fan1: 0 RPM (min = 0 RPM)
fan2: 1709 RPM (min = 0 RPM)
fan3: 0 RPM (min = 0 RPM)
fan4: 0 RPM (min = 0 RPM)
fan5: 0 RPM (min = 0 RPM)
AMD TSI Addr 98h: +47.0°C (low = +0.0°C)
(high = +0.0°C, hyst = +0.0°C)
(crit = +0.0°C) sensor = AMD AMDSI
Thermistor 14: +37.0°C (low = +0.0°C)
(high = +0.0°C, hyst = +0.0°C)
(crit = +0.0°C) sensor = thermistor
Thermistor 15: +37.0°C (low = +0.0°C)
(high = +0.0°C, hyst = +0.0°C)
(crit = +0.0°C) sensor = thermistor
pwm1: 64%
pwm2: 64%
pwm3: 64%
pwm4: 64%
pwm5: 64%
intrusion0: OK
beep_enable: disabled
Step 3: Hardware Mods
I want to remind you that for all these tests I was using Soffio's BC-250, just to see whether it was something I'd be interested in. And since I found myself pretty hooked I decided to get everything I needed from AliExpress.
Luckily with the sales and also using TopCashback I managed to bring home everything I needed for less than €200. I then bought a couple of Arctic P12 Pros from Amazon.
Everything arrived on June 24th, so it was time to get to work on:
- Replacing the thermal paste and pads;
- Installing heatsinks on the back panel, to cool the GDDR6;
- Removing the metal bracket and the I/O shield (they're only needed if the board is mounted in the rig);
- Re-running the test suite mentioned above to see if I had won the silicon lottery a second time (luckily I did);
- Modding the heatsink.
The heatsink mod let me solve one of the problems I was having with the board: how do I get rid of 200W of heat? So far I had the portable AC, but I couldn't keep using a heat pump to cool a single board.
When they're in the mining rig, the BC-250 all have their heatsinks laid out lengthwise, so a single array of fans is enough to cool all 12 boards at once. If you want to use one of these boards on its own, you need to get a bit more creative to get rid of the heat.
The most common solution in the community is the heatsink mod, which consists of literally cutting open the heatsink in the section above the APU to make room for a fan.
It's a somewhat long and tedious job, but it's not impossible to do. It's also a pretty repetitive task, so once you get the hang of it, it goes by farely quickly. In the end all it took was a pair of scissors, some good music, and an hour of my time.
It's a bit rough around the edges (literally), but it works. And the hole is big exactly as a 120mm fan, so one of the two fans can blow directly onto the APU.
Since this article has gotten pretty long, I've decided to split it into multiple parts. In the next one, we'll design a custom case for my needs.















