Full Width [alt+shift+f] Shortcuts [alt+shift+k]
Sign Up [alt+shift+s] Log In [alt+shift+l]
1

On AI

from joshua stein [alt+shift+b] in technology

In 2019, I started watching Andreas Kling's programming videos, many of which were live-coding sessions writing his new operating system Serenity OS. He was always pretty fast at writing code, especially since his IDE, Qt Creator, had knowledge of all his C++ code and could auto-complete classes, variable names, and function signatures. Back then it seemed like he had much of the code written in his head and was limited just by his typing speed. Four years later, he switched to CLion which had early GitHub Copilot support for AI-assisted code completion. While initially skeptical of Copilot, he experimented with it and within months, Copilot was writing code blocks, "reading [his] mind", and writing whole functions. His IDE's auto-completion through AI seemed like it had finally caught up with his brain and he could get ideas out into code faster. While I found it fascinating watching Andreas speed up his development, none of it appealed to me for my work for years after. I didn't even use an IDE or an LSP in my editor. I was skeptical of AI and probably wrote it off too soon due to its early failures. I eventually tinkered with Claude in a web browser, asking it questions that I would have otherwise asked a search engine and been directed to a Stack Overflow answer. Once Claude Code came out, I was amazed at the power of giving it access to a directory of code on my laptop and letting it directly read and modify files. Its ability to completely (and quickly) reverse engineer a binary blob with zero context is still pretty awesome. Once local models got good and small enough, I started using Ollama on my M4 Mac Mini to do local offline work. Like many things, it's possible to like and use a technology, language, or tool while rejecting all of the hype, fraud, and negative communities that build up around them (like Rails, or Rust). Of course, you can also choose not to like or use any of those things. You can prefer to use a hand saw instead of a circular saw, or to...
23rd Jul 2026

Stay updated

Get a weekly newsletter with the top 5 articles worth reading every week.

More from joshua stein

Amend 4.0 Released

Amend 4.0 has been released: amend-4.0.sit (StuffIt 3 archive, includes source code and THINK C 5 project file) c838ee34931c00c03869affe7f9d6b85c0bbc51dd1242d11e8682a3774fdd0e3 SHA1: 040059d0b3302f1bd6ec0207b9a2f12dccdda374 Changes in this version: New repository format that tracks author e-mail in addition to name; existing repositories are migrated automatically on open Add inregrated resource file support; .rsrc files can be added directly to a repo and files are converted to DeRez-style ASCII output before diffing, so running SADerez to produce separate .r files on every change is no longer required Allow Command+. to cancel loading a repo Allow Command+. to cancel diffing; if diff text has already been output it will remain available, otherwise the window will be closed Center settings dialog, make sure author name is present Use database transactions to avoid leaving repository database files in a partially-committed state if we crash Numerous bug fixes

3 weeks ago • 1 votes
Installing OpenBSD on the Pomera DM250{,XY?}

These are some notes for getting OpenBSD-current running on the Japanese-model Pomera DM250, DM250X, and DM250XY. Table of Contents Top Throat-clearing Making a backup Some DM250 hardware notes Making an OpenBSD installation SD card Installing OpenBSD Post-Installation Building a custom installation ramdisk Throat-clearing Much of my work has not yet been committed upstream so installation currently requires a custom kernel and U-Boot image which are provided here. OpenBSD support is still improving and may not be stable at any given time. Install at your own risk. These risks include: If the battery completely drains due to a software bug, the device may not power on correctly and will not be able to recharge its battery (see below). If the device cannot boot properly into U-Boot, you may need to recover it through a USB cable which may also require having to open the device (see recovery). Note: Do not use these instructions for the US-model DM250US yet. That device has a different power charging chip and keyboard layout. Making a backup This is optional but recommended. The tools and instructions at EKESETE.net should be used to make a full eMMC backup before doing anything. Some DM250 hardware notes The DM250's factory U-Boot detects Right Shift + Left Alt being pressed immediately after power-on and boots the recovery Linux kernel from its recovery_kernel partition instead of its normal kernel partition. The recovery kernel boots the initramfs image at the recovery_boot partition which mounts the SD card and executes any _sdboot.sh script found at its root directory. If you hold Shift + Alt too long at power-on, it will instead boot its graphical factory hardware test program. The recovery kernel and script do not show any output on the console while they boot and run. Hold down Right Shift + Left Alt + Power and count 3 seconds, then let go and it should boot the recovery kernel and _sdboot.sh from the SD card. Once the new U-Boot image is written to the eMMC (even before going through the OpenBSD installer), the DM250 will no longer be able to boot the original Linux kernel or recovery. You'll need to boot something via EFI to write the backup U-Boot image to eMMC to get back to the factory software. This can be done with the OpenBSD installation SD card created here by dropping to a shell. The DM250 will not fully power off with a USB-C cable connected to power (even with the factory Linux software). This means even if you halt -p and it powers itself off, it will immediately power back on. My U-Boot detects if the lid is closed when it first boots and if it's closed, it will halt the boot process so it doesn't boot into OpenBSD while it's closed on your desk trying to charge (though it will still be powered up to U-Boot). A working battery is required to be able to provide enough power even with a USB-C cable connected. If the battery is completely drained, it may not be able to boot up far enough to get to U-Boot for it to be able to tell the charging chip to go into a higher charge mode. By default it does a trickle charge but because it will always try to power on as soon as it has power connected, it may quickly drain the power it just added to the battery trying to boot. In short, don't let the battery drain completely. Making an OpenBSD installation SD card It is possible to install OpenBSD to the installation SD card and boot from it so the factory Linux software remains on the eMMC. It will run a bit slower (it runs slow even on the eMMC) and you will still need to write the new U-Boot image to eMMC, but you can easily revert back to the original U-Boot to resume booting Linux at a later time. These instructions assume you're running OpenBSD (any architecture). You'll need an SD card of a few GB, which is assumed to be sd1 here. Format an SD card with a GPT partition layout, making an EFI partition of at least 100MB and giving the rest to an OpenBSD partition. # fdisk -ygb 204800 sd1 # echo -e "a\n\n\n\n\nw\nx" | disklabel -E sd1 # newfs /dev/rsd1a # newfs_msdos /dev/rsd1i # mount /dev/sd1i /mnt U-Boot and OpenBSD will use that EFI partition as its firmware partition, but the original Pomera recovery software will see it as a normal MSDOS partition and run the /_sdboot.sh script contained on it. Fetch the standard OpenBSD armv7 EFI bootloader to the SD card's EFI partition as /efi/boot/BOOTARM.EFI. # mkdir -p /mnt/efi/boot # cd /mnt/efi/boot # ftp https://cdn.openbsd.org/pub/OpenBSD/snapshots/armv7/{BOOTARM.EFI,SHA256.sig} # signify -C -x SHA256.sig BOOTARM.EFI Fetch my uboot.img to the EFI partition as /uboot.img. This U-Boot image has an embedded copy of the binary device-tree built from my Linux tree for the DM250 (JP). # cd /mnt # ftp https://jcs.org/dm250/uboot.img Fetch this installation script to the EFI partition as /_sdboot.sh. This will get executed by the factory recovery partition's boot system once the DM250 is booted into recovery mode. The script mounts the EFI partition of the SD card, backs up all of the firmware files from the eMMC to the SD card, makes a backup of the current eMMC U-Boot partition to the SD card, and then writes the new U-Boot image from the SD card to the eMMC. # ftp https://jcs.org/dm250/_sdboot.sh Switch to the OpenBSD partition of the SD card and fetch the latest OpenBSD armv7 snapshot disk images to it. # cd / # umount /mnt # mount /dev/sd1a /mnt # cd /mnt # ftp https://cdn.openbsd.org/pub/OpenBSD/snapshots/armv7/{SHA256.sig,base79.tgz,comp79.tgz,game79.tgz,man79.tgz,xbase79.tgz,xfont79.tgz,xserv79.tgz,xshare79.tgz} # signify -C -x SHA256.sig *.tgz Fetch the current bwfm firmware so you can have working Wi-Fi after installation. # ftp http://firmware.openbsd.org/firmware/snapshots/{SHA256.sig,bwfm-firmware-20200316.1.3p5.tgz} # signify -C -x SHA256.sig bwfm-firmware-* Fetch my bsd.rd ramdisk image and bsd kernel. # ftp https://jcs.org/dm250/bsd{,.rd} Your SD card is now ready to go. Unmount it. # cd / # umount /mnt Installing OpenBSD Insert the prepped SD card into the DM250. If it's plugged into power, unplug it. If it's powered up, power it down. Hold down the Right Shift + Left Alt + Power buttons. As soon as the Pomera logo displays, wait about two seconds and let go. The Pomera logo will clear and the recovery kernel should now boot. It will execute the _sdboot.sh script on the SD card which will make a backup of the existing U-Boot partition to the SD card and write the new one. Nothing will be shown on the screen while it's working but it should only take about 30 seconds. Once it's done, it will reboot the device. Note that in OpenBSD, the default keyboard layout matches the Japanese keyboard on the DM250 so things like @ and * are not where they are on a US keyboard. At this point it will boot the new U-Boot with EFI support and video and keyboard drivers for the DM250. If it detected the eMMC and SD card properly, it will boot the OpenBSD EFI bootloader. No EFI variables loaded Loading Boot0000 'mmc 0' failed Booting: Label: mmc 1 Device path: /VenHw(...)/SD(1)/SD(0) disks: sd0* sd1 >> OpenBSD/armv7 BOOTARM 1.23 boot> Enter b bsd.rd to boot the installer. boot> b bsd.rd cannot open sd0a:/etc/random.seed: No such file or directory booting sd0a:bsd.rd: ... When prompted for the root disk, enter ? to see which is which. The eMMC should be sd1 showing 7.3G. Note: When installing to the eMMC, you'll need to manually setup the GPT partition table putting the EFI partition after ~16MB or so to leave room for U-Boot. This will not be needed in the future once the installer is able to recognize the DM250. Press Control + Z to get to a shell so you can manually fdisk. Use (W)hole disk or (E)dit the MBR? [whole] ^Z [1] + Suspended /install # cd /dev # sh MAKEDEV sd1 # fdisk -e -g sd1 Do you wish to write the new GPT? [n] y Writing GPT. Enter 'help' for information sd1: 1> Edit partition 0 which was auto-created, changing it to an ef partition at offset 32768 with size 8192. sd1: 1> e 0 #: type [ start: size ] ------------------------------------------------------------------------ 0: OpenBSD [ 64: 15269791 ] Partition id ('0' to disable) [01 - FF, <uuid>]: [A6] ef Partition offset [34 - 15269854]: [64] 32768 Partition size [1 - 15237087]: [15237087] 8192 Partition name: [OpenBSD Area] EFI sd1*: 1> Now create partition 1 as an OpenBSD (a6) type with the rest of the space. sd1*: 1> e 1 #: type [ start: size ] ------------------------------------------------------------------------ 1: Unused [ 0: 1 ] Partition id ('0' to disable) [01 - FF, <uuid>]: [00] (? for help) a6 Partition offset [34 - 15269854]: [40960] Partition size [1 - 15228895]: [15228895] Partition name: [] OpenBSD sd1*: 1> Print the table to make sure it matches, then w and q. sd1*: 1> p Disk: sd1 Usable LBA: 34 to 15269854 [15269888 Sectors] #: type [ start: size ] ------------------------------------------------------------------------ : Free [ 34: 32734 ] 0: EFI Sys [ 32768: 8192 ] 1: OpenBSD [ 40960: 15228895 ] sd1*: 1> w Writing GPT. sd1: 1> q # Now you can return to the installer, which is asking for disk info. Enter ? to get it to refresh disk information and it should now print out sd1. Enter e to edit the GPT (again). # fg install ? Disk: sd1 Usable LBA: 34 to 15269854 [15269888 Sectors] #: type [ start: size ] ------------------------------------------------------------------------ : Free [ 34: 32734 ] 0: EFI Sys [ 32768: 8192 ] 1: OpenBSD [ 40960: 15228895 ] Use (W)hole disk or (E)dit the GPT? [whole] e You'll now be back at fdisk, just q to quit. You can accept the auto-allocated partition layout or just make one big root and a swap partition. When prompted for the location of the sets, specify disk and then respond no that it's not mounted, and enter sd0 (the SD card), then partition a. The pathname to the sets will be just /. Continue installing, ignoring any errors from signify. The installer should automatically pick up the bwfm firmware and install it. At the end it will try to re-link the kernel which is using the upstream kernel object files, so it's important you copy the custom kernel back over /bsd. Exit to (S)hell, (H)alt or (R)eboot? [reboot] s To boot the new system, enter 'reboot' at the command prompt. # mount /dev/sd0a /mnt2 # cp /mnt2/bsd /mnt/bsd You'll also need to disable reorder_kernel which will run at each boot so it doesn't revert the kernel back to the upstream version. # mv /mnt/usr/libexec/reorder_kernel{,.disabled} # echo "#!/bin/sh" > /mnt/usr/libexec/reorder_kernel # chmod +x /mnt/usr/libexec/reorder_kernel (Note: the _ key is to the left of the up arrow, + is to the right of L.) You can now reboot. Post-Installation The first boot will report an error about bwfm and loadfirmware. You'll need to copy the firmware/nvram_ap6212a.txt file that was backed up to the SD card's EFI partition when U-Boot was flashed. # mount /dev/sd0i /mnt # cp /mnt/firmware/nvram_ap6212a.txt /etc/firmware/brcmfmac43430-sdio.rockchip,pomera-dm250.txt # umount /mnt U-Boot is compiled with boot logo support, so you can put a bitmap in the EFI partition's root directory as logo.bmp to get it to show at boot. To make it show OpenBSD puffy, you can use this image. # mount /dev/sd1i /mnt # cd /mnt # ftp https://jcs.org/dm250/logo.bmp # cd / # umount /mnt The two LEDs near the USB-C port can be addressed once booted. Create an /etc/rc.securelevel that sets them up so they are accessible from a normal kern.securelevel: # cat > /etc/rc.securelevel #!/bin/sh gpioctl -q gpio1 8 set out red_led gpioctl -q gpio1 12 set out green_led ^D # After rebooting, they can be addressed with the gpioctl utility: # gpioctl gpio1 8 1 pin 8: state 0 -> 1 Building a custom installation ramdisk If you want to tinker beyond installing, you'll need a Git clone of my OpenBSD rk3128 tree, my U-Boot pomera-dm250 tree with video and keyboard drivers, and my Linux tree which contains the DTB source files. This is optional and requires being able to compile on an armv7 machine (or cross-compile if you know how), or you can just download the latest image I've already built. Fetch an existing bsd.rd, extract its installation filesystem, build the RAMDISK kernel from my rk3128 tree, and then insert the filesystem into the new kernel. $ cd /tmp $ ftp https://cdn.openbsd.org/pub/OpenBSD/snapshots/armv7/bsd.rd $ rdsetroot -x bsd.rd root.fs $ cd /usr/src/sys/arch/armv7/compile/RAMDISK $ make config $ make $ cp -f obj/bsd /tmp/bsd.rd $ rdsetroot /tmp/bsd.rd /tmp/root.fs The /tmp/bsd.rd file is now a bootable installation image with a custom kernel.

