惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News and Events Feed by Topic
Malwarebytes
Malwarebytes
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cybersecurity and Infrastructure Security Agency CISA
F
Future of Privacy Forum
C
Cisco Blogs
T
The Exploit Database - CXSecurity.com
A
Arctic Wolf
S
Securelist
K
Kaspersky official blog
S
Schneier on Security
T
ThreatConnect
T
Tenable Blog
Spread Privacy
Spread Privacy
T
True Tiger Recordings
AWS News Blog
AWS News Blog
F
Fox-IT International blog
量子位
T
Threatpost
V
Vulnerabilities – Threatpost
C
CERT Recently Published Vulnerability Notes
Cisco Talos Blog
Cisco Talos Blog
GbyAI
GbyAI
宝玉的分享
宝玉的分享
腾讯CDC
G
Google Developers Blog
aimingoo的专栏
aimingoo的专栏
Cyberwarzone
Cyberwarzone
有赞技术团队
有赞技术团队
S
SegmentFault 最新的问题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
U
Unit 42
雷峰网
雷峰网
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
O
OpenAI News
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
The Register - Security
The Register - Security
MyScale Blog
MyScale Blog
小众软件
小众软件
A
About on SuperTechFans
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
博客园 - 三生石上(FineUI控件)
美团技术团队
Google Online Security Blog
Google Online Security Blog
P
Proofpoint News Feed
MongoDB | Blog
MongoDB | Blog

DEV Community

