Pomera DM250 Tinkering
The KING JIM Pomera DM250 "digital typewriter" is a small Linux-powered ARM computer that boots up into a custom word processor application. I've been tinkering with it to try to get OpenBSD booted on it. I'd normally wait until the end and write up a proper article explaining everything, but this process is taking a lot longer than I expected so I figured I'd document it all as I go.

Table of Contents
Background
Click to expand
KING JIM has made a number of portable word processors starting with the DM5, the DM10 and DM20 with fold-out keyboards, then the DM100 and DM200 which share the form factor with its latest DM250.
I only know of KING JIM because stsp@ has their Portabook x86 machine that has required a handful of tweaks to get OpenBSD working on it.
The DM250 was only sold in Japan, but the manufacturer recently launched an Indiegogo campaign to launch a US version ("DM250US") with an ANSI keyboard layout and defaulting to English in the software (the Japanese model has English support in its software and can use the keyboard in English, though with its slightly different layout). I learned about this on the writerDeck subreddit which I subscribe to for some reason.
The unit measures 10.35" wide by 4.72" tall, with a height of 0.7" when closed. It has a 7" 1024x600 full-color TFT LCD screen, though the DM250's custom word processing software only uses black and white. It weighs 1.4 lbs and has a soft-touch rubber coating on its case. Its DM250US now has a US layout, though the arrow keys were unfortunately moved from an inverted "T" layout on the Japanese DM250 to a horizontal layout.
The DM250 is powered by a Rockchip RK3128 quad-core ARM Cortex-A7 processor with 1GB of RAM and about 8GB of eMMC storage. It has a full-size SD card slot and USB-C for charging. It has an AMPAK AP6236 Wi-Fi and Bluetooth SDIO chip which is based on the Broadcom BCM43436.
2025-03-14
I backed the Indiegogo campaign on February 19th and used Buyee to buy a Japanese model DM250 while I waited for the US campaign to end and for mine to ship out. The Japanese DM250 arrived on the 13th and with the aid of this website, I was able to boot into a Debian build and start inspecting how the device worked. I also took backups of the eMMC flash to be able to recover to it if I screw things up.
I haven't really been interested in the random armv7 boards that run OpenBSD because they all seemed to be similar while also each having quirks that make them unusable for daily use due to lacking driver support or cheap hardware. The DM250 appealed to me because it was a complete computer with keyboard and screen, not just a lone board with an ethernet port. (Although I'm sure I will eventually come up short on complete driver support on this machine too.)
It can turn on "instantly" due to some proprietary software called "LINEOWarp" which integrates into u-boot and the Linux kernel and basically hibernates the machine after booting and writes out its RAM to the eMMC. Upon opening the lid, u-boot directly reads the WARP image and loads it into RAM, bypassing the Linux kernel boot process. I first heard about this type of software from dosdude1's Honda infotainment video which has a similar need for "instant on".
2025-03-19
Trying to get OpenBSD loaded will require updating u-boot on the DM250 to a newer release with EFI support. EFI support was added in 2015 but the DM250 has a build from 2014.
But I can't really mess with u-boot until I get access to the UART on the device and I haven't been able to find the UART pins. I tried booting to Linux and printing random garbage to the serial port while I probed every pin on the board with my Saleae looking for serial data. For some reason nothing came out anywhere.
Eventually I found this page which shows where the UART pins are, which I definitely probed and found nothing while Debian was running. But once I kept leads on those pins while powering on, I could see u-boot output. Now I can actually see what's going on.
U-Boot 2014.10-RK3128-06 (Mar 17 2022 - 14:28:55)
CPU: rk3128
CPU's clock information:
arm pll = 816000000HZ
periph pll = 594000000HZ
ddr pll = 600000000HZ
codec pll = 400000000HZ
Board: Rockchip platform Board
Uboot as second level loader
DRAM: Found dram banks:1
Adding bank:0000000060000000(0000000040000000)
512 MiB
[...]
I'm not sure why u-boot shows 512 MB of RAM there when the DM250 has 1 GB,
especially when that bank
output shows a size of 0x40000000
(1,073,741,824
bytes).
2025-03-31
While trying to solder wires to the UART pins, I damaged one of the pads :/ The device still works otherwise so I'll just sell this one and wait for my US model to arrive.
I learned that Rockchip SoCs have a neat feature where if the firmware fails
to load a bootloader from eMMC or SDMMC, it will automatically launch into a
"MaskROM" mode
where it becomes a ugen
device over its USB-C cable and allows the attached
computer to directly read and write data to the eMMC.
This way the device can never really be bricked which makes me more confident
testing u-boot changes.
This MaskROM mode works even before SDRAM is initialized, so the first thing
that has to be done is sending it a RAM training blob, then a more complete
usbplug
blob which allows more complicated commands over USB.
This can be done with
rkflashtool
or
xrock
which both work on OpenBSD.
$ doas xrock maskrom rk3128_ddr_300MHz_v2.12.bin rk3128_usbplug_v2.63.bin
After uploading the blobs, the device detaches and reattaches into its USB loader mode:
ugen0 at uhub3 port 3 "vendor 0x2207 product 0x310c" rev 2.00/1.00 addr 9
ugen0 detached
ugen0 at uhub3 port 3 "RockChip USB-MSC" rev 2.00/1.00 addr 9
If the flashed u-boot does boot but it's broken, one can short the eMMC to
ground while the board is being powered on and force it into MaskROM mode.
On the DM250, this can be done by shorting TP501
to ground.
2025-04-02
My DM250US arrived. A quick teardown shows it's basically the same hardware but with a different version silkscreened.