9th Apr 2026 • 1 votes
Wallops 2.2 Released

A new release of my Wallops IRC client is available: wallops-2.2.sit (StuffIt 3 archive) adc2b473664ec0960b5b028335566831dd69f4a1de40f79e22bf1337292cca88 SHA1: 603c5080c41a0d5752cae49a08376db4e18628b1 This update includes a number of new features and bugfixes: Auto-connect with the last saved settings on startup, if they are available, unless the Command key is held down Add support for sending Pushover notifications when the user's nick is mentioned or directly messaged, when a screen saver is detected to be running; sends to Pushover's API over plain-text HTTP Improve nick highlighting when the user's nick is not at the beginning of the line Speed up parsing of nicknames when joining large channels Add support for the /monitor command which is sent directly to the server Fix bug that may have caused a crash when initially connecting, and when reconnecting

2nd Feb 2026 • 1 votes
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. details { margin-bottom: 1em; } Background 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. Pomera DM250 US board UART pins TP802-TP804 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 [email protected]... rkparm_init_param_from_storage param read fail RKPARM: Invalid parameter part table Scanning disk [email protected]... Scanning disk [email protected]... Scanning disk [email protected]... rkparm_init_param_from_storage param read fail RKPARM: Invalid parameter part table Scanning disk [email protected]... rkparm_init_param_from_storage param read fail RKPARM: Invalid parameter part table Scanning disk [email protected]... 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 printfs 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. 2025-04-17 I've pushed my U-Boot tree to GitHub as it seems to be in a good state now. I split up my changes specific to the rk3128 and then added a specific board config for the DM250. Eventually this will need some work to enable the LVDS LCD at boot time like it was with the factory U-Boot. I added a uart_putc helper to OpenBSD's armv7 locore0.S to print numbers to the serial port, and then added them along the boot path to see how far it got. .globl uart_putc /* send r1 to uart */ uart_putc: ldr r0, =0x20064000 str r1, [r0] ldr r2, =0x20064000 + 0x7c /* UART_USR */ check_usr: ldr r3, [r2] tst r3, #(1<<1) /* UART_TRANSMIT_FIFO_NOT_FULL */ beq check_usr bx lr [...] start_mmu: mov r1, #'1' bl uart_putc [...] mov r1, #'2' bl uart_putc /* Enable MMU */ mrc CP15_SCTLR(r0) orr r0, r0, #CPU_CONTROL_MMU_ENABLE mcr CP15_SCTLR(r0) isb mov r1, #'3' bl uart_putc This showed it was getting to start_mmu but as soon as it wrote the SCTLR register to enable the MMU, it stopped outputting. Mark pointed out that this was because there was no mapping in the MMU page table to continue accessing the UART at 0x20064000. I added an entry for it: MMU_INIT(0x20000000, 0x20000000, 1, L1_TYPE_S|L1_S_V7_AP(AP_KRW)|L1_S_V7_AF) But it still wasn't printing '3'. After a few hours of debugging and reading more docs, I finally realized that my dumb uart_putc function was clobbering r0 and r1 which were being used inside of start_mmu so the page table wasn't getting set up right. By changing it to just a few inline instructions with no FIFO status checking and using registers that weren't in use, it could enable the MMU properly and get to '3' and beyond: ldr r4, =0x20064000 mov r5, #'3' str r4, [r5] Eventually with some more tweaks to the DTB passed from U-Boot to the EFI loader and to the kernel, the kernel could properly print to the chosen stdout-path and get to copyright. Since it is able to do this through the normal com_fdt_init_cons routine in dev/fdt/com_fdt.c which does a bus_space_map, I could remove all of my debugging from locore0 and then remove my custom UART page table entry. It can now get to copyright with no kernel changes: disks: sd0* sd1 sd2 >> OpenBSD/armv7 BOOTARM 1.23 boot> b bsd.arm cannot open sd0a:/etc/random.seed: No such file or directory booting sd0a:bsd.arm: 4910236+1012484+138796+608784 [2789902+360416+184+330342]=0x0 OpenBSD/armv7 booting ... arg0 0xc0caf850 arg1 0x0 arg2 0x9ac83000 Allocating page tables IRQ stack: p0x60cde000 v0xc0cde000 ABT stack: p0x60cdf000 v0xc0cdf000 UND stack: p0x60ce0000 v0xc0ce0000 SVC stack: p0x60ce1000 v0xc0ce1000 Creating L1 page table at 0x60cb0000 Mapping kernel Constructing L2 page tables undefined page type 0x2 pa 0x60000000 va 0x60000000 pages 0x2000 attr 0x8 type 0x7 pa 0x62000000 va 0x60000000 pages 0x6000 attr 0x8 type 0x4 pa 0x68000000 va 0x68000000 pages 0x7 attr 0x8 type 0x7 pa 0x68008000 va 0x60000000 pages 0x32c7b attr 0x8 type 0x2 pa 0x9ac83000 va 0x9ac83000 pages 0x7 attr 0x8 type 0x7 pa 0x9ac8a000 va 0x9ac8a000 pages 0x4 attr 0x8 type 0x7 pa 0x9ac8e000 va 0x9ac8e000 pages 0x2 attr 0x8 type 0x7 pa 0x9ac90000 va 0x9ac90000 pages 0x1 attr 0x8 type 0x2 pa 0x9ac91000 va 0x9ac91000 pages 0x100 attr 0x8 type 0x2 pa 0x9ad91000 va 0x9ad91000 pages 0x1e attr 0x8 type 0x6 pa 0x9adaf000 va 0x9adaf000 pages 0x1 attr 0x8000000000000008 type 0x0 pa 0x9adb0000 va 0x9adb0000 pages 0x1 attr 0x8 type 0x0 pa 0x9adb1000 va 0x9adb1000 pages 0x1 attr 0x8 type 0x0 pa 0x9adb2000 va 0x9adb2000 pages 0x1 attr 0x8 type 0x0 pa 0x9adb3000 va 0x9adb3000 pages 0x1 attr 0x8 type 0x0 pa 0x9adb4000 va 0x9adb4000 pages 0x1 attr 0x8 type 0x0 pa 0x9adb5000 va 0x9adb5000 pages 0x1 attr 0x8 type 0x0 pa 0x9adb6000 va 0x9adb6000 pages 0x1 attr 0x8 type 0x2 pa 0x9adb7000 va 0x9adb7000 pages 0x308c attr 0x8 type 0x5 pa 0x9de43000 va 0x9de43000 pages 0x1 attr 0x8000000000000008 type 0x2 pa 0x9de44000 va 0x9adb7000 pages 0x21bc attr 0x8 pmap [ using 3481620 bytes of bsd ELF symbol table ] Copyright (c) 1982, 1986, 1989, 1991, 1993 The Regents of the University of California. All rights reserved. Copyright (c) 1995-2025 OpenBSD. All rights reserved. https://www.OpenBSD.org Now I just need to figure out how far into init_main.c it's getting and why it hangs after printing the copyright line. 2025-04-21 With some instrumenting I figured out the kernel was getting as far as setting up the page tables for the MMU and would then lock up when doing a memset on the newly setup memory. By reducing the amount of memory used, I could get it to fully boot the kernel to !cold, but it crashes in userland: U-Boot 2017.09-g9333465-dirty (Apr 21 2025 - 13:38:25 -0500) Model: KING JIM Pomera DM250 DRAM: 1 GiB Sysmem: init Relocation Offset: 3ddc2000, fdt: 00000000 Using default environment Failed to load DTB Failed to get kernel dtb, ret=-1 In: serial Out: serial Err: serial Model: KING JIM Pomera DM250 dwmmc@10214000: 1, dwmmc@1021c000: 0 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 ## Unknown partition table type 0 PartType: <NULL> rockchip_get_boot_mode: Could not found misc partition boot mode: normal 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 Hit key to stop autoboot('CTRL+C'): 0 switch to partitions #0, OK mmc1 is current device Scanning mmc 1:1... reading /kingjim-dm250.dtb 23239 bytes read in 6 ms (3.7 MiB/s) Found EFI removable media binary efi/boot/bootarm.efi reading efi/boot/bootarm.efi 119564 bytes read in 16 ms (7.1 MiB/s) ## Starting EFI application at 62008000 ... FtlInit fffffffe Scanning disk [email protected]... Scanning disk [email protected]... Scanning disk [email protected]... Found 3 disks Adding bank: 0x60000000 - 0xa0000000 (size: 0x40000000) disks: sd0* sd1 sd2 sd3 >> OpenBSD/armv7 BOOTARM 1.23 boot> b sd0a:/bsd.rd cannot open sd0a:/etc/random.seed: No such file or directory booting sd0a:/bsd.rd: 4916868+1014156+16731272+608976 [2791939+360736+184+330515]=0x0 OpenBSD/armv7 booting ... arg0 0xc1c8514c arg1 0x0 arg2 0x9ac82000 Allocating page tables IRQ stack: p0x61cb4000 v0xc1cb4000 ABT stack: p0x61cb5000 v0xc1cb5000 UND stack: p0x61cb6000 v0xc1cb6000 SVC stack: p0x61cb7000 v0xc1cb7000 Creating L1 page table at 0x61c88000 Mapping kernel Constructing L2 page tables undefined page type 0x2 pa 0x60000000 va 0x60000000 pages 0x2000 attr 0x8 type 0x7 pa 0x62000000 va 0x60000000 pages 0x6000 attr 0x8 initarm: added 24576 pages at 0x62000000, physmem now 32768 type 0x4 pa 0x68000000 va 0x68000000 pages 0x7 attr 0x8 type 0x7 pa 0x68008000 va 0x60000000 pages 0x32c7a attr 0x8 initarm: added 103997 pages at 0x68008000, physmem now 136765 type 0x2 pa 0x9ac82000 va 0x9ac82000 pages 0x7 attr 0x8 type 0x7 pa 0x9ac89000 va 0x9ac89000 pages 0x4 attr 0x8 type 0x7 pa 0x9ac8d000 va 0x9ac8d000 pages 0x2 attr 0x8 type 0x7 pa 0x9ac8f000 va 0x9ac8f000 pages 0x1 attr 0x8 type 0x2 pa 0x9ac90000 va 0x9ac90000 pages 0x100 attr 0x8 type 0x2 pa 0x9ad90000 va 0x9ad90000 pages 0x1e attr 0x8 type 0x6 pa 0x9adae000 va 0x9adae000 pages 0x1 attr 0x8000000000000008 type 0x0 pa 0x9adaf000 va 0x9adaf000 pages 0x1 attr 0x8 type 0x0 pa 0x9adb0000 va 0x9adb0000 pages 0x1 attr 0x8 type 0x0 pa 0x9adb1000 va 0x9adb1000 pages 0x1 attr 0x8 type 0x0 pa 0x9adb2000 va 0x9adb2000 pages 0x1 attr 0x8 type 0x0 pa 0x9adb3000 va 0x9adb3000 pages 0x1 attr 0x8 type 0x0 pa 0x9adb4000 va 0x9adb4000 pages 0x1 attr 0x8 type 0x0 pa 0x9adb5000 va 0x9adb5000 pages 0x1 attr 0x8 type 0x0 pa 0x9adb6000 va 0x9adb6000 pages 0x1 attr 0x8 type 0x2 pa 0x9adb7000 va 0x9adb7000 pages 0x308c attr 0x8 type 0x5 pa 0x9de43000 va 0x9de43000 pages 0x1 attr 0x8000000000000008 type 0x2 pa 0x9de44000 va 0x9adb7000 pages 0x21bc attr 0x8 pmap [ using 3484148 bytes of bsd ELF symbol table ] Copyright (c) 1982, 1986, 1989, 1991, 1993 The Regents of the University of California. All rights reserved. Copyright (c) 1995-2025 OpenBSD. All rights reserved. https://www.OpenBSD.org OpenBSD 7.7 (obj.amd64.armv7) #113: Fri Apr 18 11:15:57 CDT 2025 [email protected]:/usr/src/sys/arch/armv7/compile/GENERIC/obj.amd64.armv7 real mem = 560189440 (534MB) avail mem = 520486912 (496MB) random: boothowto does not indicate good seed mainbus0 at root: KING JIM Pomera DM250 cortex0 at mainbus0 psci0 at mainbus0: PSCI 0.0 syscon0 at mainbus0: can't map registers syscon1 at mainbus0: "syscon" ampintc0 at mainbus0 nirq 160, ncpu 4: "interrupt-controller" syscon2 at mainbus0: "syscon" agtimer0 at mainbus0: 24000 kHz agtimer1 at mainbus0: 24000 kHz com0 at mainbus0: dw16550, 64 byte fifo com0: probed fifo depth: 0 bytes com1 at mainbus0: dw16550 com1: console com2 at mainbus0: dw16550 ehci0 at mainbus0 usb0 at ehci0: USB revision 2.0 uhub0 at usb0 configuration 1 interface 0 "Generic EHCI root hub" rev 2.00/1.00 addr 1 ohci0 at mainbus0: version 1.0 dwmmc0 at mainbus0: 18 MHz base clock sdmmc0 at dwmmc0: 4-bit, dma dwmmc1 at mainbus0: 25 MHz base clock sdmmc1 at dwmmc1: 8-bit, dma rkiic0 at mainbus0 iic0 at rkiic0 "rockchip,rk818" at iic0 addr 0x1c not configured rkiic1 at mainbus0 iic1 at rkiic1 pcxrtc0 at iic1 addr 0x51pcxrtc0: pcxrtc_reg_read: failed to read reg0 pcxrtc0: pcxrtc_reg_write: failed to write reg0 pcxrtc0: pcxrtc_reg_read: failed to read reg2 : battery ok rkiic2 at mainbus0 iic2 at rkiic2 rkiic3 at mainbus0 iic3 at rkiic3 usb1 at ohci0: USB revision 1.0 uhub1 at usb1 configuration 1 interface 0 "Generic OHCI root hub" rev 1.00/1.00 addr 1 scsibus0 at sdmmc0: 2 targets, initiator 0 sd0 at scsibus0 targ 1 lun 0: <Sandisk, SL32G, 0080> removable sd0: 30436MB, 512 bytes/sector, 62333952 sectors scsibus1 at sdmmc1: 2 targets, initiator 0 sd1 at scsibus1 targ 1 lun 0: <Toshiba, 008GB1, 0000> removable sd1: 7456MB, 512 bytes/sector, 15269888 sectors vscsi0 at root scsibus2 at vscsi0: 256 targets softraid0 at root scsibus3 at softraid0: 256 targets bootfile: sd0a:/bsd boot device: sd0 root on rd0a swap on rd0b dump on rd0b pcxrtc0: pcxrtc_clock_read: failed to read rtc WARNING: bad clock chip time WARNING: CHECK AND RESET THE DATE! Fatal kernel mode prefetch abort at 0x00000000 trapframe: 0xcd06ba70 IFSR=00000005, IFAR=00000000, spsr=80000113 r0 =00000000, r1 =00000007, r2 =c18a0868, r3 =60000113 r4 =00000007, r5 =c93ad000, r6 =c93ad000, r7 =cd06bb10 r8 =cd06a000, r9 =00000013, r10=c08a8988, r11=cd06bb08 r12=c18e5378, ssp=cd06bac0, slr=c0780344, pc =00000000 Stopped at 0 ddb> trace 0 rlv=0xc032fd30 rfp=0xcd06bb90 exception_exit rlv=0xc0343800 rfp=0xcd06bee0 sys_execve+0x2c8 [/usr/src/sys/kern/kern_exec.c:361] rlv=0xc04c4450 rfp=0xcd06bfa8 start_init+0x254 [/usr/src/sys/kern/init_main.c:716] rlv=0xc07976ac rfp=0xc1cb8f90 Bad frame pointer: 0xc1cb8f90 I'm still not sure why the memory limiting is needed, but apparently U-boot is not passing the proper memory segment information to the EFI bootloader for the kernel to know to avoid that address space. Since I was able to reduce the custom things needed in U-boot, I tried adapting my UART, GPIO, and timer changes to mainline U-boot to see if maybe the EFI code was better there. It boots now with UART output but the SDMMC and eMMC driver fails to setup either one of them: U-Boot 2025.01-00001-g4e6a9d7df66d-dirty (Apr 19 2025 - 22:17:13 -0500) Model: KING JIM Pomera DM250 DRAM: 1 GiB Core: 30 devices, 14 uclasses, devicetree: embed MMC: mmc@10214000: 1, mmc@1021c000: 0 Loading Environment from nowhere... OK In: serial@20064000 Out: serial@20064000 Err: serial@20064000 Hit any key to stop autoboot: 0 Card did not respond to voltage select! : -110 Cannot persist EFI variables without system partition Card did not respond to voltage select! : -110 No USB controllers found I can see the udelay calls work properly (which weren't in the Rockchip-specific U-boot tree until I made the RK3128-specific timer changes), and where it's failing to respond to voltage is past the initial setup which requires responses from the controllers so it seems like they are being powered up. 2025-04-21 (Evening) I guess I should have read the kernel panic better. Fatal kernel mode prefetch abort at 0x00000000 and pc =00000000 indicate that the kernel set the program counter to 0, which meant it was probably executing a function callback that was pointing to NULL. After dozens of printfs added, kernels recompiled, SD cards swapped, and reset pins grounded, I figured out that the kernel was panicking in data_abort_handler because curcpu()->ci_flush_bp was NULL and there was no check for that (because it shouldn't really happen). Why it was NULL was much more complicated. ci_flush_bp was never initialized because arm/arm/cpu.c was not attaching to cpu0, because the reg values for cpu0-cpu3 in the FDT were 0x000-0x003, but mainbus.c expects them to be 0xf00-0xf03. They are 0x000-0x003 even in the latest U-boot tree but 0xf00-0xf03 in Linux which I guess is now the authoritative source for device trees? This is why I dislike the ARM ecosystem… cpu0 at mainbus0 mpidr f00: ARM Cortex-A7 r0p5 cpu0: 32KB 32b/line 2-way L1 VIPT I-cache, 32KB 64b/line 4-way L1 D-cache cpu0: 256KB 64b/line 8-way L2 cache Anyway, now that cpu0 actually attaches and runs cpu_identify, it sets the CPU device's ci_flush_bp callback to cpu_flush_bp_noop, which does… nothing. So the kernel isn't panicking now, but instead it just locks up (actually powers off) when it should be starting userland. I'm getting there… 2025-04-22 Oh, right, we have no clock again, so the dwmmc driver's attempt to set the frequency does nothing but this isn't handled as an error. I'll have to add rockchip,rk3128-cru support to the rkclock driver, which does not look fun doing from scratch. This menial task of translating register definitions from PDFs and cross-referencing Linux driver code is usually where my willpower fades in these types of projects. 2025-04-29 A few weeks ago I bought a Geniatech XPI-3128 which is another board based on the Rockchip 3128, but with 4 USB ports, ethernet, and HDMI. I tried flashing a new U-Boot build to it and it promptly stopped booting. When I'd try powering it on with its recovery button pressed to boot into Maskrom mode, my laptop would just log messages like this: uhub3: device problem, disabling port 3 So it was as if it was trying to attach but kept failing. The device was basically bricked, so I e-mailed Geniatech's support address for help. A couple weeks later they finally gave me the information I needed, which was that I had to desolder the Wi-Fi board, remove the CPU heatsink, and then the eMMC clock line was reachable to be shorted to ground to avoid loading U-Boot and force Maskrom mode. That allowed me to flash and test different U-Boot builds again and finally get it booting on the XPI-3128. However, the more I worked on it, the more I realized trying to do anything with my older U-Boot tree was futile. The device tree (DTB) that shipped on the DM250 (and the XPI-3128) is very old, and is configured for old U-Boot and Linux drivers. Things like the names of compatible strings and the way peripherals are described are targeting Rockchip-specific drivers in their old Linux tree, rather than what's in the current Linux kernel. Trying to write OpenBSD drivers for the way this old DTB is setup would be a bad idea, so I really needed to get RK3128 support working on the latest U-Boot and targeting the official XPI-3128 device tree with all of its compatible strings. While reading various RK3128 code, I came across Linux and U-Boot patches from Alex Bee, which led me to find their U-Boot tree with RK3128 support, but done right to eventually be upstreamed. With this tree I was finally able to boot a modern U-boot (2025.04) on the XPI-3128 (though still needing my timer init code), which allowed me to boot OpenBSD all the way to userland on a USB stick: U-Boot 2025.04-rc1-00167-g04767ba5b99f-dirty (Apr 29 2025 - 21:55:41 -0500) Model: Geniatech XPI-3128 DRAM: 1 GiB Cannot find regulator pwm init_voltage Cannot find regulator pwm init_voltage Core: 164 devices, 21 uclasses, devicetree: embed MMC: mmc@10214000: 1, mmc@1021c000: 0 Loading Environment from MMC... Reading from MMC(0)... *** Warning - bad CRC, using default environment In: serial@20064000 Out: serial@20064000 Err: serial@20064000 Model: Geniatech XPI-3128 Net: No ethernet found. Hit any key to stop autoboot: 0 Scanning for bootflows in all bootdevs Seq Method State Uclass Part Name Filename --- ----------- ------ -------- ---- ------------------------ ---------------- Scanning global bootmeth 'efi_mgr': Card did not respond to voltage select! : -110 Cannot persist EFI variables without system partition 0 efi_mgr ready (none) 0 <NULL> ** Booting bootflow '<NULL>' with efi_mgr Loading Boot0000 'mmc 0' failed EFI boot manager: Cannot load any image Boot failed (err=-14) Scanning bootdev '[email protected]': Card did not respond to voltage select! : -110 Scanning bootdev '[email protected]': Unknown uclass 'nvme' in label Unknown uclass 'scsi' in label Bus usb@10180000: USB DWC2 Bus usb@101c0000: USB EHCI 1.00 scanning bus usb@10180000 for devices... 1 USB Device(s) found scanning bus usb@101c0000 for devices... 3 USB Device(s) found Scanning bootdev 'usb_mass_storage.lun0.bootdev': 1 efi ready usb_mass_ 1 usb_mass_storage.lun0.boo /EFI/BOOT/BOOTARM.EFI ** Booting bootflow 'usb_mass_storage.lun0.bootdev.part_1' with efi Booting /\EFI\BOOT\BOOTARM.EFI disks: sd0* sd1 >> OpenBSD/armv7 BOOTARM 1.23 boot> booting sd0a:/bsd: 4915064+1013912+140528+607852 [289299+107+346480+308631]=0x0 OpenBSD/armv7 booting ... arg0 0xc0a456f8 arg1 0x0 arg2 0x9cdff000 Allocating page tables IRQ stack: p0x60a74000 v0xc0a74000 ABT stack: p0x60a75000 v0xc0a75000 UND stack: p0x60a76000 v0xc0a76000 SVC stack: p0x60a77000 v0xc0a77000 Creating L1 page table at 0x60a48000 Mapping kernel Constructing L2 page tables undefined page type 0x2 pa 0x60000000 va 0x60000000 pages 0x2000 attr 0x8 type 0x7 pa 0x62000000 va 0x62000000 pages 0x3adff attr 0x8 type 0x2 pa 0x9cdff000 va 0x9cdff000 pages 0x9 attr 0x8 type 0x7 pa 0x9ce08000 va 0x9ce08000 pages 0x1 attr 0x8 type 0x2 pa 0x9ce09000 va 0x9ce09000 pages 0x100 attr 0x8 type 0x1 pa 0x9cf09000 va 0x9cf09000 pages 0x1e attr 0x8 type 0x4 pa 0x9cf27000 va 0x9cf27000 pages 0x3 attr 0x8 type 0x9 pa 0x9cf2a000 va 0x9cf2a000 pages 0xb attr 0x8 type 0x4 pa 0x9cf35000 va 0x9cf35000 pages 0xb attr 0x8 type 0x6 pa 0x9cf40000 va 0x9cf40000 pages 0x1 attr 0x8000000000000008 type 0x4 pa 0x9cf41000 va 0x9cf41000 pages 0x1 attr 0x8 type 0x6 pa 0x9cf42000 va 0x9cf42000 pages 0x22 attr 0x8000000000000008 type 0x4 pa 0x9cf64000 va 0x9cf64000 pages 0x5 attr 0x8 type 0x3 pa 0x9cf69000 va 0x9cf69000 pages 0x1009 attr 0x8 type 0x6 pa 0x9df72000 va 0x9df72000 pages 0x1 attr 0x8000000000000008 type 0x3 pa 0x9df73000 va 0x9df73000 pages 0x1fff attr 0x8 type 0x5 pa 0x9ff72000 va 0x9ff72000 pages 0x2 attr 0x8000000000000008 type 0x3 pa 0x9ff74000 va 0x9ff74000 pages 0x8c attr 0x8 pmap [ using 945052 bytes of bsd ELF symbol table ] Copyright (c) 1982, 1986, 1989, 1991, 1993 The Regents of the University of California. All rights reserved. Copyright (c) 1995-2025 OpenBSD. All rights reserved. https://www.OpenBSD.org OpenBSD 7.7-current (GENERIC) #1: Tue Apr 29 20:43:21 MDT 2025 jcs@rk3128:/usr/src/sys/arch/armv7/compile/GENERIC real mem = 1021308928 (973MB) avail mem = 992374784 (946MB) random: good seed from bootblocks mainbus0 at root: Geniatech XPI-3128 cpu0 at mainbus0 mpidr f00: ARM Cortex-A7 r0p5 cpu0: 32KB 32b/line 2-way L1 VIPT I-cache, 32KB 64b/line 4-way L1 D-cache cpu0: 256KB 64b/line 8-way L2 cache cortex0 at mainbus0 syscon0 at mainbus0: "syscon" "power-controller" at syscon0 not configured syscon1 at mainbus0: "qos" syscon2 at mainbus0: "qos" syscon3 at mainbus0: "qos" syscon4 at mainbus0: "qos" syscon5 at mainbus0: "qos" syscon6 at mainbus0: "qos" syscon7 at mainbus0: "qos" ampintc0 at mainbus0 nirq 160, ncpu 4: "interrupt-controller" rkclock0 at mainbus0 syscon8 at mainbus0: "syscon" "usb2phy" at syscon8 not configured syscon9 at mainbus0: can't map registers agtimer0 at mainbus0: 24000 kHz ehci0 at mainbus0rk3128_enable: 0x000001d9 usb0 at ehci0: USB revision 2.0 uhub0 at usb0 configuration 1 interface 0 "Generic EHCI root hub" rev 2.00/1.00 addr 1 dwmmc0 at mainbus0rk3128_set_frequency: 68 100000000 rkclock_set_frequency(rkclock0, 68, 100000000) parent : 12 MHz base clock sdmmc0 at dwmmc0: 4-bit, sd high-speed, dma dwmmc1 at mainbus0rk3128_set_frequency: 71 100000000 rkclock_set_frequency: clk div mask 16128 rk3128_get_frequency: RK3128_XIN24M rk3128_get_frequency: RK3128_XIN24M rk3128_get_frequency: RK3128_PLL_CPLL rk3128_get_pll: 0x20 = 523462184 rk3128_get_frequency: RK3128_PLL_CPLL rk3128_get_pll: 0x20 = 523462184 rk3128_get_frequency: RK3128_XIN24M rk3128_get_frequency: RK3128_XIN24M rk3128_get_frequency: RK3128_PLL_CPLL rk3128_get_pll: 0x20 = 523462184 rk3128_get_frequency: unhandled 71 rk3128_get_frequency: RK3128_PLL_CPLL rk3128_get_pll: 0x20 = 523462184 : 43 MHz base clock sdmmc1 at dwmmc1: 8-bit, mmc high-speed, dma com0 at mainbus0: dw16550 com0: console rkiic0 at mainbus0 rk3128_get_frequency: RK3128_CLK_I2C rk3128_get_frequency: RK3128_PLL_CPLL rk3128_get_pll: 0x20 = 523462184 iic0 at rkiic0 dwge0 at mainbus0rk3128_set_frequency: 124 50000000 rkclock_set_frequency(rkclock0, 124, 50000000) rk3128_enable: 0x0000016f : rev 0x35rk3128_get_frequency: unhandled 126 rkclock_get_frequency(rkclock0, 126) , address 76:e3:5a:fa:14:d9 rk3128_set_frequency: 126 50000000 rkclock_set_frequency(rkclock0, 126, 50000000) dwge0: no PHY found! scsibus0 at sdmmc1: 2 targets, initiator 0 sd0 at scsibus0 targ 1 lun 0: <Samsung, 8GTF4R, 0000> removable sd0: 7456MB, 512 bytes/sector, 15269888 sectors uhub1 at uhub0 port 1 configuration 1 interface 0 "Genesys Logic USB2.0 Hub" rev 2.00/60.90 addr 2 umass0 at uhub1 port 1 configuration 1 interface 0 "USB SanDisk 3.2Gen1" rev 2.10/1.00 addr 3 umass0: using SCSI over Bulk-Only scsibus1 at umass0: 2 targets, initiator 0 sd1 at scsibus1 targ 1 lun 0: <USB, SanDisk 3.2Gen1, 1.00> removable serial.078155ab8107712cf658 sd1: 942480MB, 512 bytes/sector, 1930199040 sectors vscsi0 at root scsibus2 at vscsi0: 256 targets softraid0 at root scsibus3 at softraid0: 256 targets bootfile: sd0a:/bsd boot device: sd0 root on sd1a (f2059a1fe6a57770.a) swap on sd1b dump on sd1b WARNING: CHECK AND RESET THE DATE! rk3128_get_frequency: RK3128_ARMCLK rk3128_get_frequency: RK3128_PLL_APLL rk3128_get_pll: 0x0 = 211673469 rk3128_set_frequency: RK3128_ARMCLK 52918367 rk3128_set_frequency: RK3128_PLL_APLL 52918367 rk3128_set_pll: freq 52918367 rk3128_set_pll: 52918367 Hz cpu0: clock not implemented Automatic boot in progress: starting file system checks. /dev/sd1a (f2059a1fe6a57770.a): file system is clean; not checking pf enabled starting network starting early daemons: syslogd pflogd ntpd. starting RPC daemons:. savecore: no core dump checking quotas: done. clearing /tmp kern.securelevel: 0 -> 1 creating runtime link editor directory cache. preserving editor files. starting network daemons: sshd. starting local daemons: cron. Tue Apr 29 20:52:11 MDT 2025 OpenBSD/armv7 (rk3128) (console) login: That kernel was actually compiled on the XPI-3128 and then booting on it (ignore all the clock debugging output). I need to fix the clock setting for MMC and ethernet and then sdmmc and dwge devices will work. USB is working fine out of the box since it's actually booting and running off of a USB stick, but once MMC works, I can install and boot from the onboard eMMC. I'd like to write a driver for the Artasie AM1805 I2C RTC that is present on the XPI-3128 which will give it a working realtime clock. Once all of those things are working I'll hopefully commit all of this RK3128 support to OpenBSD, which will then allow me to go back to working on the DM250 and write drivers for the keyboard and LCD. 2025-07-09 You may have assumed that I gave up on this project but the sad part is that I've been working on it almost every day and getting pretty much nowhere. I have the basics working like GPIO pin control (rkpinctrl), clocks (rkclock), and regulators (rkpmic) but anything more advanced like the screen or SDIO Wi-Fi or keyboard interrupts aren't working. The main problem so far is that the DTB embedded on the eMMC is ancient and uses a lot of proprietary Rockchip properties that are specifically for Rockchip's Linux 3.10 tree, on top of which has hard-coded hacks and RK312x-specific tweaks everywhere. Also, the U-Boot on the device also has hard-coded hacks and things specific to the DM250. To make this work on OpenBSD, the DTB has to be modernized which is largely helped by this RK3128 file but there are a lot of DM250-specific components that need to be added describing the keyboard, SDIO, battery, LCD screen information, LVDS controller information, etc. I currently have two DM250s taken apart on my desk with cables hooked up to their UART pins, one running OpenBSD with current U-Boot, and one running Debian Linux 11 with the DM250 Linux 3.10.0 tree booting from the DM250-specific U-Boot. This allows me to add in some debugging printks on the Linux kernel, compile it, dd it to /dev/mmcblk0p14, reboot, and see the output. Then I can add things on the OpenBSD DM250 and reboot. But often this requires changing a pin configuration or adding something new to the DTB which then has to be written to the eMMC on the OpenBSD DM250 over a USB cable. This whole process has been going very slowly and just when I think I figured something out, I broke something else. I can turn the LCD backlight on with pwmbl and adjust its brightness, but I still can't get anything to show up on the screen. I wrote rklvds and rklcdc drivers for OpenBSD based on the Rockchip-specific code in the DM250 U-Boot tree, only to discover that the LCDC does the same as what is now called the VOP and should have used a different compatible string in the DTB. The Rockchip VOP already has an OpenBSD driver that hooks it up to wscons and rkdrm, but it needed RK3128 (RK3126 actually) support which I added. But still nothing will show on the screen. Current U-Boot even has Rockchip VOP and LVDS drivers so it should work out of the box, right? But it does the same thing as OpenBSD just enabling the backlight and unable to draw anything on the screen. The keyboard kind of works with the I2C TC3589x driver I wrote, but I can't get interrupts working. The SD card slot works, but I don't get interrupts for card-detect events even though I'm specifying the same cd-gpios information as the DTB file that shipped with the DM250. Anyway, this is all rambling and probably not very interesting but I'm getting tired of this project after a few months. If I could just get the screen and the keyboard interrupts working, I could work directly on the DM250 in OpenBSD instead of it being cracked open in pieces on my desk with wires hanging out of it working over a serial connection. 2026-03-23 tl;dr: OpenBSD with my kernel tree and U-boot with updated device-tree bindings is now working reliably on the DM250 including graphical boot early in U-boot with keyboard support, X11, interrupt-driven keyboard, battery charging and sensors, Wi-Fi, SD card eject/insertion, CPU speed adjustments, red and green power/charging LEDs, and probably other things I'm forgetting. OpenBSD-current on the Pomera DM250X I just noticed this article is now more than a year old. After many months of working on other projects, I had enough desk space to get back to the DM250. I booted my US model that had OpenBSD installed on it and through its serial console I could see it booting to the kernel copyright line and then locking up or totally powering off. I had no other usable kernels on the device so it took a while to get it back to a working state which involved cross-compiling an armv7 kernel on my ThinkPad. Once I had a new kernel booting, I was encountering the same problems that I remembered encountering half a year ago, such as it locking up when all 1GB of RAM was being initialized in OpenBSD, or the SD card not being able to be properly read in U-Boot. It took me a while to figure out (or remember) many of the issues were related to power caused by the battery not charged enough (or being completely disconnected as it sometimes was while moving everything around). I think when the system is running with all of its power regulators enabled, just having its USB port connected to a 5V power source doesn't supply enough amperage to fully power everything and it relies on a working battery for help or it crashes. That led me to figure out why the battery wasn't getting charged while idling in U-Boot or OpenBSD. After more digging through the vendor U-boot tree and using a USB-C power meter, I found that the RK818 PMIC needs to be told to enable USB charging at a higher rate or else it will just trickle charge the battery at a rate that is too low to keep up with the idle power consumption of the device. This would cause the battery to eventually drain too low to be able to boot. Luckily I had a few other DM250s so I swapped the dead battery into a device with the original U-boot firmware where it would immediately charge it at a high rate before continuing with boot. Once I figured out how to enable higher-rate charging on the RK818, I wrote an rkcharger driver that hangs off the rkpmic device, and also a driver for simple-battery devices which asks the parent device (rkcharger) to read charging and battery info and exposes it as hw.sensors values. Once there was reliable power, the random crashes and power-offs stopped and I could use the full 1GB of RAM. I also updated the simple-battery node in the DM250 device tree. I also discovered that the DM250 and DM250US aren't as identical as I thought, at least in terms of charging. The DM250 uses the RK818 to do it directly while the DM250US introduces a TI BQ25620 charging chip. This caused me a lot of frustration trying to figure out why my driver wasn't working on the DM250 (because the device wasn't even there). DM250 (JP) DM250 (US), adding a BQ25620 I fixed a bunch of other little issues, many of which stemmed from incorrect things in the unofficial DM250 device-tree that is still being worked on. Once the reset and power settings were corrected for the Wi-Fi bwfm0 at sdmmc1 just magically worked without any kernel changes. It uses brcmfmac43430-sdio.bin for firmware and it can use the brcmfmac43430-sdio.rockchip,pomera-dm250.txt NVRAM settings file from the original Linux installation on the device. I brought over the U-boot LVDS and VOP drivers from Rockchip's U-boot tree, which enabled a graphical framebuffer very early in the power-on process. I also ported my Toshiba TC3589X keyboard driver from OpenBSD so I could type on the keyboard and over the serial device at the same time. I enabled U-boot's boot logo support to get a neat OpenBSD logo (read from a .bmp file in eMMC's EFI partition) during boot before clearing the screen to show OpenBSD's EFI bootloader. Since the keyboard works in U-boot now, this also enabled the keyboard to work in OpenBSD's bootloader (at least as far as telling it to boot a different device or kernel). Once that worked, OpenBSD technically didn't need any video driver since it could use simplefb that was setup by U-boot. This shows continuous boot output from the EFI bootloader all the way to the console login, which is nice. If I enable the video drivers (rklvds, rkvop, rkdrm) to (re-)initialize the video in OpenBSD, it boots about halfway through the kernel sequence and then blacks out for a second or two as it has to wait for hardware to settle before drawing through the new output path. With video and the keyboard working, I finally reached that point where I could do development directly on the device which feels a lot different than remotely poking at something through a serial console. I've done a lot of little quality-of-life changes like implementing a US keyboard layout for the non-US model (available with wsconsctl keyboard.encoding=us), adding gpio(4) support to rkgpio so I can poke individual GPIO pins from userland with gpioctl. This allows me to turn on and off the red (gpioctl gpio1 8) and green (gpioctl gpio1 12) LEDs on the side of the device depending on whether the battery is about to die (red) or is charging (green). One thing that is odd about the DM250 is that the left Alt key and the right Shift key are directly wired up to their own GPIO pins, not going through the TC35894 like every other key. Presumably this is why the recovery sequence that the vendor's U-boot tree looks for is those two keys plus power, so their U-boot didn't have to implement a TC3589X driver. Anyway, since those two keys are not on the keyboard, I thought about how to make them work in OpenBSD without a specific hack for the DM250 or something in my tcmfd driver that had to reach into GPIO land. Since the existing OpenBSD gpiokeys driver works on armv7 and sees the entries in the device tree: gpiokeys0 at mainbus0: "Power Button", "Lid Switch", "Right Shift", "Left Alt" I added a (only-slightly-hackish) hack to it to inject unknown GPIO keys into the console wskbd device's input stream, so anything listening for keyboard input will see left Alt and right Shift as though it came from the same tc35894 device. This means Control+Alt+F# keys work as expected to change virtual terminals, for example. I still have a laundry list of things I'd like to keep working on like improving the keyboard driver, implementing some degree of suspend/resume, and supporting the external DMA engine for the MMC controller to speed up eMMC access. Our arm port also doesn't enable multiple processors but some degree of support seems there from when it was imported from NetBSD. My list of commits is getting quite long so I need to try to upstream as much of this as possible. My last attempts at committing just basic RK3128 support in various drivers were thwarted, so I'm still just hammering out stuff in my own trees for now. If you have a DM250 (non-US for now) and want to try OpenBSD on it, let me know and I can send you installation images and instructions. Note: I am frequently rebasing and squashing commits in my trees as I improve things, so the commit IDs in the trees linked here may vanish or become obsolete. OpenBSD 7.9-beta (GENERIC) #134: Mon Mar 23 16:10:06 CDT 2026 jcs@dm250x:/usr/src/sys/arch/armv7/compile/GENERIC real mem = 1018015744 (970MB) avail mem = 988418048 (942MB) random: good seed from bootblocks mainbus0 at root: Rockchip RK3128 Pomera DM250 cpu0 at mainbus0 mpidr f00: ARM Cortex-A7 r0p5 cpu0: 32KB 32b/line 2-way L1 VIPT I-cache, 32KB 64b/line 4-way L1 D-cache cpu0: 256KB 64b/line 8-way L2 cache cortex0 at mainbus0 syscon0 at mainbus0: "syscon" "power-controller" at syscon0 not configured syscon1 at mainbus0: "qos" syscon2 at mainbus0: "qos" syscon3 at mainbus0: "qos" syscon4 at mainbus0: "qos" syscon5 at mainbus0: "qos" syscon6 at mainbus0: "qos" syscon7 at mainbus0: "qos" ampintc0 at mainbus0 nirq 160, ncpu 4: "interrupt-controller" rkclock0 at mainbus0 syscon8 at mainbus0: "syscon" rkusbphy0 at syscon8: phy 0 rklvds0 at syscon8: LVDS 24-bit JEIDA rkpinctrl0 at mainbus0: "pinctrl" rkgpio0 at rkpinctrl0 gpio0 at rkgpio0: 32 pins rkgpio1 at rkpinctrl0 gpio1 at rkgpio1: 32 pins rkgpio2 at rkpinctrl0 gpio2 at rkgpio2: 32 pins rkgpio3 at rkpinctrl0 gpio3 at rkgpio3: 32 pins rkdrm0 at mainbus0 drm0 at rkdrm0 agtimer0 at mainbus0: 24000 kHz rkvop0 at mainbus0: RK3126 VOP dwctwo0 at mainbus0 dwmmc0 at mainbus0: 49 MHz base clock sdmmc0 at dwmmc0: 4-bit, sd high-speed, mmc high-speed dwmmc1 at mainbus0: 49 MHz base clock sdmmc1 at dwmmc1: 4-bit, sd high-speed dwmmc2 at mainbus0: 49 MHz base clock sdmmc2 at dwmmc2: 8-bit, mmc high-speed rklvdsphy0 at mainbus0 dwdog0 at mainbus0 rkpwm0 at mainbus0 com0 at mainbus0: dw16550, 64 byte fifo bcmbt0 at com0 com1 at mainbus0: dw16550 rkiic0 at mainbus0 iic0 at rkiic0 tcmfd0 at iic0 addr 0x45 wskbd0 at tcmfd0: console keyboard rkpmic0 at iic0 addr 0x1c: RK818 rkcharger0 at rkpmic0: 4.2V 5800mAh battery simplebat0 at rkcharger0 gpioleds0 at mainbus0: "pomera:green:power" gpiokeys0 at mainbus0: "Power Button", "Lid Switch", "Right Shift", "Left Alt" pwmbl0 at mainbus0 simplepanel0 at mainbus0: 1024x600 rkdrm0: 1024x600, 32bpp wsdisplay0 at rkdrm0 mux 1: console (std, vt100 emulation), using wskbd0 wsdisplay0: screen 1-5 added (std, vt100 emulation) usb0 at dwctwo0: USB revision 2.0 uhub0 at usb0 configuration 1 interface 0 "DWC2 DWC2 root hub" rev 2.00/1.00 addr 1 scsibus0 at sdmmc0: 2 targets, initiator 0 sd0 at scsibus0 targ 1 lun 0: <Sandisk, SD32G, 0085> removable sd0: 30436MB, 512 bytes/sector, 62333952 sectors scsibus1 at sdmmc2: 2 targets, initiator 0 sd1 at scsibus1 targ 1 lun 0: <Toshiba, 008GB0, 0000> removable sd1: 7456MB, 512 bytes/sector, 15269888 sectors bwfm0 at sdmmc1 function 1 manufacturer 0x02d0, product 0xa9a6 at sdmmc1 function 2 not configured vscsi0 at root scsibus2 at vscsi0: 256 targets softraid0 at root scsibus3 at softraid0: 256 targets bootfile: sd0a:/bsd boot device: sd0 root on sd1a (717a8af462695010.a) swap on sd1b dump on sd1b bcmbt0: address 70:4a:0e:df:xx:xx bwfm0: address 70:4a:0e:df:xx:xx

