Compare commits

..

5 Commits
master ... emmc

Author SHA1 Message Date
Takumi Sueda
9134d2b25c Update 2022-09-22 22:42:17 +09:00
Takumi Sueda
575b450af9 Add emmc.img target 2022-09-22 22:29:20 +09:00
Takumi Sueda
5852372b9b Add experimental eMMC build script 2022-09-22 17:10:17 +09:00
Takumi Sueda
3817fc5eeb Set envs if it's not set 2022-09-22 14:52:29 +09:00
Takumi Sueda
462651541a Add mk_hdr from Freescale 2022-09-22 14:51:28 +09:00
36 changed files with 335 additions and 1506 deletions

View File

@@ -12,7 +12,7 @@ jobs:
outputs: outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }} upload_url: ${{ steps.create_release.outputs.upload_url }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
fetch-depth: 0 fetch-depth: 0
submodules: false submodules: false
@@ -38,33 +38,22 @@ jobs:
prerelease: true prerelease: true
build-linux: build-linux:
runs-on: ubuntu-24.04 runs-on: ubuntu-20.04
needs: [create_release] needs: [create_release]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
submodules: true submodules: true
- name: Workaround for apt update failure - name: Workaround for apt update failure
run: sudo rm -f /etc/apt/sources.list.d/github_git-lfs.* run: sudo rm /etc/apt/sources.list.d/github_git-lfs.*
- name: Install deps - name: Install deps
run: sudo apt update && sudo apt install build-essential bison flex libncurses5-dev gcc-arm-linux-gnueabi qemu-user-static debootstrap python3-pip run: sudo apt update && sudo apt install build-essential bison flex libncurses5-dev gcc-arm-linux-gnueabi qemu-user-static debootstrap python3-pip
- name: Upgrade pip and setuptools - name: Upgrade pip and setuptools
run: pip3 install -U pip 'setuptools<71' run: pip3 install -U pip setuptools
- name: Install listconfig - name: Install listconfig
run: pip3 install listconfig run: pip3 install listconfig
- name: Configure for Linux - name: Configure for Linux
run: make ldefconfig run: make ldefconfig
- name: Generate listconfig
run: listconfig ./linux-brain/Kconfig ./linux-brain/.config > listconfig
- name: Upload listconfig
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create_release.outputs.upload_url }}
asset_path: listconfig
asset_name: listconfig
asset_content_type: text/plain
- name: Build Linux - name: Build Linux
run: make lbuild run: make lbuild
- name: Setup releases - name: Setup releases
@@ -86,15 +75,27 @@ jobs:
asset_path: release.zip asset_path: release.zip
asset_name: ${{ steps.archive_name.outputs.name }}.zip asset_name: ${{ steps.archive_name.outputs.name }}.zip
asset_content_type: application/zip asset_content_type: application/zip
- name: Generate listconfig
run: listconfig ./linux-brain/Kconfig ./linux-brain/.config > listconfig
- name: Upload listconfig
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create_release.outputs.upload_url }}
asset_path: listconfig
asset_name: listconfig
asset_content_type: text/plain
build-linux-x1: build-linux-x1:
runs-on: ubuntu-24.04 runs-on: ubuntu-20.04
needs: [create_release] needs: [create_release]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
submodules: true submodules: true
- name: Workaround for apt update failure - name: Workaround for apt update failure
run: sudo rm -f /etc/apt/sources.list.d/github_git-lfs.* run: sudo rm /etc/apt/sources.list.d/github_git-lfs.*
- name: Install deps - name: Install deps
run: sudo apt update && sudo apt install build-essential bison flex libncurses5-dev gcc-arm-linux-gnueabihf libssl-dev lzop qemu-user-static debootstrap run: sudo apt update && sudo apt install build-essential bison flex libncurses5-dev gcc-arm-linux-gnueabihf libssl-dev lzop qemu-user-static debootstrap
- name: Configure for Linux - name: Configure for Linux
@@ -122,17 +123,14 @@ jobs:
asset_content_type: application/zip asset_content_type: application/zip
build-uboot: build-uboot:
runs-on: ubuntu-24.04 runs-on: ubuntu-20.04
needs: [create_release] needs: [create_release]
strategy: strategy:
matrix: matrix:
include: include:
- model: a7200 - model: g5300
nk: edna3exe.bin nk: edna3exe.bin
lilo: gen2.bin lilo: gen2.bin
- model: a7400
nk: edna3exe.bin
lilo: gen2_7400.bin
- model: sh1 - model: sh1
nk: edsa1exe.bin nk: edsa1exe.bin
lilo: gen3_1.bin lilo: gen3_1.bin
@@ -156,11 +154,11 @@ jobs:
lilo: gen3_7.bin lilo: gen3_7.bin
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
submodules: true submodules: true
- name: Workaround for apt update failure - name: Workaround for apt update failure
run: sudo rm -f /etc/apt/sources.list.d/github_git-lfs.* run: sudo rm /etc/apt/sources.list.d/github_git-lfs.*
- name: Install deps - name: Install deps
run: sudo apt update && sudo apt install build-essential bison flex libncurses5-dev gcc-arm-linux-gnueabi qemu-user-static debootstrap run: sudo apt update && sudo apt install build-essential bison flex libncurses5-dev gcc-arm-linux-gnueabi qemu-user-static debootstrap
- name: Build nkbin-maker - name: Build nkbin-maker
@@ -194,7 +192,7 @@ jobs:
asset_content_type: application/zip asset_content_type: application/zip
build-uboot-x1: build-uboot-x1:
runs-on: ubuntu-24.04 runs-on: ubuntu-20.04
needs: [create_release] needs: [create_release]
strategy: strategy:
matrix: matrix:
@@ -202,11 +200,11 @@ jobs:
- model: h1 - model: h1
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
submodules: true submodules: true
- name: Workaround for apt update failure - name: Workaround for apt update failure
run: sudo rm -f /etc/apt/sources.list.d/github_git-lfs.* run: sudo rm /etc/apt/sources.list.d/github_git-lfs.*
- name: Install deps - name: Install deps
run: sudo apt update && sudo apt install build-essential bison flex libncurses5-dev gcc-arm-linux-gnueabihf libssl-dev lzop qemu-user-static debootstrap run: sudo apt update && sudo apt install build-essential bison flex libncurses5-dev gcc-arm-linux-gnueabihf libssl-dev lzop qemu-user-static debootstrap
- name: Configure for U-Boot - name: Configure for U-Boot
@@ -233,10 +231,10 @@ jobs:
asset_content_type: application/zip asset_content_type: application/zip
build-sd: build-sd:
runs-on: ubuntu-24.04 runs-on: ubuntu-20.04
needs: [create_release] needs: [create_release]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
submodules: true submodules: true
- name: Make /opt writable - name: Make /opt writable
@@ -247,7 +245,7 @@ jobs:
unzip -q cegcc.zip unzip -q cegcc.zip
cp -r cegcc /opt/ cp -r cegcc /opt/
- name: Workaround for apt update failure - name: Workaround for apt update failure
run: sudo rm -f /etc/apt/sources.list.d/github_git-lfs.* run: sudo rm /etc/apt/sources.list.d/github_git-lfs.*
- name: Install deps - name: Install deps
run: sudo apt update && sudo apt install kpartx build-essential bison flex libncurses5-dev gcc-arm-linux-gnueabi qemu-user-static debootstrap run: sudo apt update && sudo apt install kpartx build-essential bison flex libncurses5-dev gcc-arm-linux-gnueabi qemu-user-static debootstrap
- name: Configure for Linux - name: Configure for Linux
@@ -255,18 +253,14 @@ jobs:
- name: Build Linux - name: Build Linux
run: make lbuild run: make lbuild
- name: Build Debian Root - name: Build Debian Root
run: make brainux brainux-umount-special run: make brainux
- name: Build bsd-ce - name: Build bsd-ce
run: make -C nkbin_maker bsd-ce run: make -C nkbin_maker bsd-ce
- name: Generate version string and image name - name: Generate image name
id: image_name id: image_name
run: | run: echo ::set-output name=name::sdimage-${GITHUB_REF/refs\/*s\//}
echo "name=sdimage-${GITHUB_REF/refs\/*s\//}" >> $GITHUB_OUTPUT
echo "version=${GITHUB_REF/refs\/*s\//}" >> $GITHUB_OUTPUT
- name: Build SD image - name: Build SD image
run: make image/sd.img && mv image/sd.img ${{ steps.image_name.outputs.name }}.img run: make image/sd.img && mv image/sd.img ${{ steps.image_name.outputs.name }}.img
env:
BRAINUX_VERSION: ${{ steps.image_name.outputs.version }}
- name: Compress - name: Compress
run: zip ${{ steps.image_name.outputs.name }}.zip ${{ steps.image_name.outputs.name }}.img run: zip ${{ steps.image_name.outputs.name }}.zip ${{ steps.image_name.outputs.name }}.img
- name: Upload the image - name: Upload the image
@@ -280,14 +274,14 @@ jobs:
asset_content_type: application/zip asset_content_type: application/zip
build-sd-x1: build-sd-x1:
runs-on: ubuntu-24.04 runs-on: ubuntu-20.04
needs: [create_release] needs: [create_release]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
submodules: true submodules: true
- name: Workaround for apt update failure - name: Workaround for apt update failure
run: sudo rm -f /etc/apt/sources.list.d/github_git-lfs.* run: sudo rm /etc/apt/sources.list.d/github_git-lfs.*
- name: Install deps - name: Install deps
run: sudo apt update && sudo apt install kpartx build-essential bison flex libncurses5-dev gcc-arm-linux-gnueabihf libssl-dev lzop qemu-user-static debootstrap run: sudo apt update && sudo apt install kpartx build-essential bison flex libncurses5-dev gcc-arm-linux-gnueabihf libssl-dev lzop qemu-user-static debootstrap
- name: Upgrade pip and setuptools - name: Upgrade pip and setuptools
@@ -305,7 +299,7 @@ jobs:
- name: Build Linux - name: Build Linux
run: make lbuild run: make lbuild
- name: Build Debian Root - name: Build Debian Root
run: make brainux brainux-umount-special run: make brainux
- name: Generate image name - name: Generate image name
id: image_name id: image_name
run: echo ::set-output name=name::sdimage-x1-${GITHUB_REF/refs\/*s\//} run: echo ::set-output name=name::sdimage-x1-${GITHUB_REF/refs\/*s\//}

3
.gitmodules vendored
View File

@@ -13,6 +13,3 @@
[submodule "brainlilo"] [submodule "brainlilo"]
path = brainlilo path = brainlilo
url = https://github.com/brain-hackers/brainlilo.git url = https://github.com/brain-hackers/brainlilo.git
[submodule "buildroot"]
path = buildroot
url = https://github.com/brain-hackers/buildroot.git

148
AGENTS.md
View File

@@ -1,148 +0,0 @@
# AGENTS.md
## Purpose
This repository builds Brainux, a Debian-based Linux distribution and SD card image for SHARP Brain devices. The root repo is the orchestration layer: it wires together kernel, bootloader, rootfs, image-building scripts, CI, and several hardware-specific submodules.
Future agents should treat this file as project memory plus operating instructions for working in `buildbrain`.
## Repository map
- `linux-brain/`: Linux kernel submodule.
- `u-boot-brain/`: U-Boot submodule.
- `boot4u/`: chain-boot tool for newer models.
- `brainlilo/`: chain-boot tool for older models.
- `nkbin_maker/`: converts `u-boot.bin` into `nk.bin` for the Windows CE boot flow.
- `buildroot/`: alternative lightweight rootfs build.
- `os-brainux/`: Brainux rootfs customization scripts and overrides.
- `os-buildroot/`: Buildroot-side overrides.
- `image/`: SD image creation scripts.
- `tools/`: helper scripts such as cross-prefix detection and APT cache tooling.
- `docs/knowledge/`: hardware and boot-process knowledge for SHARP Brain devices. Prefer the Markdown files over PDFs for fast reading and search.
## Search strategy
Do not start with a repo-wide search from the root unless you actually need submodule results. This repo contains large submodules, and broad searches are noisy and slow.
Prefer scoped searches:
- Kernel work: search only under `linux-brain/`.
- U-Boot work: search only under `u-boot-brain/`.
- Rootfs and image work: search `os-brainux/`, `image/`, `tools/`, and the root `Makefile`.
- Hardware/background research: read `docs/knowledge/*.md`.
## Important project knowledge
- Brainux development often happens in submodules, not in the root repo.
- Typical kernel workflow:
1. work inside `linux-brain/` on a branch based on `brain`
2. return to the repo root
3. run `make lclean ldefconfig lbuild` for a clean rebuild, or `make lbuild` for incremental rebuilds
4. test on real hardware by copying `linux-brain/arch/arm/boot/zImage` and matching DTBs
5. commit in `linux-brain/` using the surrounding kernel commit style
- Typical U-Boot workflow is similar, but uses `u-boot-brain/` plus the `make udefconfig-*` and `make ubuild` targets.
- Typical Brainux rootfs workflow edits files under `os-brainux/`, then runs `make brainux` or `make image/sd.img`.
- Real-device testing is part of the normal loop. A local build passing is useful but not sufficient for hardware changes.
## Main build targets
The root `Makefile` is the main entry point.
- Setup:
- `make setup`: initialize submodules.
- `make setup-dev`: create `env/` and install `r3build`.
- `make watch`: run the file watcher after `setup-dev`.
- Linux:
- `make ldefconfig`
- `make ldefconfig-x1`
- `make lbuild`
- `make lclean`
- U-Boot:
- `make udefconfig-<model>` such as `udefconfig-sh1` or `udefconfig-h1`
- `make ubuild`
- `make uclean`
- NK.bin:
- `make nkbin-maker`
- `make nk.bin`
- Chain boot tools:
- `make boot4ubuild`
- `make lilobuild`
- Rootfs and images:
- `make brainux`
- `make brainux-umount-special`
- `make brainux-clean`
- `make buildroot_rootfs`
- `make image/sd.img`
- `make image/sd_x1.img`
- `make image/sd_buildroot.img`
- Utilities:
- `make aptcache`
- `make uuu`
## Build behavior and constraints
- `make brainux` only works on Linux. It uses `debootstrap`, `qemu-arm-static`, `sudo`, chroot, and bind mounts.
- Outside CI, `make brainux` expects the local APT cache from `make aptcache` and points debootstrap at `http://localhost:65432/debian/`.
- `make brainux-umount-special` is the normal cleanup step after rootfs builds.
- `make image/sd.img` and related image targets depend on a prepared rootfs and remove `image/work` via `make clean_work`.
- `make ubuild` chooses the output format from the detected cross toolchain:
- `arm-linux-gnueabi-` builds `u-boot.sb`
- other configured prefixes build `u-boot.imx`
## CI reference
The authoritative automation is `.github/workflows/build.yml`.
CI currently does the following:
- Builds Linux artifacts for both the default family and the `x1` family.
- Builds U-Boot artifacts for multiple models through a matrix.
- Builds `nk.bin` for the older-model U-Boot jobs.
- Builds full Debian-based SD images for the default family and for `x1`.
When changing build logic, keep the local Makefile workflow and CI workflow aligned.
## Files and outputs to know
- Linux outputs:
- `linux-brain/arch/arm/boot/zImage`
- DTBs under `linux-brain/arch/arm/boot/dts/`
- U-Boot outputs:
- `u-boot-brain/u-boot.bin`
- `u-boot-brain/u-boot.sb` or `u-boot-brain/u-boot.imx`
- Converted boot image:
- `nk.bin`
- SD images:
- `image/sd.img`
- `image/sd_x1.img`
- `image/sd_buildroot.img`
## Guidance for edits
- If the task is about kernel or U-Boot source, make the change in the relevant submodule rather than trying to patch generated outputs or wrapper scripts in the root repo.
- If the task is about Brainux package selection, startup behavior, or filesystem contents, inspect `os-brainux/` first.
- If the task is about image layout or packaging, inspect `image/` and the root `Makefile`.
- If the task is about cross-compile behavior, inspect `tools/getcross` and the relevant Makefile targets.
- Avoid using interactive config editors such as `menuconfig` unless the user explicitly asks; prefer editing committed defconfig/config sources where practical.
## Validation expectations
Choose the lightest validation that matches the change:
- Makefile or CI edits: run the directly affected `make` target when feasible.
- Kernel build plumbing: at least run the relevant `make ldefconfig*` or `make lbuild` path if the environment supports it.
- U-Boot build plumbing: at least run the matching `make udefconfig-*` and `make ubuild` path if feasible.
- Rootfs/image changes: prefer `make brainux brainux-umount-special`, and image targets when dependencies and privileges are available.
If a full build is not possible because of missing toolchains, root privileges, mounts, or long runtime, say that explicitly and leave the repo in a clean state.
## Knowledge docs
- Start with `docs/knowledge/*.md` when you need hardware, boot-sequence, suspend, or eMMC-install context.
- `docs/knowledge/AGENTS.md` defines the rule for converting a knowledge PDF into Markdown. If asked to do such a conversion, preserve page positions with `# Page NN` headings, add an abstract, and write a concise text-first technical explanation rather than raw OCR.
## Commit and review notes
- Submodules have their own history and conventions. Kernel commits should follow the style already used in `linux-brain/`.
- Root-repo changes should stay focused on orchestration, config, CI, docs, image assembly, and rootfs customization.
- When a task spans both the root repo and a submodule, keep the responsibility split clear in the final report.

View File

@@ -1,8 +1,8 @@
JOBS=$(shell grep -c '^processor' /proc/cpuinfo) JOBS=$(shell grep -c '^processor' /proc/cpuinfo)
UBOOT_CROSS=$(shell ./tools/getcross u-boot) UBOOT_CROSS?=$(shell ./tools/getcross u-boot)
LINUX_CROSS=$(shell ./tools/getcross linux) LINUX_CROSS?=$(shell ./tools/getcross linux)
ROOTFS_CROSS=$(shell ./tools/getcross rootfs) ROOTFS_CROSS?=$(shell ./tools/getcross rootfs)
export ARCH=arm export ARCH=arm
.PHONY: .PHONY:
@@ -135,52 +135,33 @@ lilobuild:
liloclean: liloclean:
make -C ./brainlilo clean make -C ./brainlilo clean
brainux: brainux:
@if [ "$(shell uname)" != "Linux" ]; then \ @if [ "$(shell uname)" != "Linux" ]; then \
echo "Debootstrap is only available in Linux!"; \ echo "Debootstrap is only available in Linux!"; \
exit 1; \ exit 1; \
fi fi
mkdir -p brainux sudo mkdir -p brainux
sudo mkdir -p brainux/proc brainux/sys
sudo mount -t proc none $(shell pwd)/brainux/proc
sudo mount --rbind /sys $(shell pwd)/brainux/sys
@if [ "$(CI)" = "true" ]; then \ @if [ "$(CI)" = "true" ]; then \
echo "I'm in CI and debootstrap without cache."; \ echo "I'm in CI and debootstrap without cache."; \
sudo debootstrap --arch=$(ROOTFS_CROSS) --foreign trixie brainux/; \ sudo debootstrap --arch=$(ROOTFS_CROSS) --foreign buster brainux/; \
else \ else \
sudo debootstrap --arch=$(ROOTFS_CROSS) --foreign trixie brainux/ http://localhost:65432/debian/; \ sudo debootstrap --arch=$(ROOTFS_CROSS) --foreign buster brainux/ http://localhost:65432/debian/; \
fi fi
sudo cp /usr/bin/qemu-arm-static brainux/usr/bin/ sudo cp /usr/bin/qemu-arm-static brainux/usr/bin/
sudo cp ./os-brainux/setup_brainux.sh brainux/ sudo cp ./os-brainux/setup_brainux.sh brainux/
sudo ./os-brainux/override-pre.sh ./os-brainux/override ./brainux
sudo -E chroot brainux /setup_brainux.sh sudo -E chroot brainux /setup_brainux.sh
sudo rm brainux/setup_brainux.sh sudo rm brainux/setup_brainux.sh
sudo ./os-brainux/override.sh ./os-brainux/override ./brainux sudo ./os-brainux/override.sh ./os-brainux/override ./brainux
brainux-umount-special:
sudo umount $(shell pwd)/brainux/proc || true
sudo umount -l $(shell pwd)/brainux/sys || true
sudo rm -rf brainux/proc brainux/sys
brainux-clean: brainux-umount-special
sudo rm -rf brainux
buildroot_rootfs:
make -C buildroot brain_imx28_defconfig
make -C buildroot -j 12
sudo mkdir -p buildroot_rootfs
sudo tar -C ./buildroot_rootfs -xf buildroot/output/images/rootfs.tar
image/sd.img: clean_work image/sd.img: clean_work
./image/build_image.sh brainux sd.img 3072 ./image/build_image.sh
image/emmc.img: clean_work
./image/build_image_emmc.sh
image/sd_x1.img: clean_work image/sd_x1.img: clean_work
./image/build_image_x1.sh brainux sd_x1.img 3072 ./image/build_image_x1.sh
image/sd_buildroot.img: clean_work
./image/build_image.sh buildroot_rootfs sd_buildroot.img 128
.PHONY: .PHONY:
clean_work: clean_work:
@@ -189,7 +170,7 @@ clean_work:
.PHONY: .PHONY:
aptcache: aptcache:
./tools/aptcache_linux_amd64 \ ./tools/aptcache_linux_amd64 \
-rule 'local=localhost:65432, remote=ftp.riken.jp, root=/Linux/debian' \ -rule 'local=localhost:65432, remote=ftp.jaist.ac.jp' \
-rule 'local=localhost:65433, remote=security.debian.org' -rule 'local=localhost:65433, remote=security.debian.org'
.PHONY: .PHONY:

View File

@@ -94,8 +94,8 @@ Build Linux
1. Confirm that `linux-brain/arch/arm/boot/zImage` exists. 1. Confirm that `linux-brain/arch/arm/boot/zImage` exists.
Build a Debian rootfs Bootstrap Debian 11 (bullseye)
--------------------- ------------------------------
1. Run `make ldefconfig lbuild`. 1. Run `make ldefconfig lbuild`.
@@ -107,23 +107,9 @@ Build a Debian rootfs
1. Confirm that `image/sd.img` is built and burn it to an SD card. 1. Confirm that `image/sd.img` is built and burn it to an SD card.
Build a Buildroot rootfs
------------------------
Buildroot rootfs aims to be the most lightweight rootfs for experimental use. `make buildroot_rootfs` runs the defconfig target for rootfs-only build and then builds the rootfs tarball and a CPIO archive for initramfs. `make image/sd_buildroot.img` makes a bootable SD image in `image` directory like the typical Brainux SD image.
If you want to customize the build of Buildroot, `cd` into `buildroot` and use the following targets:
- `make menuconfig` to change the configuration
- `make` to build the rootfs (`-j` option might give you extra speed)
`image/sd_buildroot.img` target expects presence of the tarball at `buildroot/output/images/rootfs.tar`. You'll have to `clean` and rebuild every time you change the Buildroot's config before making the SD image.
Known issues Known issues
---------------------------------------- ----------------------------------------
If you use GCC 10 for the host compiler, `make ubuild` may fail. If you using gcc 10 for host compiler, `make ubuild` may fail.
To complete build, open `/u-boot-brain/scripts/dtc/dtc-lexer.lex.c` or `/u-boot-brain/scripts/dtc/dtc-parser.tab.c` then comment out `YYLTYPE yylloc;` To complete build, open `/u-boot-brain/scripts/dtc/dtc-lexer.lex.c` or `/u-boot-brain/scripts/dtc/dtc-parser.tab.c` then comment out `YYLTYPE yylloc;`
Watch changes in submodules & auto-build Watch changes in submodules & auto-build

Submodule buildroot deleted from cf3ea90108

View File

@@ -1,368 +0,0 @@
# Abstract
This document details the initial journey of porting embedded Linux to the SHARP Brain electronic dictionary. It covers the hardware teardown, circuit analysis, compiling U-Boot, overcoming DRAM and microSD recognition issues, and finally reverse-engineering the undocumented LCD panel to successfully achieve a functional Linux boot.
# Page 01
Title: Do Electronic Dictionaries Dream of Embedded Linux? (電子辞書は組み込み Linux の夢を見るか?)
Author: Takumi Sueda @puhitaku
Event: Bunka no Susume #6 (分解のススメ 第6回)
Date: 2021/01/30
Version: 2.0.0
# Page 02
Self-introduction: Takumi Sueda (@puhitaku). A full-stack engineer with a preference for low-level layers. Freelance (formerly at NICT). First teardown was a PS2. Hobby: hacking including circuit analysis (e-dictionaries, routers), 3D printing, and tool development with Python/Go.
# Page 03
Back in 2010, puhitaku (16 years old at the time) obtained an electronic dictionary at a textbook sale at Tsuyama National College of Technology.
# Page 04
The model was SHARP Brain PW-GC610.
# Page 05
Looking closely at the back of the device...
# Page 06
A sticker reveals: "Windows® Embedded CE 6.0 Core".
# Page 07
Close-up of the Windows CE sticker.
# Page 08
Shocking discovery: "Windows CE is running on an electronic dictionary!?"
# Page 09
Features of the SHARP Brain series:
- Runs Windows CE.
- Can run some CE apps or custom-developed ones.
- A hacking community on 2ch already existed in 2010.
Apps available at the time:
- App launcher
- Offline Wikipedia viewer
- matplotlib
- Ported visual novels, etc.
# Page 10
The young puhitaku was deeply impressed.
# Page 11
However, due to poor software and hardware, the community's activity rapidly declined.
# Page 12
With limited technical skills at the time, puhitaku could only watch from the sidelines.
# Page 13
Time passes to 2019...
# Page 14
Looking at the Brain sleeping in a drawer, a question arose.
# Page 15
"What kind of CPU does Brain have?"
# Page 16
Googled it and was surprised!
# Page 17
It was equipped with the i.MX series, synonymous with SoCs for embedded Linux!
# Page 18
What is the i.MX series?
- SoC by Freescale (now NXP).
- A "living witness" of embedded Linux.
- Source code for Linux and U-Boot (bootloader) is available on GitHub.
- Datasheets and reference manuals are freely available.
- Evaluation boards with the same SoC as Brain can be purchased.
- puhitaku had used it extensively at work.
Photo: i.MX 283 on SHARP Brain PW-SH1.
# Page 19
The SoC was practically saying, "Please run Linux on me."
# Page 20
Wondering: "Maybe Linux can run on Brain...?"
# Page 21
Immediately bought one on Mercari.
# Page 22
A grand journey of porting Linux to SHARP Brain began.
# Page 23
Step 1: Disassemble and look inside.
# Page 24
External view of SHARP Brain PW-SH1.
# Page 25
Turning it over.
# Page 26
Stickers hiding screws.
# Page 27
Removing the stickers.
# Page 28
Removing all stickers and screws.
# Page 29
Removing the back of the hinge area.
# Page 30
Prying up the hinge part.
# Page 31
Progress of disassembly.
# Page 32
Lifting the tabs with a card.
# Page 33
Carefully lifting while watching out for the keyboard flexible cable.
# Page 34
Close-up of the keyboard connector.
# Page 35
Keyboard side separated.
# Page 36
Removing the battery.
# Page 37
Disconnecting the battery connector.
# Page 38
Keyboard side disassembly complete.
# Page 39
Back of the keyboard.
# Page 40
Mainboard analysis.
Components identified:
- NXP i.MX283 (SoC)
- Micron MT46H64M16LFBF-5 (RAM)
- Samsung KLM8G1WE4A (eMMC)
- Freescale MCQE16CLD (Power management?)
- Yamaha YMU818B (Audio)
- Magnetic sensor, Micro SD slot, Earphone jack.
# Page 41
LCD side disassembly.
# Page 42
Back of the LCD panel.
# Page 43
Parts identified through disassembly. Moving towards Linux porting.
# Page 44
The first barrier: "Circuitry" (回路).
# Page 45
Cannot move forward without understanding all peripheral circuits.
# Page 46
Using a heat gun...
# Page 47
Removing the chips.
# Page 48
Removing chips reveals the location of the "key" to inject the bootloader.
# Page 49
Applying voltage to the PSWITCH pin (Row 1, Column 11) allows injecting the bootloader via USB from a PC.
# Page 50
"Let's actually see it."
# Page 51
Further probing SoC pins and peripheral circuits with a tester.
# Page 52
Exhaustively investigating connections.
# Page 53
Reverse engineering the FPC connector pins (LCD signals, backlight, touch panel, etc.).
# Page 54
Electrical connections of the board are clarified. First step achieved.
# Page 55
The second barrier: "Bootloader" (ブートローダ).
# Page 56
U-Boot is on GitHub. There's a config for an evaluation board with the same SoC as Brain.
Hypothesis: Compiling U-Boot for the evaluation board and injecting it into Brain might work.
# Page 57
Compilation succeeded! Serial port connected! Running it...
# Page 58
Output:
HTLLCLLC
Undefined Ins
"What?"
# Page 59
What is happening?
- HTLLCLLC: Output from Boot ROM (Normal).
- Undefined Ins: "Undefined Instruction".
Forum search suggests: DRAM settings are wrong, preventing DRAM R/W.
# Page 60
The third barrier: "DRAM".
# Page 61
- Evaluation board uses DDR2 DRAM.
- Brain uses LPDDR DRAM.
U-Boot implementation for the evaluation board won't work with LPDDR.
# Page 62
"Then just write an implementation for LPDDR."
# Page 63
...It sounds easy, but...
# Page 64
Snippet of DRAM control registers from the datasheet.
# Page 65
There are about 200 DRAM-related registers.
# Page 66
Analysis using:
- Custom Python scripts.
- Register dumps from the actual Brain hardware.
- Mysterious code found on GitHub.
After many trials and errors...
# Page 67
It works! U-Boot logs show successful initialization of mx28 SDRAM controller and DRAM size detection (128 MiB).
# Page 68
Now Linux can be booted from microSD!
# Page 69
"Wait, let's load the Linux kernel from microSD... oh?"
# Page 70
The fourth barrier: "microSD".
# Page 71
U-Boot doesn't recognize the microSD. Oscilloscope shows no signals.
# Page 72
It seemed trivial but was very difficult to solve.
# Page 73
- Sniffing SD signals with an oscilloscope.
- MOSFET control for power supply.
- SoC I/O clock.
- Reviewing I/O multiplexer.
- Massive amount of printf debugging.
After many trials and errors...
# Page 74
Recognized! `mmc info` shows the SD card details.
# Page 75
The fifth barrier: "Linux kernel and Debian".
# Page 76
Conclusion: Linux worked with minor adjustments, and Debian 10 ran smoothly.
# Page 77
Console output showing Debian 10, ARM926EJ-S (v5l) CPU, and Linux kernel 5.1.15.
# Page 78
Linux is cleared! Porting is almost com...
# Page 79
"Wait, the device's LCD isn't showing anything."
# Page 80
Even if Linux boots, the screen stays dark.
# Page 81
The sixth barrier: "LCD".
# Page 82
- Uses a special standard that sends signals only when there's a change on the screen.
- Official drivers in Linux cannot be used.
- LCD model number is unknown, so data format is a mystery.
Honestly, it was very tough.
# Page 83
Found a miraculous line in the Windows boot log:
`Initializing ILI9805 controller 16bit-2`
# Page 84
"ILIxxxx" refers to ILITEK LCD drivers, used in SPI LCDs, etc.
Searching revealed: No datasheet for ILI9805, but found ILI9806.
# Page 85
External view of the ILI9805 chip on the FPC.
# Page 86
Extracting all LCD signals and analyzing with a logic analyzer.
# Page 87
Logic analyzer waveform showing the initialization sequence.
# Page 88
Comparing logic analyzer captures with the ILI9806G datasheet (Rosetta Stone method). Identified the command set.
# Page 89
Success! LCD initialization and pixel transfer in U-Boot. Showing the Tux logo.
# Page 90
Linux implementation also succeeded! Full console output on the Brain screen.
# Page 91
Close-up of the screen showing systemd boot logs.
# Page 92
What is the next barrier?
# Page 93
- Keyboard (Implementation in progress!)
- Sound
- Lid close detection
- Battery management
- Performance tuning
- Stability improvements
Still much more to enjoy.
# Page 94
Recent progress.
# Page 95
Formed the "Brain Hackers" community.
# Page 96
About 70 members on Discord, mostly students. GitHub: https://github.com/brain-hackers
# Page 97
Implementation status:
- Boot Linux without disassembly (Done)
- Boot Linux (U-Boot) from Windows (Done)
- Kernel available via GitHub Actions (Done)
- Keyboard driver implementation (In progress)
- Information gathering on Wiki (In progress)
# Page 98
Planning to provide a distribution that runs Linux just by flashing to an SD card, like Raspberry Pi.
# Page 99
Started live hacking streams on YouTube/Twitter.
# Page 100
Screenshot of a live stream showing code and the device.
# Page 101
Look forward to more hacking from me and Brain Hackers!
# Page 102
Brain Hackers logo.

View File

@@ -1,154 +0,0 @@
# Abstract
This document provides a detailed technical breakdown of the SHARP Brain's boot sequence. It explains the process from the initial Boot ROM execution to the transition from the native Windows CE environment to Linux, detailing methods like using a custom application (BrainLILO) to chain-load U-Boot and exploring theoretical direct Boot ROM execution for deeper integration.
# Page 01
Title: Detailed Explanation - Until Linux Boots on an Electronic Dictionary (詳解・電子辞書で Linux がブートするまで)
Author: Takumi Sueda @puhitaku
Event: Brain Hackers Meetup #1
Date: 2021/10
# Page 02
Self-introduction: Takumi Sueda (@puhitaku). Freelance developer. Announced Linux porting to SHARP Brain in September 2020, founded Brain Hackers in October. Likes: all layers of technology (especially low-level), reverse engineering, beef bowls, and music.
# Page 03
Intro: A photograph of a disassembled SHARP Brain running Debian Linux, showing the console output on the built-in screen.
# Page 04
Recap: What is SHARP Brain?
- Electronic dictionary sold by SHARP running Windows CE.
- Users can add apps built for CE (.exe PE files).
Models:
- Up to 2011: TOSHIBA TMPA910CRAXBG (armv4l) + 64 MiB DRAM, Windows CE.
- 2012-2020: NXP i.MX28 (armv5tej) + 128 MiB DRAM, Windows CE.
- 2021 onwards: NXP i.MX7ULP (armv7-a, armv7e-m) + 128 MiB DRAM, µITRON based RTOS.
# Page 05
Recap: Linux Porting to Brain
- puhitaku succeeded in booting Linux on PW-SH1.
- Brain Hackers community expanded porting to all i.MX28 models.
- Released "Brainux", a custom Debian-based distribution that makes running Linux on Brain as easy as on a Raspberry Pi.
- Current work: Analysis and porting for the new PW-x1 (i.MX7ULP) models.
# Page 06
Main Topic: The Boot Sequence.
# Page 07
Windows → Linux: How it works. Diagram showing the transition from Windows CE to Linux.
# Page 08
Before moving to Linux, let's understand how Windows CE boots. It all starts immediately after reset.
# Page 09
1. Before Windows (Windows 以前).
# Page 10
What does the ARM SoC execute immediately after power-on? Photo of the i.MX28 SoC on the board.
# Page 11
A. Boot ROM.
# Page 12
A. Boot ROM (For i.MX28: On-chip ROM).
# Page 13
Peripheral Access: Immediately after power-on, the ARM core can only access things directly connected to the bus. eMMC, I2C, DRAM (requires init), and SPI are initially inaccessible.
# Page 14
On-chip ROM and On-chip RAM (SRAM) are accessible immediately after reset. The first code is read from On-chip ROM, using On-chip RAM as the workspace.
# Page 15
Boot Selection: The first bootloader in On-chip ROM selects the boot device, initializes peripherals, and loads the next bootloader. Options include USB slave (recovery), I2C, SPI, SSP (eMMC/SD), GPMI (NAND), and JTAG.
# Page 16
On Brain, the One-Time-Programmable ROM is configured to "boot from eMMC". Some models might boot from I2C EEPROM first and then transition to eMMC.
# Page 17
Program Image: The Boot ROM sequentially executes commands described in the "Program Image" located on the eMMC. These commands initialize the DRAM and load/jump to the next bootloader (EBOOT).
# Page 18
EBOOT execution: EBOOT loads the "NK image" (the packaged Windows system) into the previously initialized DRAM and jumps to it.
# Page 19
Result: Windows CE boots successfully.
# Page 20
Summary of the flow before Windows: Reset -> Boot ROM -> Program Image -> EBOOT -> Windows CE.
# Page 21
2. After Windows (Windows 以降).
# Page 22
How to make Linux work "nicely".
# Page 23
Recap: Brain runs Windows CE and allows adding custom .exe (PE) files.
# Page 24
Chain-loading: Executing a mysterious app called "BrainLILO" placed in the "App" folder on the eMMC.
# Page 25
BrainLILO loads the bootloader U-Boot (`u-boot.bin`) into DRAM.
# Page 26
Preparation: BrainLILO disables the MMU (Memory Management Unit) and performs other low-level tasks.
# Page 27
The Jump: Execution jumps to U-Boot. "Goodbye Windows..."
# Page 28
Linux Boot: U-Boot re-initializes the hardware, loads the Linux Image into memory, and jumps to it.
# Page 29
Result: Linux boots successfully.
# Page 30
Summary of the flow after Windows: Windows CE -> BrainLILO -> U-Boot -> Linux.
# Page 31
3. Various Linux Boot Methods (Linux ブートのさまざまな方法).
# Page 32
Pathways to Linux: There isn't just one way to boot Linux. Diagram showing different paths from Boot ROM/Program Image/EBOOT.
# Page 33
3.1. EBOOT → U-Boot.
# Page 34
EBOOT log from PW-SH1: It shows EBOOT trying to open `EDSA1CFG.BIN`. Some models check the external SD for an NK image before reading from internal eMMC (likely for factory testing).
# Page 35
EBOOT chain-boot: By placing a U-Boot image disguised as an NK image (`EDSA1EXE.BIN`) on an external SD card, EBOOT will load and run it.
# Page 36
3.2. Boot ROM → Custom Program Image → U-Boot.
# Page 37
Deep integration: Overwriting the "Program Image" area on the internal eMMC (where EBOOT normally resides) with a custom Program Image containing U-Boot SPL and U-Boot.
# Page 38
Status: Currently, only the EBOOT chain-load and BrainLILO methods are implemented. Custom Program Image is yet to be tackled.
# Page 39
4. Prospects for Custom Program Image (Program Image 自作の展望).
# Page 40
Why do it?
- Install Linux directly to internal eMMC (faster I/O than SD).
- Use SD card purely as external storage.
- Connect Wi-Fi dongles via SDIO (Linux has drivers for many modules).
- Use data pins as general GPIO for custom circuits.
- Essentially turns the Brain into a development board.
# Page 41
5. Summary (まとめ).
# Page 42
Summary:
- Multiple ways to boot Linux on SHARP Brain.
- From Windows via BrainLILO.
- From EBOOT (Windows bootloader).
- Directly from Boot ROM (Theoretical).
- Successfully booting from Boot ROM will open up even more possibilities.
# Page 43
Brain Hackers logo.

View File

@@ -1,235 +0,0 @@
# Abstract
This document explains the process of analyzing the SHARP Brain's boot sequence to install and boot Linux directly from the internal eMMC. It details the reverse engineering of the i.MX28 Boot Mode selection via OTP ROM, extracting the I2C EEPROM configurations, and overwriting the eMMC's boot stream to replace Windows CE completely with U-Boot and Linux.
# Page 01
Title: How to Erase the Identity of an Electronic Dictionary (電子辞書のアイデンティティを消す方法)
Author: Takumi Sueda @puhitaku
Event: 54th Information Science Young Researchers Workshop (#wakate2022)
Date: 2022/08
# Page 02
Self-introduction: Takumi Sueda (@puhitaku). Freelance developer. Developed for HOMMA Inc., etc. Likes: all layers of technology, reverse engineering, 3D printing, and music. Past event participation: 2020 Linux porting to Brain, 2021 TEPRA Lite BLE reverse engineering.
# Page 03
Introduction.
# Page 04
The electronic dictionary introduced today is...
# Page 05
SHARP Brain. Photo of it running Debian Linux.
# Page 06
Recap: Presented "Do Electronic Dictionaries Dream of Embedded Linux?" at the 53rd workshop in 2020.
# Page 07
Slides and articles of previous presentations are available on the author's blog.
# Page 08
What is SHARP Brain?
# Page 09
Features:
- Electronic dictionary brand launched by SHARP in 2008.
- Equipped with Windows CE (until 2020 models).
- Can run custom-compiled .exe files.
- Hacking community established on 2ch shortly after launch.
Apps: App launcher, Offline Wikipedia, matplotlib, visual novels, etc.
# Page 10
Hardware:
- CPU: NXP i.MX283 (ARM926EJ-S, armv5tej) at 454 MHz.
- DRAM: LPDDR 128MB.
- LCD: 800x480, etc.
- SD: SDXC slot available.
- eMMC: 8GB (internal, non-removable).
- Others: Battery, touch panel, magnetic sensor (lid detection).
Composition-wise, it's like a very old and simple first-generation Raspberry Pi with a keyboard, LCD, and battery.
# Page 11
Recent Achievements:
- Succeeded in booting Linux in 2020.
- Founded "Brain Hackers" community, expanded support to more models.
- Released "Brainux", a custom Debian-based distribution.
- Just download the OS image and flash it to an SD card to run Linux.
# Page 12
Even with porting success, many things remained to be done. One of them: "Overwriting Windows with Linux."
# Page 13
SD vs eMMC: Booting from SD card was established, but installing directly to the internal 8GB eMMC was not yet achieved.
# Page 14
Why install Linux to eMMC?
- Better storage performance than SD.
- Free up the SD slot for other uses.
Example SD slot uses:
- Connect Wi-Fi dongles via SDIO (Linux has mainline drivers for some modules).
- Connect custom circuits via GPIO.
- It becomes essentially a development board.
# Page 15
Install Linux into the Brain itself and make it a pure Linux machine! "Good-bye, Windows!! Good-bye, Electronic Dictionary!!"
# Page 16
What is needed to boot Linux from eMMC?
# Page 17
A powered-on computer goes through a process called "Boot" to initialize hardware and prepare to run software.
# Page 18
When Brain's power is turned on, several "bootloaders" perform the boot process, eventually starting Windows CE.
# Page 19
The flow from the moment power is applied until the system finishes booting is called the "Boot Sequence."
# Page 20
To achieve eMMC boot, one must trace the connection between the SoC behavior and bootloaders from power-on and appropriately overwrite that sequence.
# Page 21
Explanation and Analysis of the Boot Sequence: Reset ~ Boot ROM.
# Page 22
Photo of the i.MX28 SoC. What does it execute immediately after power-on?
# Page 23
A. Boot ROM.
# Page 24
A. Boot ROM (called On-chip ROM in i.MX28).
# Page 25
Immediately after reset, external peripherals are uninitialized and unusable. The CPU can generally only access locations directly connected by the bus. eMMC, DRAM, I2C, and SPI are inaccessible.
# Page 26
On-chip ROM and On-chip RAM (SRAM) are accessible via the bus immediately after reset. The CPU executes the instruction sequence in On-chip ROM using On-chip RAM as its workspace.
# Page 27
The CPU uses the Boot ROM (the first bootloader) to select the boot device, initialize peripherals, and read the next bootloader. Devices include USB recovery, I2C, SPI, SSP (eMMC/SD), GPMI (NAND), and JTAG.
# Page 28
The Boot ROM decides which external device to read the next bootloader from by looking at the "Boot Mode" written in the "One-Time Programmable (OTP) ROM".
# Page 29
One-Time Programmable (OTP) ROM:
- Non-erasable ROM implemented in the SoC's semiconductor, programmable only once.
- The first area used to convey the developer's intent to the CPU.
- Device-specific settings for boot devices are also written here.
"Let's look inside the OTP to find the first boot device!"
# Page 30
Analysis of the OTP settings.
# Page 31
Recap: Brain allows running custom exe files.
# Page 32
Using a "divine tool" called Scalpel that can see the entire memory space from Windows CE.
# Page 33
According to the datasheet, the 8 MSB bits of the 32-bit value at address 0x8002C1A0 is the BOOT_MODE. Reading it with Scalpel results in 0x01 (0b00000001).
# Page 34
Referring to the i.MX28 "Boot Mode Selection Map" table in the datasheet: BOOT_MODE 0bXXX00001 corresponds to I2C0 master, 3.3 V.
# Page 35
Conclusion: The CPU is configured to read from an EEPROM connected via I2C first.
# Page 36
Extracting and reading the EEPROM content.
# Page 37
Question: "Where is the EEPROM on the Brain board?" (Photo of the mainboard).
# Page 38
Answer: Located at U502 (highlighted in a pink box).
# Page 39
Identifying the EEPROM: Probing pins with an oscilloscope while cycling power. Found 100kHz/400kHz clocks characteristic of I2C. Narrowed down the part number via Digi-Key footprint search: VSON package, 2mm x 3mm, 0.5mm thick (Rohm). Marking "4G3" identifies it as Rohm BR24G32 (4KB).
# Page 40
Reading it: Soldered 0.2mm polyurethane wires under a stereomicroscope and read with a Saleae logic analyzer.
# Page 41
EEPROM Content: Contains a "Boot Stream" (SB) structure. These are commands sequentially executed by the Boot ROM. Using `sbtoelf` tool from the Rockbox repository and Ghidra to disassemble the binary. Example commands: LOAD, FILL, CALL, MODE.
# Page 42
Flow of binary deployment in SRAM after executing SB commands: CALL command -> Jump to entry point 0xE61C (Instructions armv5tej) -> Return.
# Page 43
What the Boot ROM does after reading EEPROM:
- Writes specific settings to eMMC peripherals.
- Transitions to eMMC boot mode (MODE command to 0x09).
- Once in eMMC boot mode, it parses the SB found on the eMMC (similar to the process with EEPROM).
# Page 44
Summary: The CPU reads the I2C EEPROM to configure eMMC settings before transitioning to eMMC boot.
# Page 45
Extracting and reading the eMMC content.
# Page 46
Dumping eMMC is easy: Boot Linux from SD and use `dd` on `/dev/mmcblk0`. Looking at the Master Boot Record (MBR) for an entry with i.MX28 specific partition type 0x53. The beginning of that partition contains a pointer (sector number) to the SB.
# Page 47
Structure of data related to boot on eMMC: Sector 0 (MBR) -> Sector 256 (SB) -> Sector 2304 (?) -> Sector 198912 (FAT32 partition with Windows CE). Flow: 1. Read MBR, 2. Read & run SB, 3. Run EBOOT.
# Page 48
Summary: The CPU reads eMMC to execute EBOOT (Windows CE bootloader).
# Page 49
Transition to Windows: EBOOT extracts the "NK image" (packaged Windows system) from eMMC to DRAM and jumps to it.
# Page 50
The boot sequence from reset to Windows CE is completely clarified! Reset -> On-chip ROM -> I2C EEPROM -> eMMC -> Windows CE.
# Page 51
Deciding which part of the boot sequence to overwrite.
# Page 52
Where to put the custom binary to boot Linux?
- I2C EEPROM SB: OS-independent (only does hardware adjustments).
- eMMC SB: Contains Windows CE's EBOOT (OS-dependent).
Strategy: Overwrite the content of eMMC with custom data.
# Page 53
Experiment: Use USB boot mode to transition to eMMC boot and start Windows.
# Page 54
"USB boot mode" allows booting from a PC without involving the EEPROM. If a PC-injected SB that merely transitions to eMMC boot succeeds in starting Windows CE, then the EEPROM content is confirmed to be OS-independent. (Using U-Boot's `mkimage` to generate SB).
# Page 55
Forcing USB boot mode by shorting the pads (JP501) next to the eMMC while connecting USB.
# Page 56
Result: Success. Decided to keep the EEPROM as is and overwrite the eMMC content.
# Page 57
Creating an eMMC image containing the bootloader.
# Page 58
Using U-Boot (Das U-Boot), commonly used in embedded Linux. Modified it to read from eMMC instead of SD. Modified the OS image generation script to include SB and U-Boot.
# Page 59
Structure of the OS image for eMMC: MBR (Entry 0: FAT32, Entry 1: SB, Entry 2: Ext4) -> Sector 2048 (FAT32 partition with Tux logo) -> Sector 20800 (SB with U-Boot) -> Sector 24800 (Ext4 rootfs). Flow: 1. Read MBR, 2. Read & run SB, 3. Run U-Boot.
# Page 60
Writing the eMMC image and booting.
# Page 61
Flashing eMMC: Just use `dd` on the actual device using an eMMC image hidden on a Linux-bootable SD card. Don't forget backups! If flashing fails, it can be recovered via USB boot + serial (UART) if you can do fine soldering.
# Page 62
Connecting UART (serial) to the development PC. Photo of the tiny wires soldered to test points and connected to a USB-Serial adapter.
# Page 63
Success! Console output shows Linux 5.4.149 booting. `mount | grep mmcblk0` shows `/dev/mmcblk0p3` mounted as rootfs (ext4).
# Page 64
SHARP Brain has stepped into its new life as a Linux machine, leaving its identity as an electronic dictionary behind.
# Page 65
Summary.
# Page 66
Summary: Even if implementation varies by SoC or architecture, the concept of bootloaders and boot sequences is common to all computers. If you want to fundamentally change the behavior of your hardware, grab a soldering iron and dig into the boot sequence.

View File

@@ -1,141 +0,0 @@
# Abstract
This document provides a technical deep dive into Linux suspend mechanisms, focusing on the implementation of Suspend-to-RAM for the SHARP Brain electronic dictionary. It explains the transition and resume flows, the required power management and wakeup interrupt handler implementations, and the specific challenges faced, such as handling I2C-based key events and device tree configurations for power regulators.
# Page 01
Title: Learning Linux Suspend with an Electronic Dictionary (電子辞書で学ぶ Linux のサスペンド)
Author: Takumi Sueda aka @puhitaku
Event: Information Science Young Researchers Workshop Spring Edition 2023 (#wakate2023s)
Date: 2023/04
# Page 02
Self-introduction: Takumi Sueda (@puhitaku). Freelance developer. Working for HOMMA Inc. Author, Security Camp instructor, OSS license consultant, etc. Likes: low-level technology, reverse engineering, 3D printing, music. Attending the workshop almost every year since 2014.
# Page 03
Writing a series "Let's Run Linux on an Electronic Dictionary" for Nikkei Linux magazine. Part 3 will be in the May issue.
# Page 04
The target device: SHARP Brain. Photo showing it running Debian Linux.
# Page 05
Features of SHARP Brain:
- Electronic dictionary brand launched in 2008.
- Equipped with Windows CE (up to 2020 models).
- Community established since launch.
- Users can run custom exe files.
# Page 06
Hardware:
- CPU: NXP i.MX283 (ARM926EJ-S, 454MHz).
- DRAM: LPDDR 128MB.
- LCD: 800x480, etc.
- SDXC slot.
- eMMC: 8GB internal.
- Battery, touch panel, magnetic sensor.
Similar to a primitive Raspberry Pi with a keyboard, LCD, and battery.
# Page 07
U-Boot and Linux porting:
- Success in 2020.
- Released "Brainux" distribution (bootable from SD card).
Implemented drivers/features:
- LCD (newly implemented).
- Keyboard (newly implemented).
- Touch panel.
- SD / eMMC R/W.
- Beep sounds via piezo element.
# Page 08
Unimplemented features:
- Power management (Sleep, cpufreq).
- Sound.
# Page 09
Focus of today's talk: Power management, specifically "Sleep".
# Page 10
What is "Sleep"?
# Page 11
There are several types of "Sleep" (system-wide sleep) in Linux:
- Suspend-to-Idle.
- Standby.
- Suspend-to-RAM.
- Hibernation.
Generally, lower items consume less power.
# Page 12
1. Suspend-to-Idle: Purely software-based sleep that just idles the CPU. Stops userspace, timekeeping, and I/O.
2. Standby: Powers off unused CPUs during boot to save more power.
3. Suspend-to-RAM: Saves CPU and device state to DRAM and powers off almost all hardware except DRAM and resume logic.
4. Hibernation: Saves state to persistent storage and shuts down. Saves all hardware.
# Page 13
For an electronic dictionary, Suspend-to-RAM is the target to balance power reduction and resume time.
# Page 14
Flow of Suspend-to-RAM transition and resume.
# Page 15
Flow of transitioning to Suspend-to-RAM:
1. Notify the whole system, preparing kernel subsystems for sleep.
2. Freeze tasks.
3. Configure devices to not handle interrupts except those for suspend/resume.
4. Stop non-boot CPUs (tasks/IRQs migrate to Boot CPU).
5. Disable scheduler tick and stop context switching.
6. Hand control to platform-specific firmware to transition to low-power state or cut power (except for RAM).
7. Sleep until an interrupt from a resume device (e.g., keyboard) arrives.
# Page 16
Flow of resuming from Suspend-to-RAM:
1. Interrupt from a resume device arrives.
2. CPU resumes and handles the interrupt (platform-dependent process).
3. Control returns to the kernel.
4. Resume kernel core, tick, and scheduling.
5. Wake up non-boot CPUs.
6. Wake up devices and restore IRQs.
7. Thaw tasks.
8. Send resume notifications to the whole system.
# Page 17
What is needed to implement Suspend-to-RAM on new hardware?
# Page 18
Two essential elements for Suspend-to-RAM:
1. Power Management: Implement functions in the driver's `dev_pm_ops` structure to gracefully cut power upon suspend notification. Describe device-regulator (power) relationships in the Device Tree. (e.g., SoC internal regulators, MOSFETs for external hardware, SPI/I2C peripherals).
2. Wakeup Interrupt Handler: Implement procedures in the Interrupt Service Routine (ISR) to instruct the Power Management Subsystem to resume when a valid wakeup input arrives. (e.g., magnetic sensor for lid, GPIO for power button).
# Page 19
Side responsible for executing Suspend-to-RAM:
- Call stack overview starting from writing to `/sys/power/state`.
- Device Tree example: Describing the relationship between the LCD panel and its DVDD/AVDD power supplies. The kernel uses this info to toggle power.
# Page 20
Communication between the wakeup ISR and the suspend execution code:
1. Driver's ISR calls `pm_wakeup_event()` to increment a counter in the PM subsystem.
2. `suspend_enter` checks the counter after the CPU PC returns. If incremented, it exits the loop; otherwise, it puts the CPU back to sleep.
Conclusion: Interrupts unrelated to resume are ignored.
# Page 21
Implementation status on SHARP Brain.
# Page 22
Suspend-to-RAM is partially achieved but still a work in progress:
- [Check] Execution of Suspend-to-RAM.
- [Check] Resume via power button (on models where key matrix is directly read via GPIO).
- [WIP] Resume via power button (on models where key events are read from MCU via I2C).
- Problem: I2C peripheral-level interrupt wakes the device for any key press. Most peripherals are sleeping, so ISR capabilities are limited.
- Might need reverse engineering of how Windows handles this.
- [WIP] Power control for LCD, etc. (Describe GPIOs connected to FET gates/ENABLE pins as regulators in Device Tree).
- [WIP] Verifying power consumption reduction.
- [WIP] Release as OS image.
# Page 23
Q&A Log:
Q: In what order do kthread and userspace processes freeze?
A: `suspend_prepare` -> `suspend_freeze_processes`. Userspace freezes first.
Q: What is the difference in power saving between the 4 methods?
A: Depends on the system. On Brain (small SoC), the difference between Suspend-to-Idle and Standby is small (115mA -> 86mA). Suspend-to-RAM's impact will be measured after implementing LCD power control.
# Page 24
References: Bootlin Elixir (Linux source browser), Mainline Linux documentation (suspend-flows.rst, sleep-states.rst).
Diagram showing the interaction between Brain and a development PC.

View File

@@ -1,15 +0,0 @@
This directory contains PDFs and texts that explains the inside of SHARP Brain, a series of e-dictionary sold by SHARP, for coding agents.
For text searching purpose, all PDFs are converted and explained into a corresponding Markdown with the same file name but the extension.
# Converting PDF to md
If the user of a coding agent requests the agent to convert the PDF into text, the agent must follow the rule:
- The slide number and the position of the Markdown document must be preserved; to achieve this, the Markdown document must have first level headers with the page number like "# Page 01" .
- The Markdown version is like a "text-only technical document version" of the PDF. Not only just converting texts in the PDF, agents must explain the topic based on the understanding of the visual slides.
- Future session of coding agents will understand the thing by reading the Markdown. Make the text simple and not redundant.
- Describe an abstract in the beginning of the Markdown.
- The resulting output must have the same file name as the original PDF but the extension ".md".

View File

@@ -1,55 +0,0 @@
# Objective
This repository contains anything necessary to build an SD card image file of Brainux - a Debian-based Linux distribution for a series of e-dictionary "Brain" series sold by SHARP, a Japanese manufacturer - and now I'm going to add the root AGENTS.md for automated development.
Explore the repository to generate appropriate AGENTS.md that will help CC for future runs. AGENTS.md should contain project memory and instructions for CC.
# Hints and instructions about the repo's structure
- Knowledge useful to understand the inside of SHARP Brain and its hacking scene will be contained in /docs/knowledge.
- The definition of GitHub Actions workflow (/.github/workflows/build.yml) will be useful to understand how it enters into the build procedure.
- The repo contains some submodules. File search or string search at the repo's root is not recommended.
- Linux (linux-brain)
- U-Boot (u-boot-brain)
- BrainLILO (chain-boot tool specially made for specific older models)
- boot4u (chain-boot tool specially made for specific newer models)
- buildroot (to build an alternative lightweight rootfs, instead of the default Debian)
- nkbin_maker (converter to turn U-Boot's ELF into an nk.bin that Windows CE's EBOOT bootloader understands)
# My typical usage of buildbrain on the development of Brainux
## Develop Linux kernel
1. `cd` into linux-brain
2. Checkout an appropriate branch
- The default branch is `brain`. When I edit the code, I make another branch from `brain`.
3. Edit the code
4. `cd ..` and go up into buildbrain
5. `make lclean ldefconfig lbuild` to start a clean build
- Run `make lmenuconfig` to edit the .config (which is not a suitable way for coding agents due to TUI)
6. Copy the resulting kernel `/linux-brain/arch/arm/boot/zImage` and `/linux-brain/arch/arm/boot/dts/imx28-pw*.dtb` into an SD card and run it on a real machine
6. Continue try-and-error loop; make another change to the code, `make lbuild`, and run it
7. `cd linux-brain` and commit the change
- Commit message must comply the kernel's convention; watch surrounding files and commits to infer the format
8. File a PR and ask review
9. Merge it
## Develop U-Boot
It is mostly the same as Linux kernel.
## Update Brainux's configuration script and file
1. Checkout an appropriate branch
2. Edit scripts and files in os-brainux
3. Run `make brainux` to build the root filesystem
- ... or run `make image/sd.img` to create a complete SD image
4. Copy the root filesystem to an SD card's second partition or write the entire image to an SD card
5. Repeat 3 and 4
6. Commit the change, file a PR, ask a review, and merge it

View File

@@ -1,23 +0,0 @@
*** exeopener ***
MIT License
Copyright (c) 2022 Chiharu Shirasaka
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -5,31 +5,27 @@ JOBS=$(nproc)
REPO=$(git rev-parse --show-toplevel) REPO=$(git rev-parse --show-toplevel)
WORK=${REPO}/image/work WORK=${REPO}/image/work
LINUX=${REPO}/linux-brain LINUX=${REPO}/linux-brain
ROOTFS=$1 IMG=${REPO}/image/sd.img
IMG_NAME=$2
IMG=${REPO}/image/${IMG_NAME}
SIZE_M=$3
export CROSS_COMPILE=arm-linux-gnueabi- export CROSS_COMPILE=arm-linux-gnueabi-
mkdir -p ${WORK} mkdir -p ${WORK}
mkdir -p ${WORK}/lilobin mkdir -p ${WORK}/lilobin
for i in "a7200" "a7400" "sh1" "sh2" "sh3" "sh4" "sh5" "sh6" "sh7"; do # for i in "g5300" "sh1" "sh2" "sh3" "sh4" "sh5" "sh6" "sh7"; do
for i in "sh1"; do
NUM=$(echo $i | sed -E 's/sh//g') NUM=$(echo $i | sed -E 's/sh//g')
make -C ${REPO}/u-boot-brain distclean pw${i}_defconfig make -C ${REPO}/u-boot-brain distclean pw${i}_defconfig
make -j${JOBS} -C ${REPO}/u-boot-brain u-boot.bin make -j${JOBS} -C ${REPO}/u-boot-brain u-boot.sb
${REPO}/nkbin_maker/bsd-ce ${REPO}/u-boot-brain/u-boot.bin #${REPO}/nkbin_maker/bsd-ce ${REPO}/u-boot-brain/u-boot.bin
case $i in case $i in
"a7200") "g5300")
mv ${REPO}/nk.bin ${WORK}/edna3exe.bin mv ${REPO}/nk.bin ${WORK}/edna3exe.bin
mv ${REPO}/u-boot-brain/u-boot.bin ${WORK}/lilobin/gen2.bin;; mv ${REPO}/u-boot-brain/u-boot.bin ${WORK}/lilobin/gen2.bin;;
"a7400")
mv ${REPO}/u-boot-brain/u-boot.bin ${WORK}/lilobin/gen2_7400.bin;;
"sh1" | "sh2" | "sh3") "sh1" | "sh2" | "sh3")
mv ${REPO}/nk.bin ${WORK}/edsa${NUM}exe.bin # mv ${REPO}/nk.bin ${WORK}/edsa${NUM}exe.bin
mv ${REPO}/u-boot-brain/u-boot.bin ${WORK}/lilobin/gen3_${NUM}.bin;; mv ${REPO}/u-boot-brain/u-boot.sb ${WORK}/lilobin/gen3_${NUM}.sb;;
"sh4" | "sh5" | "sh6" | "sh7") "sh4" | "sh5" | "sh6" | "sh7")
mv ${REPO}/nk.bin ${WORK}/edsh${NUM}exe.bin mv ${REPO}/nk.bin ${WORK}/edsh${NUM}exe.bin
mv ${REPO}/u-boot-brain/u-boot.bin ${WORK}/lilobin/gen3_${NUM}.bin;; mv ${REPO}/u-boot-brain/u-boot.bin ${WORK}/lilobin/gen3_${NUM}.bin;;
@@ -39,36 +35,41 @@ for i in "a7200" "a7400" "sh1" "sh2" "sh3" "sh4" "sh5" "sh6" "sh7"; do
esac esac
done done
dd if=/dev/zero of=${IMG} bs=1M count=${SIZE_M} dd if=/dev/zero of=${IMG} bs=1M count=2048
START1=2048 START1=2048
SECTORS1=$((1024 * 1024 * 64 / 512)) SECTORS1=$((1024 * 1024 * 64 / 512))
START2=$((2048 + ${SECTORS1})) START2=$((2048 + ${SECTORS1}))
SECTORS1=$((1024 * 1024 * 8 / 512))
START2=$((2048 + ${SECTORS1} + ${SECTORS2}))
cat <<EOF > ${WORK}/part.sfdisk cat <<EOF > ${WORK}/part.sfdisk
${IMG}1 : start=${START1}, size=${SECTORS1}, type=b ${IMG}1 : start=${START1}, size=${SECTORS1}, type=b
${IMG}2 : start=${START2}, type=83 ${IMG}2 : start=${START2}, size=${SECTORS2}, type=53
${IMG}3 : start=${START3}, type=83
EOF EOF
sfdisk ${IMG} < ${WORK}/part.sfdisk sfdisk ${IMG} < ${WORK}/part.sfdisk
sudo kpartx -av ${IMG} sudo kpartx -av ${IMG}
LOOPDEV=$(losetup -l | grep ${IMG_NAME} | grep -o 'loop.' | tail -n 1) LOOPDEV=$(losetup -l | grep sd.img | grep -o 'loop.' | tail -n 1)
${REPO}/image/mk_hdr.sh `fdisk -lu /dev/${LOOPDEV} | awk '$6==53 {print $2}'` 1 > ${WORK}/header.bin
dd if=${WORK}/header.bin of=/dev/${LOOPDEV}p2 ibs=512 conv=sync
dd if=${WORK}/lilobin/gen3_1.sb of=/dev/${LOOPDEV}p2 ibs=512 obs=512 seek=1 conv=sync
sudo mkfs.fat -n boot -F32 -v -I /dev/mapper/${LOOPDEV}p1 sudo mkfs.fat -n boot -F32 -v -I /dev/mapper/${LOOPDEV}p1
sudo mkfs.ext4 -L rootfs /dev/mapper/${LOOPDEV}p2 sudo mkfs.ext4 -L rootfs /dev/mapper/${LOOPDEV}p3
mkdir -p ${WORK}/p1 ${WORK}/p2 mkdir -p ${WORK}/p1 ${WORK}/p3
sudo mount -o utf8=true /dev/mapper/${LOOPDEV}p1 ${WORK}/p1 sudo mount -o utf8=true /dev/mapper/${LOOPDEV}p1 ${WORK}/p1
sudo mount /dev/mapper/${LOOPDEV}p2 ${WORK}/p2 sudo mount /dev/mapper/${LOOPDEV}p3 ${WORK}/p3
echo ${BRAINUX_VERSION} > ${WORK}/brainux_version
sudo cp ${WORK}/brainux_version ${WORK}/p1/
sudo cp ${LINUX}/arch/arm/boot/zImage ${WORK}/p1/ sudo cp ${LINUX}/arch/arm/boot/zImage ${WORK}/p1/
sudo cp ${LINUX}/arch/arm/boot/dts/imx28-pw*.dtb ${WORK}/p1/ sudo cp ${LINUX}/arch/arm/boot/dts/imx28-pw*.dtb ${WORK}/p1/
sudo mkdir -p ${WORK}/p1/nk # sudo mkdir -p ${WORK}/p1/nk
sudo cp ${WORK}/*.bin ${WORK}/p1/nk/ # sudo cp ${WORK}/*.bin ${WORK}/p1/nk/
make -C ${REPO}/brainlilo make -C ${REPO}/brainlilo
@@ -78,16 +79,16 @@ sudo touch "${LILO}/index.din"
sudo touch "${LILO}/AppMain.cfg" sudo touch "${LILO}/AppMain.cfg"
sudo cp ${REPO}/brainlilo/*.dll "${LILO}/" sudo cp ${REPO}/brainlilo/*.dll "${LILO}/"
sudo cp ${REPO}/brainlilo/BrainLILO.exe "${LILO}/AppMain_.exe" sudo cp ${REPO}/brainlilo/BrainLILO.exe "${LILO}/AppMain_.exe"
gzip -cd ${REPO}/image/exeopener.exe.gz > ${REPO}/image/exeopener.exe gzip -d ${REPO}/image/exeopener.exe.gz
sudo cp ${REPO}/image/exeopener.exe "${LILO}/AppMain.exe" sudo cp ${REPO}/image/exeopener.exe "${LILO}/AppMain.exe"
sudo mkdir -p ${WORK}/p1/loader sudo mkdir -p ${WORK}/p1/loader
sudo cp ${WORK}/lilobin/*.bin ${WORK}/p1/loader/ sudo cp ${WORK}/lilobin/*.bin ${WORK}/p1/loader/
sudo cp -ra ${REPO}/${ROOTFS}/* ${WORK}/p2/ sudo cp -ra ${REPO}/brainux/* ${WORK}/p3/
sudo umount ${WORK}/p1 ${WORK}/p2 sudo umount ${WORK}/p1 ${WORK}/p3
sudo kpartx -d ${IMG} sudo kpartx -d ${IMG}
rmdir ${WORK}/p1 ${WORK}/p2 rmdir ${WORK}/p1 ${WORK}/p3

57
image/build_image_emmc.sh Executable file
View File

@@ -0,0 +1,57 @@
#!/bin/bash
set -uex -o pipefail
JOBS=$(nproc)
REPO=$(git rev-parse --show-toplevel)
WORK=${REPO}/image/work
LINUX=${REPO}/linux-brain
IMG=${REPO}/image/sd.img
export CROSS_COMPILE=${CROSS_COMPILE:="arm-linux-gnueabi-"}
mkdir -p ${WORK}
mkdir -p ${WORK}/lilobin
for i in "sh1"; do
NUM=$(echo $i | sed -E 's/sh//g')
make -C ${REPO}/u-boot-brain distclean pw${i}_defconfig
make -j${JOBS} -C ${REPO}/u-boot-brain u-boot.sb u-boot.bin
case $i in
"sh1" | "sh2" | "sh3")
mv ${REPO}/u-boot-brain/u-boot.sb ${WORK}/lilobin/gen3_${NUM}.sb
mv ${REPO}/u-boot-brain/u-boot.bin ${WORK}/lilobin/gen3_${NUM}.bin;;
*)
echo "WTF: $i"
exit 1;;
esac
done
dd if=/dev/zero of=${IMG} bs=1M count=96
START1=2048
SECTORS1=$((1024 * 1024 * 64 / 512))
START2=$((2048 + ${SECTORS1}))
SECTORS2=$((1024 * 1024 * 8 / 512))
START3=$((2048 + ${SECTORS1} + ${SECTORS2}))
cat <<EOF > ${WORK}/part.sfdisk
${IMG}1 : start=${START1}, size=${SECTORS1}, type=b
${IMG}2 : start=${START2}, size=${SECTORS2}, type=53
${IMG}3 : start=${START3}, type=83
EOF
sfdisk ${IMG} < ${WORK}/part.sfdisk
sudo kpartx -av ${IMG}
LOOPDEV=$(losetup -l | grep sd.img | grep -o 'loop.' | tail -n 1)
${REPO}/image/mk_hdr.sh `fdisk -lu /dev/${LOOPDEV} | awk '$6==53 {print $2}'` 1 > ${WORK}/header.bin
dd if=${WORK}/header.bin of=/dev/${LOOPDEV}p2 ibs=512 conv=sync
dd if=${WORK}/lilobin/gen3_1.sb of=/dev/${LOOPDEV}p2 ibs=512 obs=512 seek=1 conv=sync
# sudo mount -o utf8=true /dev/mapper/${LOOPDEV}p1 ${WORK}/p1
# sudo mount /dev/mapper/${LOOPDEV}p2 ${WORK}/p2
sudo kpartx -d ${IMG}

148
image/mk_hdr.sh Executable file
View File

@@ -0,0 +1,148 @@
#!/bin/bash
# mk_hdr.sh
# Redistributed URL: https://github.com/embeddedTS/linux-2.6.35.3-imx28/blob/master/mk_hdr.sh
#
# This program is distributed with mk_mx28_sd that has the text of 3-Clause BSD License.
# Both are considered to be licenced under the same agreement so we put the text here.
# Copyright (c) 2010 Freescale Semiconductor, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# o Redistributions of source code must retain the above copyright notice, this list
# of conditions and the following disclaimer.
#
# o Redistributions in binary form must reproduce the above copyright notice, this
# list of conditions and the following disclaimer in the documentation and/or
# other materials provided with the distribution.
#
# o Neither the name of Freescale Semiconductor, Inc. nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Usage: make_boot <base_sector> <num_sb_files>
#
# where
#
# <base_sector> is the first sector _of the boot stream partition (i.e. /sd#2 or /sd#3, etc)
# <num_sb_files> is the # of boot stream blocks (currently only 1 supported)
#[ $1 = ] && { echo -e " error - boot partition start sector missing" ; exit };
#[ $2 = ] && { echo -e " error - # of bootable images in .sb file missing" ; exit };
# Future usage: make_boot <dev_partition> <sb_file_tag,sb_sector_offset> <sb_file_tag2, base_addr2> ...
#
# Where base sector comes from MBR, and sb_sector_offset is an offset from start of boot-partition, not absolute sector.
#Script Vars
base_sector=$1
numbootstreams=$2
primary=0
secondary=0
#########################################
# out_byte args...
#
# this function writes the binary value to stdout of each argument in the order given
# i.e. out_byte 0 1 2 3 will echo "\x00\x01\x02\x03" to stdout (w/o terminating null )
function out_byte(){
for val in $*
do
# echo -e "byte=$val"
echo -en "\\x$(printf %02x $val)"
done
}
function out_u32_le()
{
for val32 in $*
do
val=$(($val32))
b0=$((val % (2**8)))
val=$((val / (2**8)))
b1=$((val % (2**8)))
val=$((val / (2**8)))
b2=$((val % (2**8)))
val=$((val / (2**8)))
b3=$((val % (2**8)))
### Keep around for debug/verbose output
# printf "$val32 ==> %02x%02x%02x%02x\n" $b0 $b1 $b2 $b3
### Output the bytes in binary form
#
out_byte $b0 $b1 $b2 $b3
done
}
function out_bcb ()
{
signature=0x00112233
primary_tag=$1
secondary_tag=$2
num_bsb=$3
out_u32_le signature primary_tag secondary_tag num_bsb
}
# usage: out_bsb tag base_sector
# where base_sector is relative to partition
# i.e. if partition starts on lba 63 & first boot stream, base_sector = 1, not 64
# This function will automatically compute the absolute base sector.
function out_bsb
{
abs_sector=$(($2 + $base_sector))
# unused0
out_u32_le 0
# unused1
out_u32_le 0
# tag boot stream tag
out_u32_le $1
# boot stream base sector (absolute)
out_u32_le $abs_sector
# unused2
out_u32_le 0
}
###############################
# Send header output to std out
###############################
# Output boot stream signature & info
# out_u32_le signature primary secondary numbootstreams
out_bcb primary secondary numbootstreams
# Output .sb starting sector info
# out_u32_le unused0 unused1 tag base_sector unused2
out_bsb primary 1
# Output bsb for sb #2
#out_bsb tag_[p|s] base_sector_2
# Output bsb for sb #n
# out_bsb tag_[p|s] base_sector_n
#

View File

@@ -1,10 +0,0 @@
#!/bin/bash
set -uex -o pipefail
SRC=$1
DST=$2
install -g root -o root -m 0644 $SRC/lib/systemd/system/boot.mount $DST/lib/systemd/system/boot.mount
install -g root -o root -m 0644 $SRC/lib/systemd/system/ethernet_gadget.service $DST/lib/systemd/system/ethernet_gadget.service
install -g root -o root -m 0755 $SRC/usr/bin/enable_ethernet_gadget $DST/usr/bin/enable_ethernet_gadget

View File

@@ -5,8 +5,10 @@ set -uex -o pipefail
SRC=$1 SRC=$1
DST=$2 DST=$2
install -g root -o root -m 0644 $SRC/usr/lib/os-release $DST/usr/lib/os-release
install -g root -o root -m 0644 $SRC/etc/issue $DST/etc/issue
install -g root -o root -m 0644 $SRC/etc/issue.net $DST/etc/issue.net
install -g root -o root -m 0644 $SRC/etc/motd $DST/etc/motd install -g root -o root -m 0644 $SRC/etc/motd $DST/etc/motd
install -g root -o root -m 0440 $SRC/etc/sudoers $DST/etc/sudoers
install -g root -o root -m 0644 $SRC/etc/X11/xorg.conf $DST/etc/X11/xorg.conf install -g root -o root -m 0644 $SRC/etc/X11/xorg.conf $DST/etc/X11/xorg.conf
install -g root -o root -m 0644 $SRC/etc/X11/Xsession.d/96calibrate $DST/etc/X11/Xsession.d/96calibrate install -g root -o root -m 0644 $SRC/etc/X11/Xsession.d/96calibrate $DST/etc/X11/Xsession.d/96calibrate

View File

@@ -0,0 +1,2 @@
Brainux GNU/Linux 10 \n \l

View File

@@ -0,0 +1 @@
Brainux GNU/Linux 10

View File

@@ -1,27 +0,0 @@
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset,pwfeedback
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Host alias specification
# User alias specification
# Cmnd alias specification
# User privilege specification
root ALL=(ALL:ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
# See sudoers(5) for more information on "@include" directives:
@includedir /etc/sudoers.d

View File

@@ -1,10 +0,0 @@
[Unit]
Description=Mount boot partition
[Mount]
What=/dev/mmcblk1p1
Where=/boot
Options=ro
[Install]
WantedBy=multi-user.target

View File

@@ -1,9 +0,0 @@
[Unit]
Description=Enable Ethernet USB Gadget
[Service]
Type=oneshot
ExecStart=/usr/bin/enable_ethernet_gadget
[Install]
WantedBy=multi-user.target

View File

@@ -1,29 +0,0 @@
#!/bin/sh
g=/sys/kernel/config/usb_gadget/eth
mkdir ${g}
echo "0x0200" > ${g}/bcdUSB
echo "0x0200" > ${g}/bcdDevice
mkdir -p ${g}/strings/0x409
echo "0123456789" > ${g}/strings/0x409/serialnumber
echo "SHARP" > ${g}/strings/0x409/manufacturer
echo "Brain" > ${g}/strings/0x409/product
mkdir -p ${g}/configs/c.1/strings/0x409
echo "NCM Config" > ${g}/configs/c.1/strings/0x409/configuration
echo 250 > ${g}/configs/c.1/MaxPower
mkdir ${g}/functions/ncm.usb0
echo "8a:15:8b:44:3a:02" > ${g}/functions/ncm.usb0/dev_addr
echo "8a:15:8b:44:3a:01" > ${g}/functions/ncm.usb0/host_addr
ln -s ${g}/functions/ncm.usb0 ${g}/configs/c.1/
echo "ci_hdrc.0" > ${g}/UDC
sleep 1
ifconfig usb0 up
dhclient

View File

@@ -0,0 +1,9 @@
PRETTY_NAME="Brainux GNU/Linux 11 (bullseye)"
NAME="Brainux GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://github.com/brain-hackers/README"
SUPPORT_URL="https://github.com/brain-hackers/buildbrain"
BUG_REPORT_URL="https://github.com/brain-hackers/buildbrain"

View File

@@ -20,12 +20,12 @@ else
fi fi
cat <<EOF > /etc/apt/sources.list cat <<EOF > /etc/apt/sources.list
deb http://${REPO}/debian trixie main contrib non-free deb http://${REPO}/debian bullseye main contrib non-free
deb-src http://${REPO}/debian trixie main contrib non-free deb-src http://${REPO}/debian bullseye main contrib non-free
deb http://${REPO}/debian trixie-updates main contrib non-free deb http://${REPO}/debian bullseye-updates main contrib non-free
deb-src http://${REPO}/debian trixie-updates main contrib non-free deb-src http://${REPO}/debian bullseye-updates main contrib non-free
deb http://${REPO_SECURITY}/debian-security trixie-security/updates main contrib non-free deb http://${REPO_SECURITY}/debian-security bullseye-security/updates main contrib non-free
deb-src http://${REPO_SECURITY}/debian-security trixie-security/updates main contrib non-free deb-src http://${REPO_SECURITY}/debian-security bullseye-security/updates main contrib non-free
EOF EOF
cat <<EOF > /etc/apt/apt.conf.d/90-norecommend cat <<EOF > /etc/apt/apt.conf.d/90-norecommend
@@ -55,10 +55,10 @@ echo "brain" > /etc/hostname
# Install packagecloud repository # Install packagecloud repository
# Reference: https://packagecloud.io/brainhackers/brainux/install # Reference: https://packagecloud.io/brainhackers/brainux/install
# curl, ca-certificates: downloads the GPG key from packagecloud # curl: downloads the GPG key from packagecloud
# gnupg, debian-archive-keyring: packagecloud verification dependency # gnupg, debian-archive-keyring: packagecloud verification dependency
DEBIAN_FRONTEND=noninteractive \ DEBIAN_FRONTEND=noninteractive \
apt install -y curl ca-certificates gnupg debian-archive-keyring apt install -y curl gnupg debian-archive-keyring
# apt-transport-https can be installed after debian-archive-keyring being installed # apt-transport-https can be installed after debian-archive-keyring being installed
DEBIAN_FRONTEND=noninteractive \ DEBIAN_FRONTEND=noninteractive \
@@ -80,31 +80,31 @@ apt update -y
DEBIAN_FRONTEND=noninteractive \ DEBIAN_FRONTEND=noninteractive \
apt install -y dialog sudo \ apt install -y dialog sudo \
libjpeg-dev libfreetype6 libfreetype6-dev zlib1g-dev \ libjpeg-dev libfreetype6 libfreetype6-dev zlib1g-dev \
xserver-xorg xserver-xorg-video-fbdev xserver-xorg-dev xserver-xorg-input-evdev xinput-calibrator xorg-dev x11-apps x11-ico-dvd xinit \ xserver-xorg xserver-xorg-video-fbdev xserver-xorg-dev xserver-xorg-input-evdev xinput-calibrator xorg-dev x11-apps xinit \
jwm \ jwm \
weston xwayland \
bash tmux vim htop \ bash tmux vim htop \
pcmanfm lxterminal xterm gnome-terminal fbterm uim-fep uim-anthy fonts-noto-cjk \ midori pcmanfm lxterminal xterm gnome-terminal fbterm uim-fep uim-anthy fonts-noto-cjk \
dbus udev alsa-utils usbutils iw fake-hwclock systemd-timesyncd\ dbus udev alsa-utils usbutils iw fake-hwclock\
build-essential flex bison pkg-config autotools-dev libtool autoconf automake device-tree-compiler \ build-essential flex bison pkg-config autotools-dev libtool autoconf automake device-tree-compiler \
python3 python3-dev python3-setuptools python3-wheel python3-pip python3-smbus \ python3 python3-dev python3-setuptools python3-wheel python3-pip python3-smbus \
resolvconf net-tools isc-dhcp-client ssh openssh-client avahi-daemon wget git \ resolvconf net-tools ssh openssh-client avahi-daemon wget git \
network-manager zip fastfetch sl python3-numpy ipython3 netsurf-gtk fcitx-anthy network-manager zip neofetch sl python3-numpy ipython3 netsurf-gtk fcitx-anthy
# Packages from packagecloud # Packages from packagecloud
DEBIAN_FRONTEND=noninteractive \ DEBIAN_FRONTEND=noninteractive \
apt install -y --install-recommends brain-config apt install -y --install-recommends brain-config
systemctl enable fake-hwclock-load fake-hwclock-save fake-hwclock-save.timer systemctl enable fake-hwclock
# Ly # Ly
DEBIAN_FRONTEND=noninteractive \ DEBIAN_FRONTEND=noninteractive \
apt install -y libpam0g-dev libxcb-xkb-dev apt install -y libpam0g-dev libxcb-xkb-dev
cd / cd /
git clone --recurse-submodules -b master-24f017e https://github.com/brain-hackers/ly.git git clone --recurse-submodules https://github.com/nullgemm/ly.git
cd ly cd ly
make make
make install make install
make installsystemd
cd / cd /
rm -r ly rm -r ly
systemctl enable ly systemctl enable ly
@@ -113,7 +113,7 @@ systemctl enable ly
install -m 0777 -d /etc/X11/xorg.conf.d install -m 0777 -d /etc/X11/xorg.conf.d
# Fix Midori launch failure # Fix Midori launch failure
update-mime-database /usr/share/mime sudo update-mime-database /usr/share/mime
# Setup users # Setup users
adduser --gecos "" --disabled-password --home /home/user user adduser --gecos "" --disabled-password --home /home/user user
@@ -135,19 +135,13 @@ ttymxc0
ttyLP0 ttyLP0
EOF EOF
# Enable /boot mount
systemctl enable boot.mount
# Enable RNDIS gadget
systemctl enable ethernet_gadget
# Get wild # Get wild
cat <<EOF > /etc/apt/sources.list cat <<EOF > /etc/apt/sources.list
deb http://deb.debian.org/debian trixie main contrib non-free deb http://deb.debian.org/debian bullseye main contrib non-free
deb-src http://deb.debian.org/debian trixie main contrib non-free deb-src http://deb.debian.org/debian bullseye main contrib non-free
deb http://deb.debian.org/debian trixie-updates main contrib non-free deb http://deb.debian.org/debian bullseye-updates main contrib non-free
deb-src http://deb.debian.org/debian trixie-updates main contrib non-free deb-src http://deb.debian.org/debian bullseye-updates main contrib non-free
deb http://deb.debian.org/debian-security trixie-security/updates main contrib non-free deb http://deb.debian.org/debian-security bullseye-security/updates main contrib non-free
deb-src http://deb.debian.org/debian-security trixie-security/updates main contrib non-free deb-src http://deb.debian.org/debian-security bullseye-security/updates main contrib non-free
EOF EOF

View File

@@ -1,112 +0,0 @@
#!/bin/sh
set -u
VERBOSE=0
PIN=""
SLEEP=1
GPIOS=""
while getopts "hvr:p:s:" OPT; do
case "$OPT" in
h)
echo "Usage: blink.sh [-hv] [-r PIN_RANGE_FROM-PIN_RANGE_TO] [-p PIN] [-s SLEEP_SEC]"
echo "Example: blink.sh -r 0-10 -p 12"
echo " (blink from GPIO 0 to 10 and 12)"
exit 0
;;
v)
VERBOSE=1
;;
r)
RE='^([0-9]+)-([0-9]+)$'
if echo $OPTARG | grep -qvE $RE; then
echo "Error: invalid range: $OPTARG"
exit 1
fi
FROM=$(echo $OPTARG | sed -E "s/$RE/\\1/")
TO=$(echo $OPTARG | sed -E "s/$RE/\\2/")
GPIOS="$GPIOS$(seq -s " " $FROM $TO) "
;;
p)
if echo $OPTARG | grep -qvE "^[0-9]+$"; then
echo "Error: invalid pin number: $OPTARG"
exit 1
fi
GPIOS="$GPIOS$OPTARG "
;;
s)
if echo $OPTARG | grep -qvE "^[0-9]+$"; then
echo "Error: invalid sleep duration: $OPTARG"
exit 1
fi
SLEEP=$OPTARG
;;
esac
done
if [ $VERBOSE -eq 1 ]; then
echo "Pins to iterate over: $GPIOS"
fi
if [ "$(id -u)" -ne "0" ]; then
echo "Error: please run as root"
exit 1
fi
AVAILABLE_GPIOS=""
export_gpio() {
echo $1 > /sys/class/gpio/export
}
set_direction() {
echo out > /sys/class/gpio/gpio$1/direction
}
set_value() {
echo $2 > /sys/class/gpio/gpio$1/value
}
for i in $GPIOS; do
if [ ! -e "/sys/class/gpio/gpio$i" ]; then
export_gpio $i 2>/dev/null
if [ $? -ne 0 ]; then
echo "Error: failed to export the pin $i"
continue
fi
fi
set_direction $i 2>/dev/null
if [ $? -ne 0 ]; then
# Ignore the failure if the actual direction is out
if grep -vq "out" /dsys/class/gpio/gpio$i/direction; then
echo "Error: failed to set the direction of the pin $i to out"
continue
fi
fi
AVAILABLE_GPIOS="$AVAILABLE_GPIOS$i "
done
echo "Available GPIOs: $AVAILABLE_GPIOS"
while [ 1 ]; do
for i in $AVAILABLE_GPIOS; do
set_value $i 1 2>/dev/null
if [ $? -ne 0 ]; then
echo "Warning: failed to set the value of the pin $i to high"
fi
done
sleep $SLEEP
for i in $AVAILABLE_GPIOS; do
set_value $i 0 2>/dev/null
if [ $? -ne 0 ]; then
echo "Warning: failed to set the value of the pin $i to low"
fi
done
sleep $SLEEP
done

View File

@@ -35,7 +35,6 @@ import (
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
"path"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
@@ -46,7 +45,6 @@ import (
type Proxy struct { type Proxy struct {
remote string remote string
root string
cli *http.Client cli *http.Client
cache map[string]struct{} cache map[string]struct{}
@@ -83,9 +81,8 @@ func NewProxy() (*Proxy, error) {
return p, nil return p, nil
} }
func (p *Proxy) Run(local, remote, root string) { func (p *Proxy) Run(local, remote string) {
p.remote = remote p.remote = remote
p.root = root
err := http.ListenAndServe(local, p) err := http.ListenAndServe(local, p)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -104,13 +101,13 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
} }
if nocache { if nocache {
fmt.Printf("GET (no cache): %s%s%s -> ", p.remote, p.root, r.URL.Path) fmt.Printf("GET (no cache): %s%s -> ", p.remote, r.URL.Path)
err = p.fetchFromRemote(w, r, false) err = p.fetchFromRemote(w, r, false)
} else if _, ok := p.cache[encoded]; ok { } else if _, ok := p.cache[encoded]; ok {
fmt.Printf("GET (cache hit): %s%s%s -> ", p.remote, p.root, r.URL.Path) fmt.Printf("GET (cache hit): %s%s -> ", p.remote, r.URL.Path)
err = p.fetchFromCache(w, r) err = p.fetchFromCache(w, r)
} else { } else {
fmt.Printf("GET (cache miss): %s%s%s -> ", p.remote, p.root, r.URL.Path) fmt.Printf("GET (cache miss): %s%s -> ", p.remote, r.URL.Path)
err = p.fetchFromRemote(w, r, true) err = p.fetchFromRemote(w, r, true)
} }
@@ -136,7 +133,6 @@ func (p *Proxy) fetchFromRemote(w http.ResponseWriter, r *http.Request, cache bo
} }
newURL.Scheme = "http" newURL.Scheme = "http"
newURL.Host = p.remote newURL.Host = p.remote
newURL.Path = path.Join(p.root, newURL.Path)
req, err := http.NewRequest(http.MethodGet, newURL.String(), nil) req, err := http.NewRequest(http.MethodGet, newURL.String(), nil)
if err != nil { if err != nil {
@@ -223,7 +219,7 @@ func (w NullWriter) Close() error {
} }
type rule struct { type rule struct {
Local, Remote, Root string Local, Remote string
} }
type rules []rule type rules []rule
@@ -233,7 +229,7 @@ func (r *rules) String() string {
} }
func (r *rules) Set(raw string) error { func (r *rules) Set(raw string) error {
var local, remote, root string var local, remote string
kvs := strings.Split(raw, ",") kvs := strings.Split(raw, ",")
for _, kv := range kvs { for _, kv := range kvs {
@@ -247,8 +243,6 @@ func (r *rules) Set(raw string) error {
local = tokens[1] local = tokens[1]
case "remote": case "remote":
remote = tokens[1] remote = tokens[1]
case "root":
root = tokens[1]
default: default:
return fmt.Errorf("rule has unknown key: '%s'", tokens[0]) return fmt.Errorf("rule has unknown key: '%s'", tokens[0])
} }
@@ -258,7 +252,7 @@ func (r *rules) Set(raw string) error {
return fmt.Errorf("rule lacks mendatory keys: 'local' and/or 'remote'") return fmt.Errorf("rule lacks mendatory keys: 'local' and/or 'remote'")
} }
*r = append(*r, rule{Local: local, Remote: remote, Root: root}) *r = append(*r, rule{Local: local, Remote: remote})
return nil return nil
} }
@@ -274,13 +268,13 @@ func main() {
} }
for i, rule := range rules { for i, rule := range rules {
fmt.Printf("Proxy Rule %d: %s -> %s%s\n", i+1, rule.Local, rule.Remote, rule.Root) fmt.Printf("Proxy Rule %d: %s -> %s\n", i+1, rule.Local, rule.Remote)
p, err := NewProxy() p, err := NewProxy()
if err != nil { if err != nil {
panic(err) panic(err)
} }
go p.Run(rule.Local, rule.Remote, rule.Root) go p.Run(rule.Local, rule.Remote)
} }
for { for {
time.Sleep(9999999999) time.Sleep(9999999999)

Binary file not shown.