The keyboard keys feel slightly smaller in size and rougher in texture. u-boot appears to be the same version but the build date is newer:
U-Boot 2014.10-RK3128-06 (Oct 07 2024 - 17:22:56)
The kernel is still Linux 3.10.0 with WARP patches. The DTB stored on the eMMC is mostly the same but with these additions:
bq27z558-battery@55 {
compatible = "ti,bq27z561";
reg = <0x55>;
gpios = <0x76 0x12 0x01 0x75 0x0d 0x01>;
status = "okay";
};
bq256xx-charger@6b {
compatible = "ti,bq25620";
reg = <0x6b>;
gpios = <0x76 0x11 0x01>;
ti,watchdog-timeout-ms = <0x00>;
charge-current-limit-microamp = <0x2bf200>;
charge-voltage-limit-microvolt = <0x408b70>;
input-current-limit-microamp = <0x2dc6c0>;
minimal-system-voltage-microvolt = "\0.c";
pre-charge-control-microamp = <0x8d9a0>;
termination-control-microamp = <0x249f0>;
ti,no-thermistor = <0x01>;
status = "okay";
};
2025-04-03
I got this pogo-pin clip from Adafruit to access the UART pins without having to solder to them and potentially damage them again. It's definitely made it much easier to reliably access the UART across multiple reboots.
2025-04-14
I've been trying to get different u-boot trees compiling and booting but none
were working except the
one from KING JIM.
I tried
rockchip-linux/u-boot
and
linux-rockchip/u-boot-rockchip
but neither boot (or at least don't output anything to uart1
.
Geniatech
make the
XPI-3128
which is basically the
rk3128-evb
evaluation board that exists in u-boot.
While digging around their
documentation,
I found
this huge tarball
that includes a snapshot of their u-boot tree which is based on newer 2017.09
and has most of the necessary Rockchip drivers.
I'm not sure why Rockchip is so special that they can't do everything in the
official upstream u-boot treeā¦
With a few changes to build with a newer gcc, setting CONFIG_DEBUG_UART_BASE
to 0x20064000
(uart1
instead of uart2
), adding some
custom uart initialization
code
to arch/arm/mach-rockchip/rk3128/rk3128.c
, and adding an rk3128-specific
timer driver, I now have a working build of u-boot that has EFI support!
U-Boot 2017.09-g5d36672-dirty (Apr 12 2025 - 12:31:04 -0500)
Model: KING JIM Pomera DM250US
DRAM: 512 MiB
Sysmem: init
Relocation Offset: 00000000, fdt: 00000000
Using default environment
dwmmc@10214000: 1, dwmmc@1021c000: 0
mmc_init: err -110, timer:41969
switch to partitions #0, OK
mmc0(part 0) is current device
Bootdev: mmc 0
MMC0: High Speed, 52Mhz
PartType: RKPARM
rockchip_get_boot_mode: Could not found misc partition
boot mode: normal
Found DTB in resource part
DTB: rk-kernel.dtb
CLK: (uboot. arm: enter 600000 KHz, init 600000 KHz, kernel 0N/A)
apll 600000 KHz
dpll 600000 KHz
cpll 400000 KHz
gpll 594000 KHz
armclk 600000 KHz
aclk_cpu 148500 KHz
hclk_cpu 74250 KHz
pclk_cpu 74250 KHz
aclk_peri 148500 KHz
hclk_peri 74250 KHz
pclk_peri 74250 KHz
=> mmcinfo
Device: dwmmc@1021c000
Manufacturer ID: 11
OEM: 100
Name: 008GB
Timing Interface: High Speed
Tran Speed: 52000000
Rd Block Len: 512
MMC version 5.1
High Capacity: Yes
Capacity: 7.3 GiB
Bus Width: 8-bit
Erase Group Size: 512 KiB
HC WP Group Size: 4 MiB
User Capacity: 7.3 GiB WRREL
Boot Capacity: 4 MiB ENH
RPMB Capacity: 4 MiB ENH
=> bootefi
bootefi - Boots an EFI payload from memory
Usage:
bootefi <image address> [fdt address]
- boot EFI payload stored at address <image address>.
If specified, the device tree located at <fdt address> gets
exposed as EFI configuration table.
Unfortunately only the eMMC (dwmmc@1021c000
) is working but the probe of the
SDMMC device at dwmmc@10214000
times out.
This means I can't see an inserted SD card and begin to boot OpenBSD's EFI
loader.
I think this has to do with the device not being powered up at boot. I'm still trying to figure out what is required for this to work since it works in other older Rockchip-specific u-boot trees.
2025-04-14 (Evening)
Success!
U-Boot 2017.09-gcc6b241-dirty (Apr 14 2025 - 17:20:37 -0500)
Model: KING JIM Pomera DM250US
DRAM: 512 MiB
Sysmem: init
Relocation Offset: 00000000, fdt: 00000000
Using default environment
dwmmc@10214000: 1, dwmmc@1021c000: 0
RKPARM: Invalid parameter part table
switch to partitions #0, OK
mmc1 is current device
switch to partitions #0, OK
mmc0(part 0) is current device
Bootdev: mmc 0
MMC0: High Speed, 52Mhz
PartType: RKPARM
rockchip_get_boot_mode: Could not found misc partition
boot mode: normal
Found DTB in resource part
DTB: rk-kernel.dtb
In: serial
Out: serial
Err: serial
CLK: (uboot. arm: enter 600000 KHz, init 600000 KHz, kernel 0N/A)
apll 600000 KHz
dpll 600000 KHz
cpll 400000 KHz
gpll 594000 KHz
armclk 600000 KHz
aclk_cpu 148500 KHz
hclk_cpu 74250 KHz
pclk_cpu 74250 KHz
aclk_peri 148500 KHz
hclk_peri 74250 KHz
pclk_peri 74250 KHz
=> setenv fdtfile rk3128-pomera-dm250us.dtb
=> load mmc 1 ${kernel_addr_r} efi/boot/bootarm.efi
reading efi/boot/bootarm.efi
119296 bytes read in 51 ms (2.2 MiB/s)
=> bootefi ${kernel_addr_r} ${fdt_addr_r}
## Starting EFI application at 62008000 ...
FtlInit fffffffe
Scanning disk nandc@10500000.blk...
rkparm_init_param_from_storage param read fail
RKPARM: Invalid parameter part table
Scanning disk dwmmc@10214000.blk...
Scanning disk dwmmc@1021c000.blk...
Scanning disk rksdmmc@1021c000.blk...
rkparm_init_param_from_storage param read fail
RKPARM: Invalid parameter part table
Scanning disk rksdmmc@10214000.blk...
rkparm_init_param_from_storage param read fail
RKPARM: Invalid parameter part table
Scanning disk rksdmmc@10218000.blk...
rkparm_init_param_from_storage param read fail
RKPARM: Invalid parameter part table
Found 6 disks
Adding bank: 0x60000000 - 0x80000000 (size: 0x20000000)
disks: sd0* sd1 sd2 sd3 sd4 sd5 sd6 sd7 sd8 sd9 sd10 sd11 sd12 sd13 sd14 sd15 sd16 sd17 sd18 sd19 sd20 sd21 sd22 sd23 sd24 sd25 sd26 sd27 sd28 sd29 sd30
>> OpenBSD/armv7 BOOTARM 1.23
boot>
cannot open sd0a:/etc/random.seed: No such file or directory
booting sd0a:/bsd: 2411324+767888+11506208+484492 [188357+107+388448+214048]=0x0
I added some debug printf
s to the working u-boot tree and saw that it was
calling
rk_iomux_config(RK_UART2_IOMUX)
when initializing the storage.
That ends up calling
rk_uart_iomux_config()
which does some magic writes to the IOMUX.
Reading the
GRF documentation
and other pieces of code, I learned that GPIO1B needs pins 12 and 14 enabled to
activate mmc0_pwren
and mmc0_cmd
, and GPIO1C needs pins 0, 2, 4, 6, 8, and
10 enabled to change them from JTAG and UART2 pins to those needed for eMMC.
With that, the SD card is recognized and u-boot can read files from it with its
built-in FAT filesystem support.
The existing config on the eMMC splits up the single drive into many different
partitions like kernel
, warp
, ro_data
, etc., which each show up as
separate disks to the EFI loader.
The EFI loader is read from the SD card and loaded into memory with load mmc 1
${kernel_addr_r} efi/boot/bootarm.efi
, and then executed with bootefi
${kernel_addr_r} ${fdt_addr_r}
.
OpenBSD's BOOTARM.EFI loads successfully and can list files on the SD card and
start reading and booting bsd.rd
.
Unfortunately it goes off into lala land there so I'm not sure what it's doing,
but at least now I can move on to the OpenBSD part of this bringup.