🌱 Keep Feeding Your CI/CD — Or Watch It Die Gemma 4 vs GPT-4o vs Llama 3: What Actually Works Locally? Vessel Ops SSH in 2026: Why Every Developer Should Know It Cold Audit AI-Generated PRs Before You Merge Them (Swarm Orchestrator 10.3.0) App Store Optimization (ASO) I built a tool to visualize Django REST Framework architecture (URLs, Serializers, Models, and more) How I made my React site agent-ready in 100 lines AI Can Generate Interfaces on the Fly. But Users Still Need Orientation. AI-Assisted Content Workflow How We Learned That Most Resume Rejections Happen Before Humans See Your CV How I Prepared for CKA: Resources, Labs, and Strategy That Worked for Me Stop Flying Blind: We Built an LLM Evaluation Framework That Works Across 17+ Agent Frameworks The Misleading "User is not authorized to access connection" Error in AWS CodeBuild — and Why Your IAM Policy Looks Fine I Resurrected a Dead F1 Project and Accidentally Built a Race Intelligence OS Remix Mini PC: After a Year of Dead Ends, the eMMC Finally Talks Not All Games Are Equal: The Real Difference Between a Trap and a Tool How to add Peppol e-invoicing to your SaaS without making it your team's problem I Built a Hermes Agent to Tell Me Which Hackathons to Enter. It Told Me to Enter This One. The Five Hooks That Change How You Ship With Claude Code Powering Your Progress: Building Robust Solutions with Laravel I built a self-hosted CI/CD platform with persistent queue, encrypted secrets, and rollback UI — here's what I learned Antigravity 2.0 and the $1,000 OS: Why "Agent-First" Feels Like the Direction I've Been Building Toward Anyway I built an AI PR-triage agent in 30 lines of Markdown Core Web Vitals from 74 to 91: A Real Tax Practitioner Site Rebuild I Gave Gemma 4 150 Tools on Windows. Here's What Actually Happened. Beyond the Loop: Why Monolithic AI Agents Fail and How to Build a Microkernel Architecture The Hidden Tax of AI-Assisted Development (And How I Fixed It) I Ditched Cloud LLMs for Gemma 4 4B: A DevOps Engineer's 48-Hour Reality Check Building a Schema.org @graph That Validates on the First Try The "Lift and Shift" Trap: Why Your Integration Layer Needs More Than Just a Cloud Address All 7 OSI Layers Explained with Real-World Analogies Antigravity 2.0 in one day: the four shells and what each is good for Self-Hosting Google Fonts with size-adjust: Zero CLS Web Font Swap The Multi-Provider LLM Problem: Why “One API” Is Not Enough How I indexed 69,000 Claude Code skills (and what I learned doing it) RememberMe CareGrid: Local Gemma 4 for dementia memory and safety Google Is Killing Gemini CLI on June 18. Here Is What to Do Before Then Do Domínio ao Deploy: Hospedando Arquivos de Deep Links no Cloudflare Pages (Parte 7.1) Running Gemma 4 26B on an Old GTX 1080 with llama.cpp Devlog 1: I tried building an SNES game with the super FX chip Why Gemma 4 Feels Like an Important Moment for AI Developers✨ From Zero and Confused, This Is How I Started Learning to Code I Built a Local AI Gateway That Talks to Claude, ChatGPT, DeepSeek and Gemini — Without a Single API Key Bootstrapping with AI: Why Gemma 4 is the Micro-SaaS Founder’s Best Friend MyErp Architecture Series - #02 Cellular Architecture: Mapping Biology to Software Systems NodeJS vs Bun vs Go 🌍 RTL Arabic Style UI How Does an AI Agent Actually Buy Something? Google Just Published the Spec. Google I/O 2026 Is One Uncanny F.R.I.E.N.D.S Group Upgrade I Replaced 70MB Node.js Log Viewer with a 172KB Zig Binary The "MTTR Is All You Need" Trap The Quiet Revolution: How Firebase Became the First Agent-Native Backend at Google I/O 2026 I Built ResuMate! A 100% Private, Local AI Resume Optimizer with Google Gemma 4 Learning DirectX 12 - Part 2 Initialization Theory NeuralHats: I Put Edward de Bono’s Six Thinking Hats on Local LLMs Using Gemma 4 📝 Instant Auto Save Notes Engineering the "App-Like" Experience: A Deep Dive into PWA Architecture I built a local first AI CCTV assistant using Gemma 4 + Frigate CrowdShield AI — Smart Stadium Operating System & Crowd Intelligence Platform I built a free AI observability tool, prove your AI is useful, not just running Beyond Autocomplete: Why Google Antigravity 2.0 Changes the Rules for Indie Builders 터미널 AI 에이전트 구축 (v12) Building Instagram-Powered Apps with HikerAPI (Without Fighting Scrapers) Checkpoints, Not Transcripts: Rethinking AI Coding Agent Memory From Side Project to Student Savior: My AI PPT & Resume Tool Crossed 1.5K+ Users Why Story Points Don’t Work in the AI Era, And What Should Take Their Place Instead. Self-Hosted Document AI: How to Run Document Intelligence On Your Own Infrastructure (2026) How to Extract Tables from PDFs with AI: 4 Methods That Actually Work (2026) IDP vs OCR: What's the Difference — and Which Does Your Business Actually Need? Automated PII Detection and Redaction in Business Documents: A Practical Guide Human-in-the-Loop Document Review: When to Use It and How to Set It Up (2026) Document Processing Without RPA: A Modern Approach for Small Teams Reducto Alternative: When You Need More Than a Document Parser (2026) Hermes Agent vs LangChain vs CrewAI: When to Reach for Each SparshAI: I Built an Offline AI Tutor for Students Using Gemma 4 — Here's What Happened Building NeuroSense AI: A Human-Centered Stress Insight Assistant Powered by Gemma Why I Built a Privacy-First Dev Toolkit GAS Input Tags: Ability Activation Without Hardcoded Bindings AI Legal Document Advisor Supported By Gemm 4 Model Building Convertify in Public Week 10: PDF Cluster + Blog Launch CureNet AI: Decentralized Health Intelligence for India, Powered by Gemma 4 and ABHA Standardization When Open-Weights AI Meets a Broken Healthcare System: Deploying Gemma 4 in Rural India V.A.L.I.D. Google I/O 2026: The Year Google Stopped Building AI Assistants and Started Shipping AI Engineers Bondmap: AI-Powered Relationship Network That Maps How You're Connected to Everyone Using Gemma 4 Gemma 4 challenge inspired me to build my first app! 96. LoRA: Fine-Tune a Billion-Parameter Model on a Laptop From a Student Who Used CircuitVerse to a GSoC Contributor — My Community Bonding Story How Bf-Tree Keeps Mini-Pages Small, Hot, and Cheap to Evict I asked Claude to explain the chip war and ended up understanding modern geopolitics differently Stop Manually Checking for Server Updates: Automate With Email Notifications Nostalgia Meets Cybersecurity: Spotting Modern Scams in a Retro OS Simulator - Forward or Fraud CRACKING CODING INTERVIEW From Python to Production Pipeline :A Practical guide to Apache Airflow Antigravity 2.0: Google Just Changed What It Means to Be an Engineer I Built a Free Sticker Maker Because Every Other One Hid the Export How I bypassed Blazor WebAssembly's Virtual DOM using raw WASM pointers Distributed Tracing for LLM Agents: When MCP Makes Tool Calls Observable The Zero-Budget Memory Setup Behind My AI Agent Workflow No database. No framework. Just files, startup order, correction logs, and discipline.
Remix Mini PC: Moving the Whole Operating System Onto the eMMC
Matt Miller · 2026-05-25 · via DEV Community

Source files: GitHub

The previous post ended with a working cold boot. Plug in power, the BROM loads our TOC0 SPL from sector 16 of the SD card, our U-Boot runs, Armbian comes up to a login prompt. No laptop, no FEL, no manual intervention.

