From d9a2f355f307077b57df089f5a4b92ff4dd11b97 Mon Sep 17 00:00:00 2001 From: Dmitry Ilyin <6576495+widgetii@users.noreply.github.com> Date: Sat, 17 Oct 2026 09:18:12 +0300 Subject: [PATCH] docs: add CLAUDE.md for the openipc-hisilicon tree Guidance for Claude Code sessions on this branch, centred on how the tree differs from mainline v2022.10: the squashed vendor baseline and the OpenIPC commits on top, where each vendor subsystem lives, the mainline files it patches, and the ones the baseline replaced with the SDK's older copies (spi-nor-core, cmd/sf.c, xhci), which read as removed mainline features in a diff. It also covers how build.sh assembles each .config from the openipc/ fragments, the u-boot-z.bin image, the NOR/NAND size limits, the OpenIPC boot layer in openipc-common.h and common/openipc.c, and the requirement that environments saved by older OpenIPC bootloaders keep booting. CI lives on the openipc branch, whose CLAUDE.md it points to. --- CLAUDE.md | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000000..211ddda6381f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,229 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What this branch is + +`openipc-hisilicon` is OpenIPC's U-Boot for 38 HiSilicon and Goke IP-camera +SoCs. It is **mainline U-Boot v2022.10** with HiSilicon/XMedia vendor SDK code +grafted on, plus OpenIPC's own boot layer. CI and user-facing docs live on the +`openipc` branch: + +- `.github/workflows/ci.yml` here only calls `build-hisilicon.yml@openipc`. +- The `openipc` branch has its own `CLAUDE.md` on the workflow invariants. Read + it with `git show origin/openipc:CLAUDE.md`. +- Adding, removing or holding a SoC needs a change on **both** branches. + - Here: `build.sh` (`build_soc`, `ALL_SOCS`) and `openipc/_*`. + - There: both workflow matrices and the README. + +## Relationship to mainline + +```sh +git diff --stat v2022.10 HEAD # whole delta (~2500 files, ~530k lines) +git diff --diff-filter=M --stat v2022.10 HEAD # the ~60 mainline files we patched +git log --oneline v2022.10..HEAD # our history +``` + +History on top of `v2022.10`: + +- **`1ba97e9c9e4` "OpenIPC HiSilicon baseline"**: one squashed commit that + imports all the vendor code. +- After it come ~40 OpenIPC commits: + - SoC family ports (cv200, cv300, 18ev100, 16av100, 3536, 3520d, 3519v101, + xmorca); + - the recovery and env work; + - flash IDs ported from u-boot-xmedia; + - fixes. +- `origin/main` (equal to `master`) tracks mainline. Its merge-base with this + branch is exactly `v2022.10`, so a mainline rebase means moving the + baseline commit forward. + +### Where the vendor code lives + +Most of the delta is **added files**: whole vendor subsystems in new +directories. Mainline U-Boot has no counterpart for them. + +| Area | Location | +| --- | --- | +| Per-SoC first stage: `start.S`, lowlevel init, DDR/PLL init, `hw_compressed/` (the decompressing loader that becomes `u-boot-z.bin`) | `arch/arm/cpu/armv7/{hi35xx,xm7xxx,xmorca}/`, and for the ARM926 parts `arch/arm/cpu/arm926ejs/{hi3516cv300,hi3518ev100,hi3518ev200}/` | +| Machine glue | `arch/arm/mach-hi35xx`, `arch/arm/mach-xmedia`, `arch/arm/mach-vendor` | +| Targets | `arch/arm/Kconfig`: `TARGET_HI*`/`TARGET_XM*` and the `*_FAMILY` symbols, `ARCH_BSP` | +| Boards | `board/hisilicon//`, `board/xmedia//`. Goke parts are XMedia dies, e.g. `xm72050200` = gk7205v200; `xmorca` = GK7206V1 | +| Per-SoC headers | `include/configs/.h` | +| DDR training | `drivers/ddr/{hisilicon,xmedia,vendor}` (`vendor/` is the newer-SDK one, used by `ARCH_BSP`) | +| SPI flash (FMC, plus HISFC350 on old parts) | `drivers/mtd/fmc_*.c`, `drivers/mtd/spi/{fmc100,hisfc350}`, `drivers/mtd/spi/vendor_spi_nor.c`, `include/fmc_common.h`, `fmc_spi_ids.h` | +| NAND: SPI-NAND through FMC, and the HINFC301 parallel controller on V1 parts | `drivers/mtd/nand/raw/{fmc100,hinfc301}`, `nfc_common.c` | +| Ethernet MACs | `drivers/net/{hisfv300,sfv300,femac,higmacv300,gmacv300,ftgmac030}` | +| MMC/SDHCI | `drivers/mmc/{himci*,bsp_*,xm7*}.c` | +| USB | `drivers/phy/{hibvt,xmedia}`, `drivers/usb/gadget/udc3` | +| HW gunzip | `lib/hw_dec`, plus `cmd/hwzimage.c` and `cmd/cmd_ugzip.c` | +| ATAGs and I2C helpers | `drivers/lhs` | +| GPIO and pad-mux (`gpio status` shows the live pad function) | `drivers/gpio/hi_*` | +| Newer-SDK (`ARCH_BSP`, cv610/cv608) extras: OSD, audio, OTP, verified boot, security subsystem | `product/`, pulled in by `Makefile-otproduct`; `securec/` (Huawei bounds-checked libc) | +| CV6xx boot-image packer | `image_tool/` (`oem_quick_build.py`, prebuilt `input/gsl.bin`) | +| Source of the GSL first stage. **build.sh does not build it**: CV6xx images use the prebuilt `image_tool/input/gsl.bin` | `gsl/` | +| Vendored host tools | `extras/gzip-1.11` (built by `build.sh`) | +| OpenIPC's own per-SoC inputs | `openipc/`: config fragments and reginfo; `reginfo/` holds the CV6xx DDR tables | + +### Mainline files we patched + +The patched files are listed by `git diff --diff-filter=M v2022.10`. These +changes conflict on a rebase and change mainline behaviour: + +- **Build system**: + - The top-level `Makefile` adds the `u-boot-z.bin` / `u-boot-z.clean` + targets. They run the per-SoC `hw_compressed/` Makefile on `u-boot.bin` + and the `.reg` table. `u-boot-z.bin` is the flashable image; `u-boot.bin` + alone does not boot. + - It also adds `ddr_training_prepare`/`_clean`, chained into `prepare` and + `clean`. These build the DDR training `cmd_bin` per family. + - It adds `securec/` and `drivers/ddr/...` to `libs-y`. + - `config.mk` exports `VENDER_CHIP`. + - The various `Kconfig`/`Makefile` files only hook in the new directories. +- **Reverted-to-vendor copies.** The SDK carried older U-Boot copies of some + mainline files, and the baseline commit took those copies over mainline's. + The diff of these files shows mainline features *removed*. That is + intentional and not a regression to "fix" piecemeal. + - `drivers/mtd/spi/spi-nor-core.c`, `spi-nor-ids.c` and + `include/linux/mtd/spi-nor.h`: SCCR/octal-DTR is gone and + `stm_is_unlocked` became `stm_is_locked`. + - `cmd/sf.c`: the `flash_is_unlocked` write/erase guard is dropped. + - `drivers/usb/host/xhci*.c` and `include/usb/xhci.h`: the vendor xHCI, + which includes the hibvt/xmedia PHY headers. +- **Small hooks**: + - `serial_pl01x.c` adds `serial_enable_output()`, used for `silent=1`. + - `nand_base.c`, `mtd.h`, `rawnand.h` and `spi_flash.h` gain the vendor + fields and IDs. + - `cmd/gpio.c` gets the legacy `gpio status`. + - `cmd/net.c`, `mmc_boot.c`, `vsprintf.c`, `include/common.h`, + `arch/arm/lib/reset.c` and `mach-types.h` carry small vendor hooks. + - `env/Kconfig` lets `ENV_IS_IN_SPI_FLASH` depend on `FMC || + HISFC350_SPI_NOR`, not on DM SPI. + - `scripts/check-config.sh` no longer fails on ad-hoc `CONFIG_`s, because + the vendor headers define many. +- **Deleted**: mainline's CI configs (`.azure-pipelines.yml`, + `.gitlab-ci.yml`), `.checkpatch.conf`, `.mailmap`, and a few binary test + fixtures. + +### The vendor driver model + +Most SoCs bypass mainline's DM SPI/MTD stack: + +- **SPI flash** goes through the vendor FMC driver straight into + `spi_flash`. `fmc_common.c`/`fmc100` serve every FMC SoC. One + `drivers/mtd/fmc_.c` per SoC supplies clocks and IO; register-layout + differences are `#ifdef CONFIG_TARGET_` blocks in `fmc_common.h`. +- **The Ethernet MACs** are legacy non-DM drivers. +- **Kernels are booted with ATAGs**, not a DTB (`CONFIG_SUPPORT_PASSING_ATAGS` + in `openipc-common.h`). + +When a new die differs from a supported one, extend the tree's driver with +`#ifdef CONFIG_TARGET_`. Do not import the SDK's duplicate copy. The +GK7206 port (`784ae4105ee`) is the worked example for FMC, hw_dec and +timestamp. + +## Build + +```sh +bash build.sh # every SoC in ALL_SOCS; continues past failures, exits non-zero if any failed +bash build.sh hi3516cv300 # one or more SoCs (CROSS_COMPILE defaults to arm-linux-gnueabi-) +``` + +Output: + +- Images land in `output/`: `u-boot--{nor,nand}.bin`, or + `boot-[-]-nor.bin` for cv608/cv610. +- Each SoC builds out-of-tree (`O=`) in `output/build-/`, and its + `.config` stays there. + +Build environment: + +- `build.sh` first builds the patched gzip (`WSIZE=0x2000`) from + `extras/gzip-1.11`. Set `GZIP_REBUILD=1` to force a rebuild. +- CI runs with `/bin/sh` symlinked to bash, because vendor recipes use + bash-isms. +- CI also needs `pycryptodome`, `u-boot-tools`, `device-tree-compiler`, + `lzop`, bison/flex and libssl-dev. + +There are **no `configs/*_defconfig` for most SoCs**. The ones in `configs/` +are vendor leftovers, apart from the cv608/cv610 `_openipc_` ones. For each +image, `build.sh` builds `.config` by concatenating these, later lines +winning, and then runs `olddefconfig`: + +1. `openipc/openipc_config`: the base for every SoC. +2. `openipc/_config`: the gk7205v5xx SoCs share `xm720xxx_config`, and + the GK7206 dies share `gk7206v100_config`. +3. `openipc/nand_config`, for NAND images only. +4. `CONFIG_PRODUCT_SOC=""`. + +`openipc/_reginfo.bin` becomes `$O/.reg`, the DDR/pinmux table spliced +into the first stage. `build.sh` has one function per family (`build_v500`, +`build_cv6xx`, `build_nor_ddr`, `build_nor_splice`, `build_xmedia`, +`build_xmorca`), because each SDK generation packages its image differently. +Several SoCs share one board and binary and differ only in fragment and +reginfo. For example, `hi3516cv100`/`hi3518*v100` all build +`u-boot-hi3518ev100.bin`. + +**Hard size limits**: a NOR image may be at most 256 KiB, because env starts +at 0x40000. A NAND image may be at most 768 KiB. CI rejects an oversized +image, because flashing one overwrites env and bricks the camera. + +**Verification** (there are no unit tests): + +- **QEMU smoke**: CI boots each NOR image in widgetii/qemu-hisilicon. It + passes only on `Hit Ctrl-C to stop autoboot`, not on the banner. +- **Hardware**: load the image into RAM with `defib` before writing flash. +- Commit bodies state which check was done, or say "Build-tested only". + +## The OpenIPC boot layer + +This is the code with no SDK or mainline counterpart, and most changes touch +it. + +- `include/configs/openipc-common.h` is the **only** place that defines the + default env: bootcmd, bootargs, the `ub`/`uk`/`ur`/`fwupd` update commands, + `altbootcmd`, NOR/NAND mtdparts and `baseaddr`/`osmem` per family. Per-SoC + headers include it last and may override only `OPENIPC_*` macros. They must + never define `CONFIG_EXTRA_ENV_SETTINGS`, `CONFIG_BOOTARGS` or + `CONFIG_BOOTCOMMAND`. +- `common/openipc.c` holds the OpenIPC boot logic, entered from each board's + `misc_init_r()` via `openipc_helper()`: + - **NOR**: `firmware_scan()` locates the kernel and squashfs, then sets + `kernaddr`/`kernsize` and rebuilds `mtdparts`. + - **NAND**: it attaches UBI and requires a UBIFS `rootfs` volume holding + `/boot/fitImage` or `/boot/uImage`. There is no kernel volume. + - **Broken firmware**: the scan sets `bootfail`, and `firmware_recovery()` + tries SD/USB. + - **Boot loops**: past `bootlimit` (the DRAM bootcount word at + SDRAM + 0x1f20000, cleared by openipc-failsafe), `altbootcmd` boots the + same kernel with `failsafe`. It does not reflash. +- OpenIPC also changed these Kconfig defaults: + - autoboot stops on Ctrl-C only; + - `silent=1` suppresses console output; + - `CMD_ECHO` is enabled; + - the prompt is `OpenIPC # `. + +**Saved environments must keep working.** Cameras upgraded from the old +per-SoC OpenIPC bootloaders (u-boot-gk7205v200, u-boot-hi3516ev200, +u-boot-xmedia and others) keep their env. That env may lack `mtdids` or +`loadkernel`, or carry retired commands, which `altbootcmd_migrate()` +rewrites. So: + +- Fall back to the controller name (`sfc`, or `hi_sfc` on HiSilicon). +- Inline commands rather than `run` a variable that may not exist. + +Firmware, sysupgrade and openipc.org depend on two layouts. Do not change +either: + +- the NAND layout `768k(boot),256k(env),-(ubi)`, with the kernel inside the + rootfs; +- the NOR offsets in `openipc-common.h`. + +## Conventions + +- `.gitignore` keeps mainline's `.*` rule, so new files under `.github/` + need `git add -f`. +- One topic per commit, in the form `: ` (`nand:`, + `openipc:`, `hinfc301:`, `fmc100:`, `xmorca:`, `ci:`). The body explains + the failure on real cameras, the root cause, and what was verified on + which board.