14th Mar 2025 • 1 votes

More in technology

iPhone Duo early review

By a mile, the iPhone Duo has garnered more questions about what I think about it than any other phone I’ve ever had. It’s clearly a phone that has people intrigued, so I thought I’d jot down some loose, unorganized thoughts about what I think about it after about ten days. If I could sum all my thoughts up into one word, it’d simply be “fun”. I think for the vast majority of people, myself included, the iPhone 18 Pro is a more practical phone that through scientific analysis you’d likely even find a better phone. Even if they were priced the same, its package is more traditionally comfortable and ergonomic, with a better quality main camera, a helpful telephoto camera, a screen that’s more practical to use more of the time, a better biometric system (Face ID versus Touch ID) and a more established software experience. But damn if the iPhone Duo isn’t fun. Phones have been downright boring for so long. Incredible technology, lovely apps, but the hardware has been a bit slow moving since the iPhone X. Maybe that’s why I jumped onto the iPhone Air so readily. Even that slight departure from “black slab of glass” to “a dramatically thinner black slab of glass” was exciting versus what we’ve grown accustomed to. So I pick up the Duo, and it’s kinda just exciting to hold a phone for the first time in ages. Maybe that’s a honeymoon period and after a few months I’ll be over it. Maybe everyone who tries a folding phone for the first time experiences this. And to be clear, it’s not just all raw novelty. The fun aspect is fueled by having an absolutely incredible inner screen that fundamentally transforms what a phone is and can be. In addition, support the Apple Pencil has turned out to be phenomenally handy for me to be able to jot down quick thoughts and notes. For downsides, Touch ID is objectively worse than Face ID, but honestly, I don’t mind it as much as I expected I would. The smaller camera sensor than the Pro series phones is still decidedly great (rumors were it was a 17e size which was not correct, it’s the size of the normal 17’s). Software support gets better by the day, though iOS on the Duo is still decidedly a bit buggy at times. Other random thoughts Touch ID is objectively worse than Face ID, but honestly, I don’t mind it as much as I expected I would, previewing notifications is where I miss it the most After getting used to having a single speaker in the iPhone Air for a year, having stereo (not to mention great sounding) speakers is amazing The FaceTime camera on the inside is indeed not great for selfies/photography but honestly perfectly acceptable for FaceTime, and I’d definitely prefer this solution over a cutout on the inside so I’m happy! It definitely has a heavy feel to it, but it’s nothing honestly that bothersome A lot of the reviews said something to the effect of “the crease is practically invisible” and while I don’t really mind it or anything I definitely would disagree with that statement, you can see it a fair bit even with light content The hinge is a bit harder to open than I expected, I’ve found the secret is don’t pry from the middle of the side, instead put a thumb near the top and bottom (also helps prevent pressing Camera Control instead which I was doing all the time). I imagine this is necessary to have it be able to stop at arbitrary angles once open (which I do like) and hopefully it loosens up a bit with more use, but playing with Android foldables at Best Buy I did find their hinge easier to open I am really split on the inner, nano texture screen. It definitely helps reflections, has a neat look to it, and is super nice to draw on with the pencil, but it’s significantly less vibrant than the outer display which to my eyes looks a fair bit nicer. I think they made the right decision ultimately but it’s definitely not a zero-compromise solution. I was considering nano texture on my next MacBook but after this I think I’ll stick with glossy. My glass half full take with the Duo for now though is that we get two really cool screens to play with The outer screen is awesome for taking photos, unlike taller iPhones, your viewfinder fills the screen completely so it’s the largest feeling viewfinder I’ve used on a phone I miss the action button, nice little launcher for ChatGPT/Claude depending on which month it is Battery life is downright phenomenal versus my iPhone Air and 15 Pro (two devices admittedly not known for having great battery life) So, I don’t think the Duo is for most people who either don’t care much about phones, or care a lot about having the perfect phone, but for a decent amount of people in the middle I think the Duo represents a fundamentally different experience, that’s a ton of fun, and I’m excited to be excited about a phone again. (But, Apple, please figure out a way to add a telephoto lens.)

