mirror of
https://github.com/brain-hackers/buildbrain
synced 2026-03-28 16:51:09 +09:00
Merge pull request #59 from brain-hackers/ci-bump-debian
Brainux: bump up Debian version to Trixie
This commit is contained in:
47
.github/workflows/build.yml
vendored
47
.github/workflows/build.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
prerelease: true
|
||||
|
||||
build-linux:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
needs: [create_release]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -54,6 +54,17 @@ jobs:
|
||||
run: pip3 install listconfig
|
||||
- name: Configure for Linux
|
||||
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
|
||||
run: make lbuild
|
||||
- name: Setup releases
|
||||
@@ -75,20 +86,8 @@ jobs:
|
||||
asset_path: release.zip
|
||||
asset_name: ${{ steps.archive_name.outputs.name }}.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:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
needs: [create_release]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -123,7 +122,7 @@ jobs:
|
||||
asset_content_type: application/zip
|
||||
|
||||
build-uboot:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
needs: [create_release]
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -195,7 +194,7 @@ jobs:
|
||||
asset_content_type: application/zip
|
||||
|
||||
build-uboot-x1:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
needs: [create_release]
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -234,7 +233,7 @@ jobs:
|
||||
asset_content_type: application/zip
|
||||
|
||||
build-sd:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
needs: [create_release]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -256,14 +255,18 @@ jobs:
|
||||
- name: Build Linux
|
||||
run: make lbuild
|
||||
- name: Build Debian Root
|
||||
run: make brainux
|
||||
run: make brainux brainux-umount-special
|
||||
- name: Build bsd-ce
|
||||
run: make -C nkbin_maker bsd-ce
|
||||
- name: Generate image name
|
||||
- name: Generate version string and image name
|
||||
id: image_name
|
||||
run: echo ::set-output name=name::sdimage-${GITHUB_REF/refs\/*s\//}
|
||||
run: |
|
||||
echo "name=sdimage-${GITHUB_REF/refs\/*s\//}" >> $GITHUB_OUTPUT
|
||||
echo "version=${GITHUB_REF/refs\/*s\//}" >> $GITHUB_OUTPUT
|
||||
- name: Build SD image
|
||||
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
|
||||
run: zip ${{ steps.image_name.outputs.name }}.zip ${{ steps.image_name.outputs.name }}.img
|
||||
- name: Upload the image
|
||||
@@ -277,7 +280,7 @@ jobs:
|
||||
asset_content_type: application/zip
|
||||
|
||||
build-sd-x1:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
needs: [create_release]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -302,7 +305,7 @@ jobs:
|
||||
- name: Build Linux
|
||||
run: make lbuild
|
||||
- name: Build Debian Root
|
||||
run: make brainux
|
||||
run: make brainux brainux-umount-special
|
||||
- name: Generate image name
|
||||
id: image_name
|
||||
run: echo ::set-output name=name::sdimage-x1-${GITHUB_REF/refs\/*s\//}
|
||||
|
||||
148
AGENTS.md
Normal file
148
AGENTS.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# 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.
|
||||
20
Makefile
20
Makefile
@@ -140,12 +140,16 @@ brainux:
|
||||
echo "Debootstrap is only available in Linux!"; \
|
||||
exit 1; \
|
||||
fi
|
||||
sudo mkdir -p brainux
|
||||
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 \
|
||||
echo "I'm in CI and debootstrap without cache."; \
|
||||
sudo debootstrap --arch=$(ROOTFS_CROSS) --foreign bullseye brainux/; \
|
||||
sudo debootstrap --arch=$(ROOTFS_CROSS) --foreign trixie brainux/; \
|
||||
else \
|
||||
sudo debootstrap --arch=$(ROOTFS_CROSS) --foreign bullseye brainux/ http://localhost:65432/debian/; \
|
||||
sudo debootstrap --arch=$(ROOTFS_CROSS) --foreign trixie brainux/ http://localhost:65432/debian/; \
|
||||
fi
|
||||
sudo cp /usr/bin/qemu-arm-static brainux/usr/bin/
|
||||
sudo cp ./os-brainux/setup_brainux.sh brainux/
|
||||
@@ -154,6 +158,14 @@ brainux:
|
||||
sudo rm brainux/setup_brainux.sh
|
||||
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
|
||||
@@ -177,7 +189,7 @@ clean_work:
|
||||
.PHONY:
|
||||
aptcache:
|
||||
./tools/aptcache_linux_amd64 \
|
||||
-rule 'local=localhost:65432, remote=ftp.jaist.ac.jp' \
|
||||
-rule 'local=localhost:65432, remote=ftp.riken.jp, root=/Linux/debian' \
|
||||
-rule 'local=localhost:65433, remote=security.debian.org'
|
||||
|
||||
.PHONY:
|
||||
|
||||
368
docs/knowledge/202101_the_first_linux_porting_story_of_brain.md
Normal file
368
docs/knowledge/202101_the_first_linux_porting_story_of_brain.md
Normal file
@@ -0,0 +1,368 @@
|
||||
# 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.
|
||||
BIN
docs/knowledge/202101_the_first_linux_porting_story_of_brain.pdf
Normal file
BIN
docs/knowledge/202101_the_first_linux_porting_story_of_brain.pdf
Normal file
Binary file not shown.
154
docs/knowledge/202110_brain_boot_sequence.md
Normal file
154
docs/knowledge/202110_brain_boot_sequence.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# 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.
|
||||
BIN
docs/knowledge/202110_brain_boot_sequence.pdf
Normal file
BIN
docs/knowledge/202110_brain_boot_sequence.pdf
Normal file
Binary file not shown.
235
docs/knowledge/202208_install_linux_into_the_emmc.md
Normal file
235
docs/knowledge/202208_install_linux_into_the_emmc.md
Normal file
@@ -0,0 +1,235 @@
|
||||
# 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.
|
||||
BIN
docs/knowledge/202208_install_linux_into_the_emmc.pdf
Normal file
BIN
docs/knowledge/202208_install_linux_into_the_emmc.pdf
Normal file
Binary file not shown.
141
docs/knowledge/202304_linux_suspend_on_brain.md
Normal file
141
docs/knowledge/202304_linux_suspend_on_brain.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# 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.
|
||||
BIN
docs/knowledge/202304_linux_suspend_on_brain.pdf
Normal file
BIN
docs/knowledge/202304_linux_suspend_on_brain.pdf
Normal file
Binary file not shown.
15
docs/knowledge/AGENTS.md
Normal file
15
docs/knowledge/AGENTS.md
Normal file
@@ -0,0 +1,15 @@
|
||||
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".
|
||||
|
||||
55
docs/prompts/0000-introduce-coding-agents.md
Normal file
55
docs/prompts/0000-introduce-coding-agents.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# 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
|
||||
|
||||
@@ -63,6 +63,8 @@ mkdir -p ${WORK}/p1 ${WORK}/p2
|
||||
sudo mount -o utf8=true /dev/mapper/${LOOPDEV}p1 ${WORK}/p1
|
||||
sudo mount /dev/mapper/${LOOPDEV}p2 ${WORK}/p2
|
||||
|
||||
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/dts/imx28-pw*.dtb ${WORK}/p1/
|
||||
sudo mkdir -p ${WORK}/p1/nk
|
||||
|
||||
Submodule linux-brain updated: aa3edcd5fc...a9f534c7f5
@@ -6,5 +6,5 @@ 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/rndis_gadget.service $DST/lib/systemd/system/rndis_gadget.service
|
||||
install -g root -o root -m 0755 $SRC/usr/bin/enable_rndis_gadget $DST/usr/bin/enable_rndis_gadget
|
||||
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
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=Enable Ethernet USB Gadget
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/bin/enable_ethernet_gadget
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,9 +0,0 @@
|
||||
[Unit]
|
||||
Description=Enable RNDIS USB Gadget
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/bin/enable_rndis_gadget
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
29
os-brainux/override/usr/bin/enable_ethernet_gadget
Executable file
29
os-brainux/override/usr/bin/enable_ethernet_gadget
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/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
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
g=/sys/kernel/config/usb_gadget/eth
|
||||
|
||||
mkdir ${g}
|
||||
|
||||
echo "0x3066" > ${g}/bcdDevice
|
||||
echo "1" > ${g}/os_desc/use
|
||||
echo "0xcd" > ${g}/os_desc/b_vendor_code
|
||||
echo "MSFT100" > ${g}/os_desc/qw_sign
|
||||
|
||||
mkdir ${g}/functions/rndis.rn0
|
||||
echo "RNDIS" > ${g}/functions/rndis.rn0/os_desc/interface.rndis/compatible_id
|
||||
echo "5162001" > ${g}/functions/rndis.rn0/os_desc/interface.rndis/sub_compatible_id
|
||||
echo "8a:15:8b:44:3a:02" > ${g}/functions/rndis.rn0/dev_addr
|
||||
echo "8a:15:8b:44:3a:01" > ${g}/functions/rndis.rn0/host_addr
|
||||
|
||||
mkdir ${g}/configs/c.1
|
||||
ln -s ${g}/functions/rndis.rn0 ${g}/configs/c.1/
|
||||
|
||||
echo "ci_hdrc.0" > ${g}/UDC
|
||||
|
||||
sleep 1
|
||||
ifconfig usb0 up
|
||||
dhclient
|
||||
@@ -20,12 +20,12 @@ else
|
||||
fi
|
||||
|
||||
cat <<EOF > /etc/apt/sources.list
|
||||
deb http://${REPO}/debian bullseye main contrib non-free
|
||||
deb-src http://${REPO}/debian bullseye main contrib non-free
|
||||
deb http://${REPO}/debian bullseye-updates main contrib non-free
|
||||
deb-src http://${REPO}/debian bullseye-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 bullseye-security/updates main contrib non-free
|
||||
deb http://${REPO}/debian trixie main contrib non-free
|
||||
deb-src http://${REPO}/debian trixie main contrib non-free
|
||||
deb http://${REPO}/debian trixie-updates main contrib non-free
|
||||
deb-src http://${REPO}/debian trixie-updates main contrib non-free
|
||||
deb http://${REPO_SECURITY}/debian-security trixie-security/updates main contrib non-free
|
||||
deb-src http://${REPO_SECURITY}/debian-security trixie-security/updates main contrib non-free
|
||||
EOF
|
||||
|
||||
cat <<EOF > /etc/apt/apt.conf.d/90-norecommend
|
||||
@@ -83,18 +83,18 @@ DEBIAN_FRONTEND=noninteractive \
|
||||
xserver-xorg xserver-xorg-video-fbdev xserver-xorg-dev xserver-xorg-input-evdev xinput-calibrator xorg-dev x11-apps x11-ico-dvd xinit \
|
||||
jwm \
|
||||
bash tmux vim htop \
|
||||
midori pcmanfm lxterminal xterm gnome-terminal fbterm uim-fep uim-anthy fonts-noto-cjk \
|
||||
pcmanfm lxterminal xterm gnome-terminal fbterm uim-fep uim-anthy fonts-noto-cjk \
|
||||
dbus udev alsa-utils usbutils iw fake-hwclock systemd-timesyncd\
|
||||
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 \
|
||||
resolvconf net-tools ssh openssh-client avahi-daemon wget git \
|
||||
network-manager zip neofetch sl python3-numpy ipython3 netsurf-gtk fcitx-anthy
|
||||
resolvconf net-tools isc-dhcp-client ssh openssh-client avahi-daemon wget git \
|
||||
network-manager zip fastfetch sl python3-numpy ipython3 netsurf-gtk fcitx-anthy
|
||||
|
||||
# Packages from packagecloud
|
||||
DEBIAN_FRONTEND=noninteractive \
|
||||
apt install -y --install-recommends brain-config
|
||||
|
||||
systemctl enable fake-hwclock
|
||||
systemctl enable fake-hwclock-load fake-hwclock-save fake-hwclock-save.timer
|
||||
|
||||
# Ly
|
||||
DEBIAN_FRONTEND=noninteractive \
|
||||
@@ -113,7 +113,7 @@ systemctl enable ly
|
||||
install -m 0777 -d /etc/X11/xorg.conf.d
|
||||
|
||||
# Fix Midori launch failure
|
||||
sudo update-mime-database /usr/share/mime
|
||||
update-mime-database /usr/share/mime
|
||||
|
||||
# Setup users
|
||||
adduser --gecos "" --disabled-password --home /home/user user
|
||||
@@ -139,15 +139,15 @@ EOF
|
||||
systemctl enable boot.mount
|
||||
|
||||
# Enable RNDIS gadget
|
||||
systemctl enable rndis_gadget
|
||||
systemctl enable ethernet_gadget
|
||||
|
||||
# Get wild
|
||||
cat <<EOF > /etc/apt/sources.list
|
||||
deb http://deb.debian.org/debian bullseye main contrib non-free
|
||||
deb-src http://deb.debian.org/debian bullseye main contrib non-free
|
||||
deb http://deb.debian.org/debian bullseye-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 bullseye-security/updates main contrib non-free
|
||||
deb-src http://deb.debian.org/debian-security bullseye-security/updates main contrib non-free
|
||||
deb http://deb.debian.org/debian trixie main contrib non-free
|
||||
deb-src http://deb.debian.org/debian trixie main contrib non-free
|
||||
deb http://deb.debian.org/debian trixie-updates main contrib non-free
|
||||
deb-src http://deb.debian.org/debian trixie-updates main contrib non-free
|
||||
deb http://deb.debian.org/debian-security trixie-security/updates main contrib non-free
|
||||
deb-src http://deb.debian.org/debian-security trixie-security/updates main contrib non-free
|
||||
EOF
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -45,6 +46,7 @@ import (
|
||||
|
||||
type Proxy struct {
|
||||
remote string
|
||||
root string
|
||||
|
||||
cli *http.Client
|
||||
cache map[string]struct{}
|
||||
@@ -81,8 +83,9 @@ func NewProxy() (*Proxy, error) {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (p *Proxy) Run(local, remote string) {
|
||||
func (p *Proxy) Run(local, remote, root string) {
|
||||
p.remote = remote
|
||||
p.root = root
|
||||
err := http.ListenAndServe(local, p)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -101,13 +104,13 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if nocache {
|
||||
fmt.Printf("GET (no cache): %s%s -> ", p.remote, r.URL.Path)
|
||||
fmt.Printf("GET (no cache): %s%s%s -> ", p.remote, p.root, r.URL.Path)
|
||||
err = p.fetchFromRemote(w, r, false)
|
||||
} else if _, ok := p.cache[encoded]; ok {
|
||||
fmt.Printf("GET (cache hit): %s%s -> ", p.remote, r.URL.Path)
|
||||
fmt.Printf("GET (cache hit): %s%s%s -> ", p.remote, p.root, r.URL.Path)
|
||||
err = p.fetchFromCache(w, r)
|
||||
} else {
|
||||
fmt.Printf("GET (cache miss): %s%s -> ", p.remote, r.URL.Path)
|
||||
fmt.Printf("GET (cache miss): %s%s%s -> ", p.remote, p.root, r.URL.Path)
|
||||
err = p.fetchFromRemote(w, r, true)
|
||||
}
|
||||
|
||||
@@ -133,6 +136,7 @@ func (p *Proxy) fetchFromRemote(w http.ResponseWriter, r *http.Request, cache bo
|
||||
}
|
||||
newURL.Scheme = "http"
|
||||
newURL.Host = p.remote
|
||||
newURL.Path = path.Join(p.root, newURL.Path)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, newURL.String(), nil)
|
||||
if err != nil {
|
||||
@@ -219,7 +223,7 @@ func (w NullWriter) Close() error {
|
||||
}
|
||||
|
||||
type rule struct {
|
||||
Local, Remote string
|
||||
Local, Remote, Root string
|
||||
}
|
||||
|
||||
type rules []rule
|
||||
@@ -229,7 +233,7 @@ func (r *rules) String() string {
|
||||
}
|
||||
|
||||
func (r *rules) Set(raw string) error {
|
||||
var local, remote string
|
||||
var local, remote, root string
|
||||
|
||||
kvs := strings.Split(raw, ",")
|
||||
for _, kv := range kvs {
|
||||
@@ -243,6 +247,8 @@ func (r *rules) Set(raw string) error {
|
||||
local = tokens[1]
|
||||
case "remote":
|
||||
remote = tokens[1]
|
||||
case "root":
|
||||
root = tokens[1]
|
||||
default:
|
||||
return fmt.Errorf("rule has unknown key: '%s'", tokens[0])
|
||||
}
|
||||
@@ -252,7 +258,7 @@ func (r *rules) Set(raw string) error {
|
||||
return fmt.Errorf("rule lacks mendatory keys: 'local' and/or 'remote'")
|
||||
}
|
||||
|
||||
*r = append(*r, rule{Local: local, Remote: remote})
|
||||
*r = append(*r, rule{Local: local, Remote: remote, Root: root})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -268,13 +274,13 @@ func main() {
|
||||
}
|
||||
|
||||
for i, rule := range rules {
|
||||
fmt.Printf("Proxy Rule %d: %s -> %s\n", i+1, rule.Local, rule.Remote)
|
||||
fmt.Printf("Proxy Rule %d: %s -> %s%s\n", i+1, rule.Local, rule.Remote, rule.Root)
|
||||
|
||||
p, err := NewProxy()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
go p.Run(rule.Local, rule.Remote)
|
||||
go p.Run(rule.Local, rule.Remote, rule.Root)
|
||||
}
|
||||
for {
|
||||
time.Sleep(9999999999)
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user