There was just one cosmetic issue. The SD card was still required.

If you pulled it out, the device fell straight to FEL because the BROM had nothing else to boot. That's not actually a problem in most usage, but it bothered me. The whole point of internal storage is that you don't need external media. A 16 GB eMMC is sitting right there on the mainboard, untouched since the project began, except for the small TOC0 SPL I had written to its boot partition during placement experiments and which the BROM had never accepted.

So: one more push. Move everything onto the eMMC, eject the SD card forever.

The unknown that wasn't

I had spent a long evening earlier in the project writing TOC0 SPLs to the eMMC's boot partition (/dev/mmcblk2boot0) at offset 0 and offset 0x2000, both with the same result every time: BROM silent, no SPL banner, device falls to FEL. I had concluded from this that "the eMMC boot partition is not the right place" — but I had never finished the obvious next experiment. I had never written a TOC0 SPL to the user area at sector 16, which is the exact offset that works on SD.

It is embarrassing how easy this was to test. From inside Armbian (booted from the SD as usual), with the boot partition's read-only flag still in its default state (we don't even need to unlock it because the user area is fully writable):

sudo dd if=~/uboot-build/u-boot/u-boot-sunxi-with-spl.bin \
        of=/dev/mmcblk2 bs=512 seek=16 conv=fsync

Enter fullscreen mode Exit fullscreen mode

Power off. Pull the SD out. Plug power back in. Watch the UART.

U-Boot SPL 2026.07-rc2-g744cf5d4e398-dirty
DRAM: 2048 MiB
Trying to boot from MMC2
NOTICE:  BL31: ...
NOTICE:  BL31: Found U-Boot DTB at 0x20ad278, model: Remix Mini PC
...
=>

Enter fullscreen mode Exit fullscreen mode

The BROM had just loaded our TOC0 SPL from the eMMC user area at sector 16, same offset as SD. The whole "the eMMC boot partition is the special boot device" mental model was wrong. Allwinner BROM on this device treats the eMMC user area and the SD card the same way — it scans them for a TOC0 signature at sector 16 and runs whatever it finds. The boot partitions are a separate eMMC feature the BROM does not use here.

The U-Boot prompt at the end is just because there is no Linux rootfs on the eMMC yet, so U-Boot has nothing to chain to. But the hard part — getting BROM to accept eMMC — was over the moment I tried the right offset.

The rootfs migration

Once the eMMC was a usable boot device, the remaining work was straightforward Linux administration. Create a partition on the eMMC user area starting at 16 MiB (well clear of the SPL at sector 16), format it ext4, rsync the SD's contents over, fix up the bootloader config to point at the new UUID.

sudo parted -s /dev/mmcblk2 mklabel msdos
sudo parted -s /dev/mmcblk2 mkpart primary ext4 16MiB 100%
sudo partprobe /dev/mmcblk2

Enter fullscreen mode Exit fullscreen mode

Then immediately I learned something I had not known about parted. After running mklabel msdos, my TOC0 SPL at sector 16 was gone:

$ sudo dd if=/dev/mmcblk2 bs=512 skip=16 count=1 | hexdump -C | head -1
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00

Enter fullscreen mode Exit fullscreen mode

Zeros. parted does not just write the 512-byte MBR at sector 0; it zeros some configurable amount of leading sectors to scrub residual filesystem signatures and old SPL data. The exact size depends on parted's version and the device, but on my install it was at least 8 KiB — which is exactly where my SPL lived.

This was completely recoverable — the SPL file was still on disk, one dd puts it back at sector 16 — but it's a real gotcha for anyone doing this in the same order I did. The right ordering is:

  1. Create the partition table first with parted.
  2. Then write the SPL at sector 16.
  3. The partition itself starts at sector 32768, so nothing else touches sector 16 again.

After restoring the SPL and verifying, mkfs.ext4 -L armbi_emmc /dev/mmcblk2p1 formats the partition cleanly without touching the bootloader region. rsync -aHAXx / /mnt/emmc/ copies the current SD rootfs over while running on top of it. About 89,000 files and 2.1 GB. Nine minutes at SD-card-speed.

The variable substitution trap

Inside the eMMC copy, two files needed editing:

  • /etc/fstab — the kernel needs to know which device to mount as root.
  • /boot/armbianEnv.txt — the U-Boot boot script reads this to pass the root= parameter to the kernel.

Both currently referenced the SD card's UUID. They needed to reference the eMMC partition's UUID instead. Easy substitution, four shell commands:

SD_UUID=$(sudo blkid -s UUID -o value /dev/mmcblk0p1)
EMMC_UUID=$(sudo blkid -s UUID -o value /dev/mmcblk2p1)
sudo sed -i "s|$SD_UUID|$EMMC_UUID|g" /mnt/emmc/etc/fstab
sudo sed -i "s|$SD_UUID|$EMMC_UUID|g" /mnt/emmc/boot/armbianEnv.txt

Enter fullscreen mode Exit fullscreen mode

I ran the first command. I skipped the second by accident — possibly the multi-line paste cut off, possibly I just didn't notice it. The third and fourth commands ran with $EMMC_UUID set to an empty string, and sed happily did exactly what I told it to: replace the SD UUID with nothing. The result was a fstab that read:

UUID= / ext4 defaults,noatime,...

Enter fullscreen mode Exit fullscreen mode

and an armbianEnv.txt that read rootdev=UUID=. The eMMC rootfs would have failed to mount on boot in a way that would have been hard to debug at three in the morning.

The verify step — printing both files after the substitution — is what caught it. I noticed the UUID column was suddenly empty, looked at the variables, found $EMMC_UUID was unset, set it explicitly, ran a targeted sed to put the right UUID back. Twenty seconds of fix work because of a verify step that took ten seconds. Always print before and after.

The final test

After fixing fstab and armbianEnv, unmounting cleanly, and writing one last sync:

sudo poweroff

Enter fullscreen mode Exit fullscreen mode

Unplug power. Pull SD card out (critical — the BROM tries SD first, and if it finds the SD's TOC0 SPL it'll boot from there regardless of whether the eMMC also has one). Plug power back in.

U-Boot SPL 2026.07-rc2-g744cf5d4e398-dirty
DRAM: 2048 MiB
Trying to boot from MMC2                          ← eMMC, not SD
NOTICE:  BL31: ...
NOTICE:  BL31: Found U-Boot DTB at 0x20ad278, model: Remix Mini PC

U-Boot 2026.07-rc2 Allwinner Technology
CPU:   Allwinner A64 (SUN50I)
Model: Remix Mini PC
DRAM:  2 GiB
...
MMC: no card present                              ← SD physically removed
...
switch to partitions #0, OK
mmc1(part 0) is current device
Scanning mmc 1:1...                               ← eMMC partition 1
Found U-Boot script /boot/boot.scr
...
Starting kernel ...

Armbian 24.11.1 Bookworm ttyS0

pine64 login:

 v24.11.1 for Pine64 running Armbian Linux 6.6.62-current-sunxi64
 Usage of /:  17% of 15G                          ← root mounted from eMMC

Enter fullscreen mode Exit fullscreen mode

Full Armbian login. No SD card in the device. No laptop attached. The Remix Mini PC is now genuinely autonomous: plug in power, after about twenty seconds it is running Linux, ready to be SSH'd into or used directly through HDMI and a USB keyboard.

The boot trace is worth comparing to the previous post's. Same SPL build, same BL31, same U-Boot, same kernel, same rootfs — but the source has shifted from "SD card sector 16" to "eMMC user area sector 16." The SD card is no longer required for any part of the chain.

What this finishes

The original project goal — turn the device into something that boots its own operating system from its own internal storage without a host PC — is done. There is a small list of polish items left (the wired Ethernet is still off, the kernel-side device tree is still a patched BananaPi-M64 rather than a true Remix DTS, the eMMC could be using its boot partition more cleverly) but nothing on that list is blocking. The machine works.

The SD card, freshly imaged and gzip-backed-up at 893 MB, goes into a drawer as a recovery boot media. The two Remix Mini PCs on my desk — one with eMMC, one without — are both functional Linux SBCs as of this evening.

Lessons that I'd put on a sticky note

  • Test the obvious-but-untested case before getting deep into the non-obvious ones. Writing TOC0 to the eMMC user area at sector 16 — the same offset that works on SD — was the simplest possible experiment, and I never ran it until very late in the project. Hours of "the boot partition won't accept TOC0" investigation could have been compressed into one dd command.

  • parted mklabel zeros more than just the MBR. If you have anything in the first few kilobytes of a disk that you want to keep, write it after you create the partition table.

  • Empty shell variables make sed eat data. sed 's|X|$Y|g' with $Y unset does not error; it silently substitutes X with nothing. Always echo your variables before passing them to sed.

  • Verify steps are not optional. Every single bug in this project was caught by either a UART log or a "print the file after editing" command. Every single one was lost time when those verifies were skipped.

Three years between buying the device and getting it to boot on its own. About twenty seconds between power-on and login prompt now. That's the trade I would make again.


Enjoying the content? If you'd like to support my work and keep the ideas flowing, consider buying me a coffee! Your support means the world to me!

Buy Me A Coffee