14 hours ago • 1 votes
Reverse engineering a vintage diode-transistor logic chip

Going through a collection of old parts, CuriousMarc encountered some ICs that he couldn't identify. He opened up one of these ICs, and I studied it under the microscope. After some reverse engineering, I determined that it was a logic chip that implemented four NAND gates using old-fashioned diode-transistor logic (DTL).1 The chip turned out to be the ST680A, a member of the Signetics 600 series of chips from 1965. In this article, I discuss the circuitry in this chip and how diode-transistor logic works. The die of the ST680A under the microscope. Integrated circuits can be packaged in many ways. One of the most popular is the plastic DIP (Dual In-line Package), a black rectangle of epoxy with two rows of metal pins. This type of package was invented by Signetics: "Introduced in late 1965, the 600 series was the first integrated circuit family to be offered in a solid, plastic, dual in-line package (DIP)." Earlier integrated circuits were packaged in round metal cans or in small flat-packs. In 1965, engineers at Fairchild invented the DIP, which had two rows of pins on 0.1" spacing. Unlike the surface-mounted flat-pack, the DIP had pins that were inserted into holes, making manual or automated assembly quick and easy. Because the pins of a DIP were on a regular grid, rather than the circular pattern of a metal can, circuit board design and manufacturing were also easier (details). The first DIP chips had ceramic packages. The plastic DIP, introduced by Signetics, was much cheaper and became very popular. An advertisement for the Signetics 600 series. From Electronics, March 21, 1966. The plastic DIP is less popular with me, however, because it is harder to open. With a ceramic package, I can simply tap it with a chisel and pop it open, but that doesn't work with epoxy packages. An epoxy package can be dissolved with nitric or sulfuric acid, but I try to avoid dangerous acids. Instead, CuriousMarc used Antoine's hot air decapping method. Unfortunately, the hot air technique doesn't always work. In this case, tiny bits of epoxy were stuck to the die, obscuring the circuitry. I used a few drops of boiling sulfuric acid to clean the die. (I'm okay with sulfuric acid in tiny quantities.) The die on its metal frame. The photo above shows the silicon die on its metal frame, the lead frame. The golden blobs are where the bond wires were attached to the die. You can see the doped silicon regions that form diodes and bipolar NPN transistors, as well as 16 resistors in the center, forming serpentine paths. Most chips have a passivation layer—a thin layer of silicon dioxide—over the chip. Inconveniently, this old chip didn't have a passivation layer, so the acid also stripped off the metal layer. (A few remnants are visible in the upper left.) Without the metal layer, I had to guess at how the components were connected to form logic gates. The die has very faint color differences where the silicon was protected by the metal, so that helped. Eventually, I came up with the diagram below, showing how the metal layer was probably configured. This wiring reveals that the chip implements four DTL NAND gates, which I'll describe in more detail below. One puzzle was that the chip has two unused diodes, indicated with question marks below. The metal layer for a quad NAND chip. I desaturated the image to make the labels clearer. Transistors, diodes, and resistors In this section, I'll explain how the patterns in the image correspond to components of the circuit. The silicon die is doped with various impurities to form regions with different electrical characteristics. These regions appear red or green under the microscope due to thin-film effects. As a result, the chip's transistors, diodes, and resistors are visible. The chip is made from bipolar NPN transistors, which have a completely different construction from the MOS transistors in modern ICs. In an NPN transistor, the current from the collector to the emitter is controlled by the current through the base. The collector is a large region of N-type silicon, silicon that is doped with atoms such as phosphorus or arsenic. Since these elements have one more valence electron than silicon, they give the silicon more negative charge carriers, so it is called N for negative. The N-type silicon happens to appear reddish. On top of the collector, the base is a thin region of P-type silicon, which appears green. This silicon has been doped with atoms such as boron or gallium, which have one fewer valence electron than silicon. The missing electrons form "holes", which act as positive charge carriers. Finally, the emitter is N-type silicon, on top of the base layer. These layers work together through semiconductor magic, amplifying the base current. Two NPN transistors on the chip. The second transistor is a larger output transistor. The chip's output transistors are slightly larger so they can sink more current. In the transistor on the right above, note that the collector contact wraps around three sides of the transistor. The emitter is also larger, with an L-shaped contact. According to the datasheet, each output transistor can sink 2.5 mA of current. The chip uses many diodes since it is diode-transistor logic. The structure of a diode is similar to a transistor, but without the emitter. In a diode, current flows from the cathode (P-type silicon) to the anode (N-type). A diode and a resistor on the chip. The chip uses 16 resistors, located in the middle of the die. A resistor is constructed from a long, thin region of doped silicon. Since silicon has moderately high resistance, a long strip of silicon acts as a resistor. Most of the resistors have a serpentine layout to fit a long resistor into a smaller area. These resistors consist of P-type silicon (green) in a "tub" of N-type silicon (red). The tub is connected to the positive voltage supply; since current doesn't flow from N-type silicon to P-type silicon, this isolates the resistors from each other. Operation of a DTL gate Logic gates can be created in many ways. The earliest integrated circuits (such as the ones in the Apollo Guidance Computer) used Resistor-Transistor Logic (RTL), where logic gates were constructed from resistors and transistors. In March 1962, Signetics announced the first family of commercial Diode-Transistor Logic (DTL) integrated circuits (details). By using diodes on the inputs instead of resistors, DTL provided better performance than RTL. However, DTL soon became overshadowed by TTL (Transistor-Transistor Logic), which was faster and used less power. (If you built digital circuits a few decades ago, you're probably familiar with the popular 7400 series of TTL chips.) The diagram below shows how the DTL NAND gate works. If both inputs are high, the current from the first resistor flows through the base of the first transistor, turning it on. The transistor amplifies this current, passing a much larger current from the transistor's collector to the transistor's emitter. This current goes through the base of the second transistor, which turns on the second transistor. The second transistor passes an even larger current from the output pin to ground, pulling the output pin low. The DTL NAND gate with both inputs high. The schematic is from the datasheet. This circuit is considerably more complicated than the DTL gate on Wikipedia. But if one of the input pins is pulled low, the current from the resistor goes through the diode instead of the transistor. The first transistor turns off, and without a base current, the second transistor turns off. The third resistor pulls the output high. Thus, the output is low only if both inputs are high: a NAND gate. The DTL NAND gate with an input low. I'll point out a few features of this circuit. The diodes on the inputs ensure that one input doesn't affect the other input. The diode in the middle raises the voltage on the first transistor's emitter, so it requires more voltage to turn on, reducing the sensitivity to noise. The output uses a resistor to pull the output high; more advanced circuits use another transistor. When the output is low, the third resistor is still "trying" to pull the output high, which is wasting power. Moreover, the resistor limits the output current, so the high output is fairly weak. In some DTL families, you can get gates with different values for the output resistor, so you can select the tradeoff between wasting power and having an output that is too weak. If you've used TTL integrated circuits from the 1970s, you know that chips usually have power and ground on diagonal pins: ground on pin 7 and power on pin 14. (Putting power and ground diagonally opposite both helps die layout and circuit board layout.) Much to my surprise, I found that the Signetics chips predate this standard and have ground on pin 1 and power on pin 8: still diagonal, but the wrong diagonal! The diagram below shows how the four NAND gates are wired in the chip. Pinout of the 680A quad NAND gate. From the databook. Three chips from one die When I examined the die under the microscope, I figured out the circuit, but I was puzzled by two extra diodes, as if two NAND gates had a third input that wasn't used. The explanation is that Signetics used the same silicon layout for at least three different chips, applying a different metal layer for different functionality. This saved money since it's much cheaper to produce a single optical mask for the metal layer than a complete set of new masks. Signetics sold semi-custom ICs to customers, using an approach called variFEBS (Variable Functional Electronics Blocks). This approach used a custom metal layer on top of fixed silicon, providing custom circuits without the cost of a full mask set. These circuits didn't sell well, but Signetics used the same approach for standard ICs. Pinout of the 670A triple NAND gate and the 616A quad NAND gate. All three chips have some similarities, such as using pins 2 and 14 as outputs. From the databook. One IC with the same silicon as the quad NAND gate is the 670A chip, which has three NAND gates, each with three inputs (above left). The diagram below shows how the silicon can be wired to provide this functionality. The hypothesized metal layer for the 670A triple-NAND gate. The layout for the triple chip above is a bit tricky because the top gate has inputs on both sides of the power (Vcc) pin. This creates a layout problem because the power and ground metal runs vertically to the resistors, blocking metal wiring from one side to the other. The solution is a "crossunder", a region of silicon that allows a signal to pass under the metal layer, connecting the inputs on the left to the rest of the circuitry on the right. This crossunder is visible near the top of the chip. Another chip with the same layout is the 616A dual NAND gate, with five inputs on each gate. Since this chip has 10 inputs in total (compared to 8 on the quad gate), this chip uses the two "extra" diodes that I spotted. If that isn't enough inputs, each NAND gate has an expansion input; by connecting external diodes to the expansion input, the gate can be made as large as desired. The hypothesized metal layer for the 616A dual-NAND chip. Some history The history of Signetics is closely tied to Fairchild. The story of Fairchild's founding is well known: in 1957, eight engineers—the Traitorous Eight—left Shockley Semiconductor and created Fairchild Semiconductor. Hundreds of companies (the "Fairchildren") were started by engineers who left Fairchild. Signetics was one of those companies, formed in 1961 and said to be the first company to exclusively design and manufacture integrated circuits.2 Signetics announced its first product in 1962, a NAND gate that cost $125 (over $1000 in current dollars).3 Not surprisingly, sales were weak. Signetics soon ran short of money, so in 1962, Corning Glass invested $1.7 million for 51% ownership of Signetics. Corning Glass may seem like a strange investor, but Corning was more of a high-tech company than you'd expect, making components such as resistors and glass capacitors, and later creating fiber optics. Moreover, in the early 1960s, integrated circuits were the hot area (much like AI now), and everyone wanted to get involved. In 1963, the Department of Defense pushed for contractors to use integrated circuits in new products. Riding this wave, Signetics became the leading producer of integrated circuits.4 However, Fairchild soon introduced a series of DTL chips that competed with Signetics. The Fairchild 930 series was faster than the Signetics chips and less than half the price, so Fairchild took much of the market from Signetics and dominated the IC market. Signetics also produced analog integrated circuits. Signetics is probably best known for creating the 555 timer chip in 1970, said to be the world's most popular IC, with billions sold.5 Signetics was acquired by Philips in 1975, and then Philips Semiconductors was spun off as NXP (Next exPerience) in 2006. NXP is currently the #10 semiconductor manufacturer worldwide, so the heritage of Signetics lives on. For more, follow me on Bluesky (@righto.com), Mastodon (@[email protected]), or RSS. Thanks to CuriousMarc for providing the IC and thanks to TubeTime for finding the databook. AI statement: Despite the presence of the em dash, no AI was used in the writing of this article (details). Notes and references After I had reverse-engineered the chip, TubeTime found datasheets for it, making my reverse engineering unnecessary. (See the Signetics Condensed Catalog 1969, Utilogic II Databook 1971, and Utilogic 2 Databook 1972.) We must have been unlucky with our original web searches since we didn't find anything. But this way you get to see what's inside the chip :-) The Signetics ST680A IC in its package. The large circular depression marks pin 1. From the date code, this chip is from 1971.  ↩ For more Signetics history, see Signetics Founding History, written by Lionel Kattner, a co-founder of Signetics. He states that the company name was inspired by the words "signals" and "networks", as well as the high-tech suffix "-netics". ↩ See History of Semiconductor Engineering, page 156. ↩ The book Making Silicon Valley describes the history of Signetics. It has a negative view of the Corning investment, saying that Signetics executives "Van Poppelen and Kattner dissented on the grounds that Corning was not a good fit for an integrated circuit company. In their view, Corning was a staid Eastern firm, ignorant about semiconductors and antithetic to the ways and culture of the electronics industry on the West Coast. Their view later proved to be correct." ↩ The 555 timer was created by analog IC wizard Hans Camenzind. If you're interested in analog circuits, you should read his book Designing Analog Chips, which you can download for free. ↩

18 hours ago • 1 votes
How Do Building Codes Affect the Price of Housing?

A great deal of effort has gone into understanding the regulatory burden on housing construction, and the extent to which it contributes to high housing prices.

3 days ago • 1 votes
Barracuda Networks is your new best friend (Barracuda Email Security Gateway Pre-Auth Remote Root RCE CVE-2026-116606 / CVE-2026-111560)

Yes, that's right! Today we're at the aquarium. Welcome back to yet another watchTowr Labs blog post. You can begin preparing your comments now. What Is A Barracuda, And Why? Must We? Barracuda’s Email Security Gateway solution (ESG) is no stranger to love, for

4 days ago • 1 votes
📚 BoredReading

You seem to be enjoying this.

Join free to unlock everything.

Create free account

Already have an account? Sign in