diskOS installer: initial public beta

Flashes the diskOS custom UI onto the FiiO Snowsky Disc over Ingenic mask-ROM USB,
building the image from your own stock firmware. Runs from source via install.sh.
This commit is contained in:
b0hemia
2026-08-26 15:26:14 +10:00
commit e0bc4785e9
109 changed files with 12625 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
ko_fi: b0hemia
# github: [b0hemia] # uncomment once GitHub Sponsors is enabled on the account
+78
View File
@@ -0,0 +1,78 @@
# === diskOS installer - publication .gitignore ===
# Excludes secrets, FiiO-derived artifacts, build outputs, and release binaries.
# The public repo ships SOURCE; large/built artifacts go on GitHub Releases.
# NOTE: gitignore has NO inline comments - every comment is on its own line.
# --- SECRETS - never publish (private ECC update-signing key lives here) ---
signing/
*.pem
*.key
# --- FiiO-derived images (contain FiiO rootfs - never redistribute) ---
diskos_dev*.bin
diskos_public*.bin
diskos_v209_recovery.bin
*_recovery.bin
*.squashfs
# --- retired unlicensed blob ---
_retired_unlicensed/
# --- build outputs / venvs / caches ---
build/venv/
build/work/
build/dist/
.venv/
__pycache__/
*.pyc
*.pyo
# --- prebuilt native binaries (Release artifacts / rebuilt by build/ scripts) ---
# source is in src/usbboot/ ; static builds via build/build-*-static.sh
vendor/*/usbboot
vendor/*/mksquashfs
vendor/*/unsquashfs
vendor/*/*.bak
vendor/*/lib/
flash/usbboot
# --- top-level duplicates of payload/* (keep only payload/) ---
/mq_ui
/S97diskos_install
/S99usbserial
# --- deprecated/unsafe legacy shell installer (superseded by the Python installer; never publish) ---
# Kept on disk for reference but excluded from the public repo AND the release tarball.
INSTALL.md
mkdiskos.sh
flash/flash_diskos.sh
flash/extract_stock_rootfs.sh
# --- internal process / release-engineering docs (not for the public repo) ---
PUBLICATION_PLAN.md
BETA_CHECKLIST.md
RELEASE.md
RELEASE_READINESS.md
UPDATE2_DRAFT.md
UPDATE_ARCHITECTURE.md
INSTALL_v209_legacy.md
# --- source-tree checksums are fragile; release checksums are generated at staging ---
SHA256SUMS
# --- unsupported developer diagnostics (hardcoded paths / no clean public build) ---
flash/qual_lpddr3.sh
flash/scan_check.sh
flash/my_write5_scan_dram.bin
# --- extra build/release scratch ---
build/release/
*.sqfs
# NOTE: the SPL corresponding-source tarball (spl-src/*.tar.gz) is deliberately NOT ignored -
# it is the GPL corresponding source and must ship with the repo.
# --- scratch / OS noise ---
*.log
*.tmp
.DS_Store
+41
View File
@@ -0,0 +1,41 @@
# Contributing to diskOS
Thanks for wanting to help. diskOS touches real hardware in a way that can brick a device, so a few
rules keep contributions safe and legally clean.
## Ground rules
1. **Hardware-affecting changes must be tested on real hardware.** Anything that changes the image
builder, the boot hook, the NAND writer, the SPL, or device targeting has to be flashed and
booted on an actual Snowsky Disc before it is declared working. Say which firmware version and
which DRAM/NAND variant you tested on.
2. **Never weaken the fail-closed contract.** The first-boot hook must always fall back to the stock
UI when it cannot verify the UI against the baked manifest. The flasher must fail closed rather
than commit an unverified or wrong-device write.
3. **Add an error code for every new failure mode** (`E1xx` preflight, `E2xx` build, `E3xx` flash,
`F1xx` device-writer) and document it in `README.md`.
4. **Keep the honest-limitations tone.** If something is blocked by hardware or a toolchain gap, say
so plainly. Do not imply a feature works when it has not been verified.
## Licensing and provenance
- Original diskOS files are MIT. By contributing you agree your contribution is under the same
license. Please sign off your commits (`git commit -s`, Developer Certificate of Origin).
- **Do not upload FiiO firmware, stock rootfs images, or generated `diskos_*.bin` images** to issues
or PRs - they contain FiiO's software. The installer builds images locally from a user's own
firmware; that is fine, redistributing them is not.
- If you touch how a GPL/LGPL component is bundled (usbboot, squashfs-tools, the SPL, libusb),
keep its corresponding source and `NOTICE.md` in sync.
- Do not commit device-identifying data (serials, MAC addresses) or secrets.
## Filing issues
Include: firmware version + hash, DRAM/NAND variant if known, host OS, the exact error code, the
bad-block count if the flasher printed one, and redacted logs. **Do not** post serial numbers, MAC
addresses, firmware zips, stock rootfs, or generated images.
## Development
See [`agents/AGENTS.md`](agents/AGENTS.md) for a project brief (the hardware facts that are easy to
get wrong, the repo layout, and the device-safety rules) - useful whether you work by hand or with
an AI coding agent. Build the installer with `bash build/build.sh`.
+53
View File
@@ -0,0 +1,53 @@
# Dependency inventory - generated from a self-built onefile artifact
> **Scope note:** this inventory describes a **self-built PyInstaller onefile**. The **published
> diskOS release does NOT ship that onefile** - it distributes source and runs from your own Python
> (see [`NOTICE.md`](NOTICE.md) / [`licenses/THIRD_PARTY_BUNDLED.md`](licenses/THIRD_PARTY_BUNDLED.md)),
> so these bundled libraries are not redistributed by this project. This file is retained for anyone
> who chooses to build and redistribute the onefile themselves (they take on these obligations).
This is an artifact-derived list from a PyInstaller onefile build: ~93 distinct native `.so` entries
were bundled. Below are the license-bearing shared libraries PyInstaller pulled in transitively
(CPython + Tkinter GUI + pycryptodome + pyusb chains), grouped by license obligation. They matter
**only if you build and redistribute the onefile yourself**; the published source release does not
bundle them.
## Copyleft - obligations to satisfy (priority)
| Library | Bundled as | License | Obligation |
|---|---|---|---|
| **libudev** (systemd) | `libudev.so.1` | **LGPL-2.1** | ship license text + §6 relink materials (or drop it) |
| **FreeType** | `libfreetype.so.6` | **FTL or GPLv2 (dual)** | ship FTL text (permissive path) + attribution |
| **libcap** | `libcap.so.2` | BSD-3 / GPLv2 (dual) | permissive path: BSD text |
> NOTE: `libudev` (LGPL) is bundled only because of the **Tkinter GUI**'s X/font chain. Consider a
> `--nowindow`/CLI-only build, or explicitly excluding `libudev`, to remove the LGPL relink burden.
## Permissive - attribution/notice only (ship license texts)
| Library | Bundled as | License |
|---|---|---|
| OpenSSL 3 | `libssl.so.3`, `libcrypto.so.3` | Apache-2.0 |
| Tcl / Tk 8.6 | `libtcl8.6.so`, `libtk8.6.so` | TCL/Tk (BSD-style) |
| libpng | `libpng16.so.16` | PNG Reference License |
| zlib | `libz.so.1` | zlib |
| xz / liblzma | `liblzma.so.5` | 0BSD / public-domain |
| bzip2 | `libbz2.so.1.0` | bzip2 (BSD-style) |
| libffi | `libffi.so.8` | MIT |
| fontconfig | `libfontconfig.so.1` | MIT-style |
| expat | `libexpat.so.1` | MIT |
| brotli | `libbrotlicommon/dec` | MIT |
| X11 client libs | `libX11/Xext/Xrender/Xft/Xau/Xdmcp/Xss` | MIT (X11) |
| BLT | `libBLT*` | BSD-style |
## Already in NOTICE.md (direct deps)
CPython (PSF), pyusb (BSD-3), pycryptodome (BSD-2 + public-domain), PyInstaller bootloader
(GPL-2.0 + bootloader exception). The pycryptodome `_raw_*`/`_ghash_*` etc. modules are part of it.
## If you build and redistribute the onefile yourself
The published release does **not** ship the onefile, so none of the above is an obligation for it. If
you choose to build one (`build/build.sh`) and hand it to others, **you** become the redistributor of
everything it embeds and must satisfy those licenses - in particular the LGPL `libudev` and the
dual-licensed FreeType pulled in by the Tkinter GUI. The simplest way to avoid that burden is a
CLI-only build that excludes `tkinter`. To enumerate exactly what a given onefile bundles, walk the
extracted binary's shared objects and map each back to its distribution package.
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 diskOS contributors
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.
+135
View File
@@ -0,0 +1,135 @@
# diskOS installer - third-party components & licenses
The diskOS installer ships the third-party programs and libraries below. Each is invoked as a
separate program or loaded as a library; this document provides the required attribution and points
to the corresponding source that ships alongside the binaries. The full verbatim license texts are in
[`licenses/`](licenses/); this file is the component-to-license index.
## Bundled native programs (called as subprocesses - mere aggregation)
| Component | Purpose | License | Source |
|---|---|---|---|
| **usbboot** | Ingenic X2000 mask-ROM USB loader (the flasher front-end) | **GPL-2.0-or-later** - © 2021 Aidan MacDonald, © 2015 Amaury Pouly | included: `src/usbboot/` (built from this) |
| **mksquashfs / unsquashfs** (squashfs-tools **4.6.1**) | build/extract the rootfs image | **GPL-2.0** | https://github.com/plougher/squashfs-tools (v4.6.1) |
| **dropbearmulti** (Dropbear SSH **2022.83**) | embedded in the diskOS image; started by the opt-in Debug Mode for SSH-over-WiFi | **MIT-style** (© 2002-2020 Matt Johnston; components under MIT/BSD/public-domain) - text in `licenses/LICENSE-dropbear.txt` | https://matt.ucc.asn.au/dropbear/dropbear.html (v2022.83; **predates the CVE-2023-48795 "Terrapin" Strict-KEX mitigation - an update is planned**. Debug Mode SSH is opt-in and short-lived, and Dropbear's Terrapin exposure is limited.) |
`usbboot` and squashfs-tools are **GPL-2.0**, so anyone redistributing them must make their
corresponding source available and include the GPL-2.0 license text. (`dropbearmulti` is MIT-style -
no source-availability obligation, only its license text as noted above.) **The complete
corresponding source ships in-tree and in every release tarball**, so it travels from the same place
as the binaries (GPL-2.0 §3(a), plus the "same place" provision in §3's final paragraph):
`usbboot`'s own source is `src/usbboot/usbboot.c`;
**squashfs-tools 4.6.1** source is `corresponding-source/squashfs-tools_4.6.1*`. Both are rebuilt by
`build/build-usbboot-static.sh` / `build/build-squashfs-static.sh`.
**Static linking (Linux):** the prebuilt Linux `usbboot`, `mksquashfs`, and `unsquashfs` are shipped
**fully statically linked** (built with `gcc -static` on a glibc host). They therefore statically
incorporate:
- **libusb-1.0.27 (LGPL-2.1)** - in `usbboot`
- **liblzo2 2.10 (GPL-2.0-or-later)**, **zlib**, **liblzma** (permissive) - in squashfs-tools
- the **GNU C Library (glibc, LGPL-2.1-or-later)** - the host's system C runtime, in all three
Because liblzo2 is GPL, the resulting `mksquashfs`/`unsquashfs` binaries are effectively GPL-2.0. The
corresponding source for the statically-linked **GPL/LGPL** libraries is provided so their §3/§6
obligations are met:
- **liblzo2** (`corresponding-source/lzo2_2.10*`) and **libusb-1.0** (`corresponding-source/libusb-1.0_1.0.27*`)
ship in-tree.
- **glibc** (statically linked, so it travels inside the binary): the **complete corresponding source**
is vendored in `corresponding-source/glibc_2.39*` (the exact version the shipped binaries were built
against). Because it is statically linked it does not qualify for the "system library" exception, so
its source ships alongside the binaries like the others.
**Relink path (satisfies LGPL-2.1 §6 for libusb *and* glibc):** we ship the **complete source** of
`usbboot` (`src/usbboot/usbboot.c`) and squashfs-tools (`corresponding-source/squashfs-tools_4.6.1*`)
plus the exact build recipes (`build/build-usbboot-static.sh`, `build/build-squashfs-static.sh`). A
user can therefore rebuild and relink these tools against a **modified** libusb, liblzo2, **or glibc**
of their choosing - the freedom §6 exists to protect. See
[`corresponding-source/README.md`](corresponding-source/README.md).
**Python runtime + libraries - NOT redistributed by this project.** The installer runs **from
source** with **your own Python**. The two Python dependencies (`pyusb`, `pycryptodome`) are fetched
from PyPI by *your* `pip` into a local `.venv` (created by `./install.sh`); CPython, `tkinter`, and
their transitive native libraries (OpenSSL, Tk/Tcl, the X11 stack, freetype, fontconfig, zlib, etc.)
all come from **your system's Python** - this project ships none of them, so their redistribution
notices are not our obligation. Their license texts (for reference) are still listed in
[`licenses/README.md`](licenses/README.md).
> If you instead build a self-contained PyInstaller onefile yourself (`build/build.sh`), *that*
> binary embeds CPython + ~90 native libraries and you become the redistributor of them - see
> [`licenses/THIRD_PARTY_BUNDLED.md`](licenses/THIRD_PARTY_BUNDLED.md) for the enumeration and
> obligations. The **published release does not do this**; it distributes source + the native flash
> tools below.
## Bundled device blobs
| Component | Purpose | Notes |
|---|---|---|
| **my_write5_dram.bin** | the bad-block-aware DRAM NAND writer run on-device | diskOS project code - source: `flash/my_write5.c` |
| **disc_spl_lpddr3.bin** | Ingenic X2000 USB stage-1 SPL (DRAM init) | **GPL-2.0** - built from source: Ingenic-community/uboot-xburst `1060b516` + our LPDDR3 patches. Corresponding source in `spl-src/`; see `SPL_SOURCE.md`. (No vendor/USBCloner binary is redistributed.) |
## Python dependencies (fetched by your pip, not redistributed by us)
`./install.sh` installs these from PyPI into a local `.venv`; **CPython** comes from your own system
Python. This project does not ship any of them, so their license texts are listed here only for
reference. (**PyInstaller** is used *only* if you build the optional onefile yourself; it is not
involved in the source release.)
| Component | License |
|---|---|
| **pyusb** (USB device detection) | BSD-3-Clause |
| **pycryptodome** (AES-decrypt of FiiO OTA chunks) | BSD-2-Clause + public-domain (Unlicense) |
| **CPython** (your system's) | Python Software Foundation License |
| **PyInstaller** runtime bootloader (only for a self-built onefile) | GPL-2.0 **with a bootloader exception** permitting distribution of the packaged app under any license |
## Bundled shared libraries (macOS build)
| Component | License |
|---|---|
| **libusb-1.0** (bundled next to usbboot on macOS) | LGPL-2.1 |
## diskOS's own code
- **The Python installer, build scripts, and docs** in this repo are licensed **MIT** -
`Copyright (c) 2026 diskOS contributors`. See `LICENSE`.
- **The diskOS UI (`payload/mq_ui`)** ships as a **binary-only** component (static-musl, MIPS): its
source is not yet published and it is **not** covered by the MIT license above.
**diskOS UI Binary License:** *You may use and redistribute the `mq_ui` binary verbatim - on its own
or as part of the diskOS installer - free of charge. It is provided **AS IS, without warranty of any
kind**. Its source is not published, and no right to modify, decompile, or reverse-engineer it is
granted. The embedded third-party components below retain their own licenses.* © 2026 the diskOS
author (alias **b0hemia**).
It statically incorporates these third-party components, whose licenses apply to the shipped binary:
| Embedded in `mq_ui` | License | Text / source |
|---|---|---|
| **musl libc** (static C runtime) | MIT | `licenses/MIT-musl.txt`; source: https://musl.libc.org/ |
| **LVGL** (UI toolkit) | MIT | `licenses/MIT-LVGL.txt` |
| **JSMN** (JSON parser) | MIT | `licenses/MIT-JSMN.txt` |
| **SQLite** (amalgamation) | Public domain | https://sqlite.org/copyright.html |
| **MD5** (Peslyak/Solar Designer) | Public domain | in the (unpublished) UI source |
| **QR Code generator** (Nayuki `qrcodegen`) | MIT | `licenses/MIT-qrcodegen.txt` |
| **TJpgDec** (tiny JPEG decoder, via LVGL) | BSD-style (ChaN) | `licenses/LICENSE-TJpgDec.txt` |
| **Montserrat** font (via LVGL built-in fonts) | SIL OFL 1.1 | `licenses/OFL-1.1-Montserrat.txt` |
| **Source Han Sans SC** (CJK fallback font, subset) | SIL OFL 1.1 | `licenses/OFL-1.1-SourceHanSans.txt` |
| **Font Awesome Free** glyphs (via LVGL `LV_SYMBOL_*`) | OFL 1.1 (fonts) + CC-BY 4.0 (icons) | `licenses/OFL-1.1-FontAwesome.txt`, `licenses/CC-BY-4.0.txt` |
## NOT distributed by this installer
- **FiiO's stock rootfs** - you supply your own official firmware; the installer only reads it locally
and never redistributes it.
- **ffmpeg** - used at runtime for album-art decoding, but it is part of FiiO's stock firmware already
on the device (`/usr/bin/ffmpeg`); the installer does **not** ship it.
---
### Compliance checklist (done)
- ✅ Full license texts shipped in [`licenses/`](licenses/) (GPL-2.0, LGPL-2.1, BSD, PSF, LVGL-MIT,
dropbear, Font Awesome OFL/CC-BY) - see [`licenses/README.md`](licenses/README.md).
- ✅ diskOS installer license stated: **MIT** (`LICENSE`). The `mq_ui` binary is documented as
binary-only (source unpublished, not MIT) with its embedded LVGL/JSMN/Font Awesome notices shipped.
- ✅ Exact upstream versions pinned and their **complete corresponding source shipped in-tree** for the
GPL/LGPL native binaries: squashfs-tools 4.6.1, liblzo2 2.10, libusb-1.0 1.0.27, the SPL, and
usbboot - in [`corresponding-source/`](corresponding-source/) and [`spl-src/`](spl-src/). Source
travels from the same place as the binaries; no separate written offer is needed.
+288
View File
@@ -0,0 +1,288 @@
# diskOS
**diskOS** is a custom player UI/firmware for the **FiiO Snowsky Disc** digital audio player
(Ingenic X2000). It replaces the stock interface, and ships with an installer (run from source with
your own Python; a setup script sets up a local virtual environment) that flashes it onto the device
over the chip's mask-ROM USB mode - building the image **from your own stock firmware**, so no FiiO
rootfs is redistributed. The installer tooling in this repo is open
source; the diskOS UI itself (`payload/mq_ui`) currently ships as a **binary-only component**
(see [License](#license)).
> ⚠️ **Unsupported beta tool - read this.** Installing **erases and rewrites the device's main
> root filesystem**. Power loss, host sleep, a bad cable, a software defect, an unsupported
> DRAM/NAND variant, or running it on the wrong X2000 device can leave the player unbootable, lose
> data, or require hardware recovery. Mask-ROM reflashing recovered the tested unit(s), but
> **recovery is not guaranteed** for every unit or every failure. This may void your warranty.
> Not affiliated with or endorsed by FiiO, Snowsky, or Ingenic. **Proceed at your own risk; no
> warranty or support is promised.** Back up your data and keep the installer's saved stock image
> on separate storage.
> 🧪 **BETA.** Validated on the **Winbond W63AH6NKB (LPDDR3)** DRAM - the chip the Snowsky Disc
> uses. The Disc's own stock bootloader initializes only this chip, so every Disc that runs stock
> firmware has it; this is the Disc's DRAM, not one of several variants. We have flashed and booted
> our own unit(s), but wide field-testing is still ongoing, so treat it as beta. In the unlikely
> event a future hardware revision ever ships different DRAM, the flash fails safe at memory init
> (the device stays mask-ROM-recoverable) rather than completing. Report your results.
## Documentation
| Doc | What's in it |
|---|---|
| [`docs/HARDWARE.md`](docs/HARDWARE.md) | Live-probed hardware capability map: SoC, the quad CS43131 balanced DACs, display planes, power ICs, wireless, USB, and the stock-vs-hardware gap list. |
| [`docs/COMMAND_MAP.md`](docs/COMMAND_MAP.md) | The player IPC command surface: ~221 `mq_player` tags, reply frames, and the MCU/SPI command set - what you drive to build features. |
| [`docs/RE_CATALOGUE.md`](docs/RE_CATALOGUE.md) | Reverse-engineering of the `mq_player`/`mq_ui` binaries: structure, tables, string maps, network receivers. |
| [`NOTICE.md`](NOTICE.md) | Third-party components and their licenses (GPL usbboot, squashfs-tools, the SPL, etc.). |
| [`SPL_SOURCE.md`](SPL_SOURCE.md) | GPL corresponding source + build recipe for the stage-1 DRAM bring-up bootloader. |
| [`DEPENDENCY_INVENTORY.md`](DEPENDENCY_INVENTORY.md) | Libraries a *self-built* onefile would bundle + their obligations (the source release does not bundle these). |
| [`docs/PRIVACY.md`](docs/PRIVACY.md) | What the installer and the on-device UI send over the network. |
| [`agents/`](agents/) | A project brief you can drop into Claude Code or Codex to work on diskOS with an AI agent. |
| [`SECURITY.md`](SECURITY.md) / [`CONTRIBUTING.md`](CONTRIBUTING.md) | How to report vulnerabilities; how to contribute safely. |
| [`licenses/`](licenses/) | Verbatim license texts for the shipped third-party components. |
## First-time setup
The installer runs from source with your own Python. A one-time setup script builds a local
virtual environment and installs the two Python dependencies into it (nothing is installed
system-wide):
```bash
./install.sh
```
You need **Python 3.8+**. The script also checks for two optional system components and prints the
exact package to install if either is missing:
- **Tk / tkinter** - only for the *graphical* installer (the command line works without it).
Debian/Ubuntu: `sudo apt install python3-tk`.
- **libusb-1.0** - to detect the device in mask-ROM mode.
Debian/Ubuntu: `sudo apt install libusb-1.0-0`.
After setup, run everything through `./diskos-installer` (it uses the `.venv` automatically).
## Install (graphical)
1. Launch the graphical installer: `./diskos-installer gui`.
2. Choose **Install diskOS**, pick your FiiO firmware `.zip`, and a variant:
- **Public** - no *always-on* root shell (recommended). Debug Mode can still enable SSH on
demand from the UI (opt-in, off by default - see below).
- **Dev** - adds an always-on USB-serial **root shell**. ⚠️ **This is a passwordless root shell
available to anyone with physical USB access, on every boot; it bypasses normal device
security.** Only use it on a development device you control, never an everyday or untrusted one.
3. Put the device in **mask-ROM**: power it **off**, hold **Volume-Down**, and plug in USB (the
screen stays **black** - that's correct).
4. Click **Install**, tick the acknowledgement, and **Begin**. Don't disconnect or let the computer
sleep during the flash (~**60-90 minutes**).
5. When it verifies, **power-cycle** the device. The UI is embedded in the flashed image, so first
boot installs diskOS automatically - **no microSD step needed**.
## Install (command line)
```bash
./install.sh # one-time: build the .venv + install Python deps
./diskos-installer doctor # check host + bundled tools + device
./diskos-installer install --firmware SNOWSKY_DISC_update_*.zip --variant public
./diskos-installer restore-stock # deactivate diskOS -> reflash your saved stock rootfs
./diskos-installer remove # delete the installer's saved files from this computer
```
## Requirements
- Your device's **official FiiO firmware** as a `.zip` (we never ship FiiO's rootfs - you supply
it; download it from FiiO's firmware page for the Snowsky Disc). The installer decrypts and
extracts the stock rootfs from it locally.
- A USB cable and ~**60-90 minutes** for the flash.
- **Python 3.8+** and the two pip dependencies (installed into a local `.venv` by `./install.sh`).
- USB access to the mask-ROM device (`a108:eaef`). **Don't run the installer as root** - it keeps your
saved recovery image and state under your home directory, and `sudo` would misplace them. Instead
install the bundled udev rule once so your normal user has access:
```bash
sudo cp udev/70-diskos-maskrom.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules && sudo udevadm trigger
```
(The whole build+save+flash runs as one user process; there is no separate "flash step" to elevate.)
- **Linux (x86_64):** this is the released platform - the tarball ships the native flash tools
prebuilt in `vendor/linux-x86_64/`.
- **macOS (Apple Silicon + Intel):** no release artifact yet; it's a **build-from-source** path -
clone the repo and run `build/build-macos.sh` first (`libusb` via `brew install libusb`). See
*For developers*. Treat macOS as unverified until built and flashed.
## Remove diskOS / restore stock
`restore-stock` reflashes the stock rootfs the installer built and saved during install - a
checksum-verified reconstruction of your firmware's rootfs (not a dump of the device's original
partition). This **deactivates diskOS**; inert diskOS files under `/usr/data` remain until you
delete them - it is not a factory wipe. You can also switch back temporarily:
**Settings → System → Default UI → Stock**, or hold **Vol-Up at power-on** to boot the other UI once.
If a flash fails or is interrupted, the main rootfs may be **partially written** and the device
may not boot normally. In the tested cases you can return to mask-ROM (power off, hold Vol-Down,
replug) and re-flash or restore your saved stock image. Mask-ROM is normally reachable because it
lives in on-chip ROM and is entered by a button combo before any flashed code runs, but recovery
is **not guaranteed** on untested hardware or every failure mode.
## What's proven vs. beta (honest)
- ✅ **Flash mechanism + image build** - proven; it's how diskOS was flashed to real hardware,
including the bad-block-aware writer skipping factory bad blocks and verifying every block.
- ✅ **Firmware extraction** - reproduces the stock rootfs byte-for-byte from FiiO's zip.
- ✅ **Linux** - the app builds and flashes end-to-end.
- ⚠️ **macOS** - code is macOS-aware and the build recipe is provided, but the macOS artifact has
not yet been produced/tested on Apple hardware. Treat as unverified until built + flashed.
- ⚠️ Each stock firmware version should be flash-tested before it's declared supported
(V2.09 and V2.28 so far).
## Known issues (this beta)
diskOS is an early beta. What we know about:
- **Firmware coverage.** Only **V2.09** and **V2.28** are flash-tested. Newer stock versions use
different internal command codes and are refused by default (override at your own risk).
- **~90-minute flash.** A full install writes **and verifies** the whole root filesystem over USB, so
it takes roughly **60-90 minutes**. Don't disconnect or let the host sleep. (Most of that time is a
conservative fixed wait; a faster writer is planned.)
- **No on-device updates.** Updating diskOS means re-flashing with the installer; there is no
over-the-air path yet.
- **microSD at cold boot.** The card is auto-mounted a few seconds into boot. If your library is
empty right after a **cold** boot, reinsert the card once and it should mount.
- **Output/work modes.** USB-DAC, Bluetooth-receiver, and USB-storage modes are wired but lightly
tested; local playback is the well-worn path.
- **USB-serial debug is unreliable.** The optional serial shell can be finicky (a USB CDC-ACM
flow-control quirk); prefer **Debug Mode's SSH over WiFi** for remote access (see below).
- **Last.fm scrobbling is unverified beta.** The building blocks (HTTPS transport, request signing,
parsing) are tested, but the full connect-and-scrobble round-trip against a live Last.fm account has
not yet been run end-to-end. It is **off by default** and needs your own Last.fm API key; treat it as
experimental. Credential setup transfers your API key over your **local network in plain HTTP** - see
[`docs/PRIVACY.md`](docs/PRIVACY.md).
Found something else? Open an issue with your device's **firmware version** and any on-screen
**error code**.
## Debug Mode (optional remote access)
For development or troubleshooting, diskOS can expose a remote shell **on demand** - it is **OFF by
default**. Open **Settings → System → Debug Mode → Enable Debug**. The screen then shows:
- an **SSH** command (`ssh root@<device-ip>`) reachable over WiFi, and
- a **fresh random password**, generated per-enable and shown on that screen.
> ⚠️ **This grants root access to the device over your network while it is on.** Only enable it on a
> network you trust, and turn it **off** when you are done. The password is random and rotates each
> time you enable it; the device's stock password is never used or exposed.
>
> **Where the password lives:** while Debug Mode is on, the current password is also written in
> **plaintext** to `/usr/data/sshd/current_pw` (mode 0600, root-only) so the screen can show it again
> after a UI restart. Disabling Debug Mode deletes it. A **reboot while it is still on** can leave a
> stale copy - harmless, because a reboot drops the SSH overlay (so that password no longer works
> until you re-enable), but you can delete the file manually if you want it gone. It is only as
> protected as physical/root access to the device's storage.
>
> **SSH server:** Debug Mode uses **Dropbear 2022.83**, which predates the CVE-2023-48795 "Terrapin"
> Strict-KEX mitigation (an update is planned). Because Debug Mode is opt-in and short-lived, exposure
> is limited, but keep it off on untrusted networks. Serial (USB) is available only on **dev** builds
> and is unreliable (see the known issue above); public builds expose no serial shell.
## How it works (in brief)
diskOS runs by a small hook in the stock `fiio_init.sh` that launches our UI (`mq_ui`) instead of
the stock one. Because the rootfs is a **read-only squashfs**, enabling that hook means rewriting
the rootfs partition (mtd2) - hence the flash. The UI itself is embedded in the image and installed
to the writable `/usr/data` on first boot, verified against a baked SHA-256 manifest; if it does
not match, the stock UI runs instead (**fail-closed**). You **cannot** install from the device's own
"System updates" menu - that path checks a signature we can't forge, so mask-ROM USB is the only
way in. See [`docs/HARDWARE.md`](docs/HARDWARE.md) for the partition map and the rest of the hardware.
## For developers
The installer already **runs from source** - `./install.sh` then `./diskos-installer` (see
*First-time setup*). The release tarball ships the native flash tools prebuilt in
`vendor/<os>-<arch>/`; a fresh **git clone** does not include them (they are large binaries kept out
of git), so build them once:
```bash
# Build the native flash tools into vendor/<os>-<arch>/ :
bash build/build-usbboot-static.sh # static usbboot (Linux)
bash build/build-squashfs-static.sh # static mksquashfs/unsquashfs (Linux)
bash build/build-macos.sh # usbboot + libusb (run on a Mac)
```
Optionally, you can package everything into a single self-contained binary (this is **not** how the
release ships, and it bundles ~90 system libraries - see
[`licenses/THIRD_PARTY_BUNDLED.md`](licenses/THIRD_PARTY_BUNDLED.md) before redistributing one):
```bash
bash build/build.sh # -> build/dist/diskos-installer (optional onefile)
```
See [`build/README-vendor.md`](build/README-vendor.md) for how the native tools are produced and the
portability requirements. Working on diskOS with an AI agent? Start with
[`agents/AGENTS.md`](agents/AGENTS.md).
## Error codes (for bug reports)
If the installer stops with an error, it prints a short code like `[E301]`. **Quote that code**
when reporting an issue - it tells us exactly where it stopped. In the tested cases the device
stays reachable in mask-ROM and your saved stock image can be re-flashed, but recovery is not
guaranteed on untested hardware or every failure mode.
| Code | Meaning |
|---|---|
| **E1xx** | **Environment / preflight - nothing was written to the device** |
| E101 | Unsupported host OS/arch (Linux/macOS only) |
| E102 | A bundled component is missing - re-download the installer |
| E103 | A bundled tool can't run (its directory is mounted `noexec`, or a missing library) |
| E110 | No device in mask-ROM mode (power off, hold Vol-Down, plug USB) |
| E111 | More than one device in mask-ROM mode - unplug the others |
| E112 | Can't confirm exactly one device (USB permissions / no libusb) |
| E120 / E121 / E122 | Image not found / wrong size / not a squashfs |
| E140 / E141 | No firmware `.zip` provided / no saved stock image to restore |
| E142 | `DISKOS_INSTALLER_HOME` points at a non-empty, non-state directory |
| **E2xx** | **Firmware extract & image build** |
| E201 / E202 | Input isn't a zip / unsafe zip (path escape or bomb) |
| E210 | FiiO OTA manifest missing, ambiguous, or unsafe |
| E211 | AES-decrypt failed (wrong key or not a FiiO OTA) |
| E212 / E213 | Rootfs chunks missing/duplicate / assembled image invalid |
| E220 / E221 | Not a Snowsky Disc rootfs / untested firmware version |
| E222 / E223 | diskOS UI binary invalid / boot-hook anchor problem |
| E224 | Stock rootfs doesn't match the known-good pinned hash (modified/corrupt firmware) |
| E230 / E231 / E232 | squashfs pack/unpack failed / image too large / output failed validation |
| E233 | A file in the stock rootfs resolves outside it via a symlink (crafted/corrupt firmware) |
| E240 | Stock image larger than the partition (refusing to truncate) |
| E250 | Invalid variant (must be `public` or `dev`) |
| **E3xx** | **Flashing (host side)** |
| E301 | No result read back - flash outcome UNKNOWN (assume failed, re-flash) |
| E302 | Short/truncated result readback - flash outcome UNKNOWN (assume failed, re-flash) |
| E303 | **Flash timed out - the device stopped responding (likely reset mid-flash)** |
| E310 | Flash verify failed - see the device code below |
| **F1xx** | **Device writer aborted and reported a coded reason.** It fails closed rather than committing a bad block mapping, but blocks erased/written before the abort may already be modified - the rootfs can be partially written. Return to mask-ROM and re-flash or restore stock. |
| F101…F106 | init/ECC, out-of-space, block-write fail, too many bad blocks, ECC re-enable, bad-block marker |
Exit codes: `0` success, `1` error, `2` usage/preflight refusal (unsupported host, missing
`--firmware`, bad arguments, or Tk unavailable for the GUI), `3` you cancelled at a prompt,
`130` interrupted.
## Support
diskOS is a solo, open-source hobby project. If it's useful to you and you'd like to help keep the
work going, you can leave a tip:
[![Ko-fi](https://img.shields.io/badge/Ko--fi-Support%20diskOS-FF5E5B?logo=ko-fi&logoColor=white)](https://ko-fi.com/b0hemia)
**[ko-fi.com/b0hemia](https://ko-fi.com/b0hemia)** - entirely optional, and hugely appreciated.
## License
- **Original diskOS installer files** in this repo (the Python installer, build scripts, docs)
are **MIT** - see [`LICENSE`](LICENSE). SPDX: `MIT`.
- **Third-party components** retain their own licenses and ship with corresponding source: the native
flash tools **usbboot** and **squashfs-tools** (**GPL-2.0**), the libraries they statically link
(**liblzo2** GPL-2.0, **libusb-1.0** LGPL-2.1, zlib/liblzma), and the stage-1 **SPL** (**GPL-2.0**).
The corresponding source for all of these ships in [`corresponding-source/`](corresponding-source/)
(SPL also in [`spl-src/`](spl-src/) + [`SPL_SOURCE.md`](SPL_SOURCE.md)); see
[`NOTICE.md`](NOTICE.md) for the full mapping and the relink path for the LGPL libusb.
- **The diskOS UI (`payload/mq_ui`)** currently ships as a **binary-only** component. It is not
covered by the MIT license above and its source is not yet published; treat it as a redistributable
binary whose provenance, version, and third-party content are still being documented. If/when the
UI source is published this note will be updated.
> **Do not redistribute the `diskos_*.bin` images the installer builds** - they contain FiiO's
> rootfs. The installer produces them locally from *your* firmware; that is fine for your own use,
> but sharing them would redistribute FiiO's software. Share the installer, not the built image.
+64
View File
@@ -0,0 +1,64 @@
# Security policy
diskOS is an **unsupported beta** that flashes firmware over a device's mask-ROM USB mode. Because
a defect here can brick a device or write to the wrong hardware, security and safety reports are
taken seriously.
## Reporting a vulnerability
**Do not open a public issue for a security or device-safety vulnerability.** Instead, use GitHub's
private vulnerability reporting for this repository (the "Report a vulnerability" button under the
**Security** tab), which opens a private advisory visible only to the maintainer.
Please include, where relevant:
- What the issue is and how to reproduce it.
- The impact (e.g. writes outside the intended partition, wrong-device targeting, host privilege
issues, data exposure).
- Your host OS, the installer version, and the device firmware version.
Please redact anything device-identifying from logs before sending: serial numbers, Bluetooth/Wi-Fi
MAC addresses, and network credentials.
## Especially in scope
- **Wrong-device / wrong-partition writes** - anything that could let the flasher erase or write a
device it should have refused, or write outside the intended rootfs region.
- **Host privilege issues** - the installer is designed to run as your **normal (non-root) user**
(USB access via the bundled udev rule); it should not need `sudo`. Path-traversal, symlink-follow,
arbitrary-delete, or predictable-temp-file issues matter.
- **Unauthenticated input** - the installer extracts a squashfs and decrypts a firmware package;
report anything that lets crafted input escape the work directory or run code.
- **Bricking-class bugs** - a report that a specific sequence leaves a device unrecoverable.
## Debug Mode (on-device remote access)
diskOS has an opt-in **Debug Mode** (Settings → System → Debug Mode), **off by default**, that starts
an SSH server over WiFi. It uses a **random password generated per enable**, placed into a private
shadow file bind-mounted over `/etc/shadow`; the device's stock password is never used or exposed.
While it is on, it grants **root access over the network**.
- **Password storage:** while Debug Mode is on, the current password is also stored in **plaintext** at
`/usr/data/sshd/current_pw` (mode 0600, root-only) so the UI can redisplay it after a restart;
disabling Debug Mode deletes it. A reboot while still enabled can leave a stale copy - the SSH
overlay is dropped on reboot so that password no longer authenticates until re-enabled. It is only
as protected as root/physical access to the device.
- **SSH server:** Dropbear **2022.83**, which predates the CVE-2023-48795 "Terrapin" Strict-KEX
mitigation (update planned); exposure is limited by Debug Mode being opt-in and short-lived.
- **Serial:** the local USB-serial root shell exists only on **dev** builds and is passwordless-root by
design (physical-USB access only); **public builds have no serial shell**. Report only if it is
reachable without physical access.
In scope: anything that exposes the debug password, leaves SSH running (or the shadow overlay mounted)
after it should be off, lets the overlay corrupt/leak the on-disk credentials, or reaches the stock
`/etc/shadow` over the network.
## Response
This is a hobbyist project with no SLA, but security and bricking reports are prioritised over
features. Expect an initial acknowledgement within a week or so. Fixes for confirmed
device-safety issues will be called out clearly in the release notes.
## Supported versions
Only the latest release is supported. There are no backported fixes for older builds.
+94
View File
@@ -0,0 +1,94 @@
# Stage-1 SPL - corresponding source & build (GPL-2.0)
The installer's USB stage-1 loader (`flash/disc_spl_lpddr3.bin`) that brings up DRAM before
the on-device NAND writer runs is **built entirely from GPL source** - no vendor/USBCloner
binary is redistributed. This file is the GPL-2.0 "corresponding source" pointer + build recipe.
## Source
- **Upstream:** Ingenic-community **uboot-xburst**, U-Boot 2013.07, commit `1060b516` (GPL-2.0,
`COPYING` in-tree). https://github.com/Ingenic-community/uboot-xburst
- **Our patches** (a small, self-contained delta adding W63AH6NKB LPDDR3 support to the X2000
USB "burner" SPL, ported from the GPL tobunto/u-boot X2000 tree):
1. `-fcommon` + a mask-ROM return shim in `arch/mips/cpu/xburst2/x2000/start.S` (DDR-only
stage-1 returns to the mask ROM after DRAM init).
2. `ddr_mr11` field + macro in `ddr_reg_data.h`.
3. `case LPDDR3:` MR sequence (MR63,10,1,2,3,11) in `ddrc_dfi_init()`.
4. Force `type = LPDDR3` in `sdram_init()` (this part's controller CFG.TYPE reads as LPDDR2).
5. **PHY PLL divisors `FBDIV=8, PDIV=4`** for W63AH6NKB LPDDR3 @400 MHz (the tree's stock
20/5 sets the wrong PHY clock and DDR training never converges).
6. Bounded every hardware-poll (no infinite hang on a bad unit) + a small TCSM breadcrumb
record for field diagnostics.
7. **Robust watchdog disable** (clear `WDT_TCER.TCEN` then stop the WDT clock via `TCU_TSSR`)
**and dropped the redundant dynamic-calibration sweep** - the stock code stopped only the WDT
clock (leaving the counter armed, which reset the device ~36 min into a flash), and the sweep
left a marginal PHY calibration. Device-verified: survives 25 min idle + full 76 MB DRAM
round-trip intact (the 2026-08-25 flash-failure fix).
The complete patched source is shipped as `spl-src/uboot-xburst-lpddr3-src.tar.gz`, with the
delta over upstream also provided as a readable patch series in `spl-src/patches/`. Frozen at the
commit the released binary was built from: `7caf048` / tag `lpddr3-working-v2` (Ingenic-community/uboot-xburst `1060b516` + 8 patches).
## Toolchain
- `gcc-10-mipsel-linux-gnu` (10.5.0) + binutils for mipsel. (The tree's compiler-compat headers
stop at gcc-10; newer GCC fails. Pin GCC 10.)
## Build + assemble
```sh
export ARCH=mips CROSS_COMPILE=mipsel-linux-gnu- # gcc-10 on PATH as mipsel-linux-gnu-gcc
make distclean
make burner_x2000_lpddr2_config
make -j # -> spl/u-boot-spl.bin
# USB stage-1 = DDR param block + zero-pad to 0x800 + spl/u-boot-spl.bin
# load 0xb2401000, exec 0xb2401800; see flash/assemble_stage1.py
```
## DDR parameter block
The stage-1 prepends a 0x800-byte parameter region the SPL reads at `0xb2401000`:
a **BDIF** (board-info) record + a **DDR** record of 35 Winbond W63AH6NKB-BI register words
(controller/PHY/MR/timing values - hardware register settings for LPDDR3 @400 MHz, 24 MHz
EXTAL, 800 MHz PLL).
**Provenance (honest, and an OPEN item):** these values were **captured from the device's factory
configuration** (they match what the vendor SPL uses), NOT independently re-derived from the
W63AH6NKB datasheet. `flash/assemble_stage1.py` copies roughly **332 bytes** of this captured
block into the shipped stage-1 binary. These are low-level hardware register settings, but we do
**not** claim, as a legal conclusion, that "they are physical facts, therefore unrestricted." The
provenance of these vendor-origin bytes is an **unresolved compliance item**. Before any wide/public
binary distribution it should be resolved by one of: (a) independently regenerating the complete
parameter/BDIF block from documented datasheet values; (b) obtaining and documenting redistribution
permission; or (c) having counsel review and approve the provenance with an accurate disclosure of
the copied vendor-origin bytes. Until then the captured block ships as both the working block and a
regression oracle, and this limitation is disclosed here.
## Supported hardware
This stage-1 is built for the **Winbond W63AH6NKB-BI LPDDR3** DRAM and configures that chip.
**The Snowsky Disc uses this one DRAM chip.** The Disc's own stock SPL contains exactly one DRAM
config - `LPDDR3_W63AH6NKB-BI` - and initializes only that chip. Because a Disc must run FiiO's
stock firmware (whose SPL brings up only W63AH6NKB), any Disc in the field necessarily has this
chip; FiiO cannot ship a unit with DRAM its own bootloader can't initialize. So supporting
W63AH6NKB covers every current Disc, not "one of several." (The chip names `W97BV6MK` and
`NK6CL256M16` that appear in Ingenic's cloner configs are for *other* X2000-family boards -
x2000e/x2000h/m300 - not the Disc.)
**Residual / tail risk:** we have physically verified our own unit(s); "every Disc has W63AH6NKB"
is a strong inference from the stock SPL, not a survey of many units, so a hypothetical future
hardware revision with different DRAM cannot be ruled out. The SPL **fails safe** on DRAM it cannot
bring up: bounded polls return to the mask ROM instead of hanging, and a TCSM breadcrumb
@0xb24017c0 reports the failing stage - no brick, still mask-ROM-recoverable. Note the installer
does **not** run a separate DRAM verify-before-erase gate on each flash, so DRAM that *initialises
but is marginal* is a residual risk (a bad read-back would be written to NAND and would verify
against that same DRAM). A future revision could add a pre-erase DRAM round-trip and/or multi-chip
auto-detect if a different Disc DRAM ever turns up.
## Verification
Device-qualified over Ingenic mask-ROM USB boot **during development**: the stage-1 loads,
initialises LPDDR3, returns to the mask ROM, and a DRAM write/read round-trips byte-for-byte. This
was the bring-up qualification of the SPL itself; it is **not** a gate the installer re-runs on
every flash (see the residual-risk note above).
+86
View File
@@ -0,0 +1,86 @@
# diskOS - working rules for AI coding agents
This file is written for an AI coding agent (Claude Code, Codex, or similar) helping someone
hack on **diskOS** - a custom UI/firmware for the FiiO Snowsky Disc digital audio player
(Ingenic X2000 SoC). Drop it in as your `CLAUDE.md` or `AGENTS.md`, or paste it into the
session, and follow it. It encodes the discipline that keeps this project honest and the
device un-bricked.
## The one rule that matters most: verify, do not guess
This device's hardware, firmware, audio path, and command surface are **non-obvious and easy
to hallucinate**. Before you assert anything about how the device behaves:
- **Check `docs/HARDWARE.md`** (live-probed hardware capability map) for chip part numbers,
sample rates, dev nodes, partition layout, I2C addresses.
- **Read the actual binary / source** for what code does - never state it from training priors
or from earlier in the session.
- If a claim is not in a doc and you cannot verify it against the device or a binary, **say it
is unverified** rather than stating it confidently.
"Probably", "should be", "likely already" are hallucination flags. Resolve them by reading
first.
## Hardware facts that are easy to get wrong
- Wireless chip is **BCM43438 / AP6212 (2.4 GHz only, BT over UART)**. There is **no 5 GHz**.
(Old notes saying "BCM4345C5" are wrong - those `.hcd` files are leftovers for other models.)
- **Four CS43131 DACs**, fully balanced (L+/L-/R+/R-), driven by a kernel driver via **ioctl**
on `/dev/cs43131{,b,c,d}` - **not** via ALSA controls.
- **No physical LED** on the unit. `/sys/class/leds` is empty; `RGB_*` config fields are
vestigial. Plan no LED features.
- **No GPU / VPU / hardware JPEG / DVFS / thermal sensors.** MSA SIMD is the only accel.
- The rootfs partition (`mtd2`) is a **read-only squashfs**, which is why the boot hook cannot
be edited in place; persistent state lives in the writable `/usr/data` (`mtd7`).
See `docs/HARDWARE.md` for the full map and the reproducible probe commands.
## Repo layout
- `diskos_installer/` - the Python installer (GUI + CLI) that builds a diskOS image from the
user's own stock firmware and flashes it over mask-ROM USB.
- `flash/` - the low-level flashing pieces: the mask-ROM writer source (`my_write5.c`), the
stage-1 SPL, and helper scripts.
- `spl-src/` - GPL corresponding source for the stage-1 DRAM bring-up SPL (patch series over
upstream U-Boot). See `SPL_SOURCE.md`.
- `src/usbboot/` - the Ingenic mask-ROM USB loader (third-party GPL; do not rewrite).
- `payload/` - the on-device first-boot hook and the diskOS UI binary (`mq_ui`).
- `docs/` - hardware map and other reference docs.
- `licenses/`, `NOTICE.md` - third-party attribution and license texts.
## Device-safety rules (read before touching the device)
- A flash **rewrites the read-only rootfs**. It is **normally recoverable** because the Ingenic
mask-ROM USB mode lives in on-chip ROM and is reached by a button combo *before* any flashed
code runs - so a bad flash can usually be re-flashed. This is the safety net, not an A/B slot, and
recovery is **not guaranteed** on every unit or failure mode (match the README's wording).
- The first-boot install is **fail-closed**: if the UI cannot be verified against the baked
manifest (SHA-256), the stock UI runs instead. Never weaken that contract.
- **You cannot install from the device's own "System updates" menu** - it checks an ECDSA
signature against FiiO's public key, which a custom image will not have. Mask-ROM USB is the
only way in.
- The mask-ROM USB link is **flaky** - it allows roughly one `usbboot` run per power-cycle and
hangs early ~1 in 3. If a run hangs at the download-to-start transition, power-cycle back
into mask-ROM and retry rather than fighting it.
## Working habits
- **Honest limitations.** When something is blocked by hardware (no 5 GHz, no GPU, DAC ioctls
not yet reverse-engineered) or a toolchain gap, say so plainly instead of implying it works.
- **Test before claiming success.** A change to the image builder or the boot hook is not
"done" until it is validated against a real build / a real device, not just a passing
typecheck. The installer carries offline validation (independent squashfs extraction, hash
round-trips) precisely so the expensive on-device flash only tests what it must.
- **Fail closed, log loudly.** Every error path in the installer has a code (`E1xx` preflight,
`E2xx` build, `E3xx` flash, `F1xx` device-writer). If you add a failure mode, give it a code
and document it in `README.md`.
- **Cite file:line** when you summarize what changed, so a human can verify it.
## Contributing
- Keep the flashed image = stock FiiO rootfs + the minimal diskOS patch. We do **not**
redistribute FiiO's rootfs; the installer builds it from the user's own firmware zip.
- GPL components (usbboot, squashfs-tools, the SPL) ship with corresponding source. If you
touch how they are bundled, keep the source and `NOTICE.md` in sync.
- New firmware versions must be **flash-tested on real hardware** before being declared
supported - command-tag meanings differ across versions and a wrong command can misbehave.
+26
View File
@@ -0,0 +1,26 @@
# agents/
Instructions for working on diskOS with an AI coding agent.
`AGENTS.md` in this folder is a ready-made project brief: the hardware facts that are easy to
get wrong, the repo layout, the device-safety rules, and the "verify, do not guess" discipline
that keeps this project honest and the device un-bricked.
## How to use it
- **Claude Code:** copy `agents/AGENTS.md` to `CLAUDE.md` at the repo root (or into
`~/.claude/`), or start a session and tell Claude to read `agents/AGENTS.md` first.
- **Codex:** copy it to `AGENTS.md` at the repo root, or paste it in at the start of a session.
- **Anything else:** paste the contents in as system/context before you start.
The point is to give the agent the same guardrails we use: check `docs/HARDWARE.md` before
claiming anything about the hardware, never assert device behavior from memory, keep the
fail-closed boot contract intact, and treat a flash as recoverable-but-serious.
## Good first tasks
- Read `docs/HARDWARE.md` and the installer's `README.md`, then ask the agent to explain the
install flow back to you - a quick check that it has the right mental model.
- Add support/validation for a new stock firmware version (must be flash-tested on real
hardware before it is declared supported).
- Improve error messages / add error codes for failure modes not yet covered.
+52
View File
@@ -0,0 +1,52 @@
# Vendored native tools - portability requirements
The installer bundles native binaries under `vendor/<os>-<arch>/` and calls them
via subprocess. For a distributable build these MUST be portable across the user's
machines - not just copies of the build host's dynamically-linked binaries.
| tool | why bundled | portability requirement |
|---|---|---|
| `usbboot` | Ingenic mask-ROM USB loader (the flasher) | Build **static** against libusb compiled `--disable-udev` (drops libudev + libcap; libusb falls back to sysfs enumeration). `usbboot` has **no direct udev symbols** - they were only transitive via libusb - so this yields a binary needing only libc. Prefer full-static (musl) or, at minimum, `$ORIGIN/lib` rpath + a bundled `libusb-1.0.so` in `vendor/<tag>/lib/`. Do **not** ship arbitrary host glibc `.so`s or rely on `LD_LIBRARY_PATH` as the primary strategy. |
| `mksquashfs`, `unsquashfs` | build/extract the rootfs image | Ship **static** squashfs-tools (with lzo support - the stock image uses `-comp lzo`). |
| `my_write5_dram.bin` | the DRAM NAND writer run on-device | Architecture-neutral blob (runs on the device, not the host). Copy as-is. |
| `disc_spl_lpddr3.bin` | X2000 SPL | Same - device blob, copy as-is. |
## Status
- `vendor/linux-x86_64/` holds **fully static** `usbboot`, `mksquashfs`, and
`unsquashfs`, produced by `build/build-usbboot-static.sh` and
`build/build-squashfs-static.sh` (each verifies the binary is `statically linked`;
the squashfs build additionally runs an LZO round-trip self-test). They are static
against glibc (built with `gcc -static`), so no runtime `.so` is needed; note the
static glibc/liblzo2/libusb licensing in `../NOTICE.md` and the corresponding source
in `../corresponding-source/`. `my_write5_dram.bin` and `disc_spl_lpddr3.bin` are
device blobs, copied as-is.
- `vendor/macos-*/` is produced on a Mac by **`vendor/setup-macos.sh`** (compiles
`usbboot` from `src/usbboot/usbboot.c` against Homebrew libusb, gathers
lzo-capable squashfs-tools, copies the device blobs, and runs `dylibbundler` so
every tool is self-contained under `vendor/macos-<arch>/lib/` - no Homebrew at
runtime). `usbboot.c` is a single libusb-only file (no udev / no Linux-isms), so
it builds on macOS as-is. Then `build/build-macos.sh` packages the app.
## macOS: Intel + Apple Silicon coverage
`usbboot.c` and pyusb are portable; only the *build* is per-arch. Options:
1. **Native per-arch (most robust):** run `build/build-macos.sh` on an Intel Mac
and on an Apple Silicon Mac → two binaries. Recommended.
2. **Single file via Rosetta:** build **x86_64** only (on an Intel Mac, or with an
x86_64 Homebrew under `arch -x86_64`). The x86_64 app runs natively on Intel and
under Rosetta 2 on M-series (macOS offers to install Rosetta on first run).
One file covers both, at a small speed cost - fine for a flasher.
3. **Universal2 (advanced):** build both arches, `lipo` the vendor tools into fat
binaries, and set `target_arch='universal2'` in the spec with a universal2
Python. One native file for both, most work.
## Building portable usbboot (sketch)
1. Get the Ingenic `usbboot` source (the X2000 burn tool).
2. Build libusb static: `./configure --disable-udev --enable-static --disable-shared`
→ `libusb-1.0.a`.
3. Link `usbboot` against the static libusb; confirm with `ldd` that libudev/libcap
are gone and only libc (or nothing, if fully static) remains.
4. Verify it still enters mask-ROM and flashes on a real unit before shipping.
+40
View File
@@ -0,0 +1,40 @@
#!/bin/bash
# build-macos.sh - build the standalone diskos-installer app on macOS.
# RUN ON A MAC. Produces build/dist/diskos-installer for this Mac's arch.
#
# Intel + Apple Silicon coverage (pick one):
# * Simplest single file: build x86_64 (below, on an Intel Mac OR via an
# x86_64 Homebrew under Rosetta) - it runs natively on Intel and under
# Rosetta 2 on M-series. Needs Rosetta on M-series (macOS offers to install it).
# * Best native: build on each arch -> two binaries (diskos-installer-arm64 /
# -x86_64). Run this script on an Intel Mac and an Apple Silicon Mac.
# * Universal2: build both arches, lipo the vendor tools + use PyInstaller
# target_arch=universal2 (advanced; see build/README-vendor.md).
set -euo pipefail
cd "$(dirname "$0")/.." # installer/
[ "$(uname)" = "Darwin" ] || { echo "run this on macOS." >&2; exit 2; }
if [ "${1:-}" != "--skip-setup" ]; then
echo ">> populating vendor/ for this Mac"
bash vendor/setup-macos.sh
fi
VENV=build/venv
[ -d "$VENV" ] || python3 -m venv "$VENV"
"$VENV/bin/pip" install --quiet --upgrade pip pyinstaller pyusb pycryptodome
"$VENV/bin/pyinstaller" --clean --noconfirm \
--distpath build/dist --workpath build/work \
build/diskos-installer.spec
APP=build/dist/diskos-installer
# ad-hoc sign so it runs locally without a Developer ID (enthusiast tool).
# For distribution you'd sign + notarize with a real identity.
codesign --force --deep --sign - "$APP" 2>/dev/null || \
echo " (codesign ad-hoc skipped/failed - 'xattr -dr com.apple.quarantine $APP' if Gatekeeper blocks it)"
echo
echo "Built: $APP ($(uname -m))"
echo "Smoke test: $APP doctor"
echo "If Gatekeeper blocks it: xattr -dr com.apple.quarantine $APP"
+45
View File
@@ -0,0 +1,45 @@
#!/bin/bash
# build-squashfs-static.sh - build portable, fully-static mksquashfs + unsquashfs
# for Linux, with the compressors the installer actually uses.
#
# The installer repacks the rootfs with `-comp lzo -b 131072` and unpacks the
# stock (lzo) rootfs, so LZO is mandatory; gzip + xz are included for reading
# other firmware. Built static (liblzo2.a/libz.a/liblzma.a) so there are no
# liblzo2/libz/liblzma/glibc-version runtime deps on the user's machine.
#
# Output: installer/vendor/linux-x86_64/{mksquashfs,unsquashfs} (static, stripped).
# A cosmetic getpwuid NSS warning at link time is expected (owner-name display in
# the summary only; packing uses numeric uid/gid) and does not affect output.
set -euo pipefail
cd "$(dirname "$0")/.." # installer/
OUTDIR="$(pwd)/vendor/linux-x86_64"
WORK=$(mktemp -d); trap 'rm -rf "$WORK"' EXIT
cd "$WORK"
echo "==> fetching squashfs-tools source"
apt-get source squashfs-tools >/dev/null 2>&1 || {
echo "ERROR: 'apt-get source squashfs-tools' failed - enable deb-src or fetch squashfs-tools 4.x." >&2
exit 3; }
cd squashfs-tools-*/squashfs-tools
echo "==> building static (gzip+lzo+xz)"
make clean >/dev/null 2>&1 || true
make GZIP_SUPPORT=1 LZO_SUPPORT=1 XZ_SUPPORT=1 \
EXTRA_CFLAGS="-static" LDFLAGS="-static" -j"$(nproc)" mksquashfs unsquashfs >/dev/null
strip mksquashfs unsquashfs
for b in mksquashfs unsquashfs; do
file "$b" | grep -q "statically linked" || { echo "ERROR: $b not static" >&2; exit 5; }
done
# prove the installer's exact LZO path round-trips before installing
t="$WORK/smoke"; mkdir -p "$t/src"; echo diskos > "$t/src/f"
./mksquashfs "$t/src" "$t/o.sqsh" -comp lzo -b 131072 -noappend >/dev/null 2>&1
./unsquashfs -d "$t/u" "$t/o.sqsh" >/dev/null 2>&1
diff -r "$t/src" "$t/u" >/dev/null || { echo "ERROR: LZO round-trip failed" >&2; exit 6; }
echo "==> LZO round-trip OK"
for b in mksquashfs unsquashfs; do
install -m 0755 "$b" "$OUTDIR/$b"
echo "==> installed $OUTDIR/$b ($(sha256sum "$OUTDIR/$b" | cut -d' ' -f1))"
done
+48
View File
@@ -0,0 +1,48 @@
#!/bin/bash
# build-usbboot-static.sh - build a portable, fully-static `usbboot` for Linux.
#
# The distro's libusb-1.0.a is built WITH udev, so linking against it drags in
# libudev + libcap dynamically - which defeats portability (missing/old libudev
# on other distros). This rebuilds libusb with --disable-udev --enable-static so
# usbboot links fully static: no libusb.so, no libudev, no glibc-version pin.
# udev is only needed for hotplug events; usbboot does a one-shot vid/pid open,
# which uses libusb's sysfs backend and works without udev.
#
# Output: installer/vendor/linux-x86_64/usbboot (statically linked, stripped).
# Run on an x86_64 Linux host with build-essential + apt source access.
set -euo pipefail
cd "$(dirname "$0")/.." # installer/
ROOT=$(pwd)
SRC="$ROOT/src/usbboot/usbboot.c"
OUT="$ROOT/vendor/linux-x86_64/usbboot"
[ -f "$SRC" ] || { echo "ERROR: $SRC missing" >&2; exit 2; }
WORK=$(mktemp -d)
trap 'rm -rf "$WORK"' EXIT
cd "$WORK"
echo "==> fetching libusb source"
apt-get source libusb-1.0 >/dev/null 2>&1 || {
echo "ERROR: 'apt-get source libusb-1.0' failed - enable deb-src or fetch libusb 1.0.x manually." >&2
exit 3; }
cd libusb-1.0-*/
echo "==> configuring libusb (static, no udev)"
./configure --disable-udev --enable-static --disable-shared \
--disable-examples-build --disable-tests-build CFLAGS="-O2" >/dev/null
echo "==> building libusb"
make -j"$(nproc)" >/dev/null
LIBA=$(find "$PWD" -name libusb-1.0.a | head -1)
[ -f "$LIBA" ] || { echo "ERROR: libusb-1.0.a not produced" >&2; exit 4; }
INC=$(dirname "$LIBA")/../.. ; INC="$PWD/libusb"
echo "==> linking usbboot (fully static)"
gcc -O2 -std=c99 -I"$INC" -static -o usbboot "$SRC" "$LIBA" -lpthread
strip usbboot
file usbboot | grep -q "statically linked" || { echo "ERROR: not static" >&2; exit 5; }
install -m 0755 usbboot "$OUT"
echo "==> installed: $OUT"
echo " sha256: $(sha256sum "$OUT" | cut -d' ' -f1)"
echo " $(file -b "$OUT")"
echo "NOTE: confirm a mask-ROM GET_CPU_INFO handshake on a real device before shipping."
Executable
+35
View File
@@ -0,0 +1,35 @@
#!/bin/bash
# build.sh - produce the standalone `diskos-installer` executable for THIS host
# (Linux or macOS). PyInstaller can't cross-build, so run this on each target OS.
#
# Prereqs: python3. Everything else is created in a local venv; nothing is
# installed system-wide.
#
# Before building, populate vendor/<os>-<arch>/ with the native tools for this
# host (see build/README-vendor.md): usbboot, mksquashfs, unsquashfs,
# my_write5_dram.bin, disc_spl_lpddr3.bin (+ lib/ for any bundled .so/.dylib).
set -euo pipefail
cd "$(dirname "$0")/.." # installer/
VENV=build/venv
[ -d "$VENV" ] || python3 -m venv "$VENV"
"$VENV/bin/pip" install --quiet --upgrade pip pyinstaller pyusb pycryptodome
# sanity: the vendor dir for this host must exist
tag=$("$VENV/bin/python" - <<'PY'
import platform
s=platform.system().lower(); o={"darwin":"macos","linux":"linux"}.get(s,s)
m=platform.machine().lower()
a={"x86_64":"x86_64","amd64":"x86_64","arm64":"arm64","aarch64":"arm64"}.get(m,m)
print(f"{o}-{a}")
PY
)
[ -d "vendor/$tag" ] || { echo "ERROR: vendor/$tag missing - add native tools for this host first." >&2; exit 2; }
"$VENV/bin/pyinstaller" --clean --noconfirm \
--distpath build/dist --workpath build/work \
build/diskos-installer.spec
echo
echo "Built: build/dist/diskos-installer ($(du -h build/dist/diskos-installer | cut -f1))"
echo "Smoke test: build/dist/diskos-installer doctor"
+70
View File
@@ -0,0 +1,70 @@
# PyInstaller spec - one self-contained diskos-installer executable.
# Bundles the native flashing tools (vendor/<os>-<arch>/) and the payload
# (mq_ui + on-device init scripts) as data, plus pyusb. The result needs no
# system Python and no system packages: "remove the tool" = delete this file.
import os
ROOT = os.path.abspath(os.path.join(os.getcwd())) # run from installer/
# host tag for the vendor dir to bundle (build on each target OS)
import platform
_sys = platform.system().lower()
_os = {"darwin": "macos", "linux": "linux"}.get(_sys, _sys)
_arch = {"x86_64": "x86_64", "amd64": "x86_64", "arm64": "arm64",
"aarch64": "arm64"}.get(platform.machine().lower(), platform.machine().lower())
TAG = f"{_os}-{_arch}"
# files under vendor/ that must NOT be bundled into the app (dev-only backups, notes)
def _skip_vendor(fn):
return fn.endswith(".bak") or fn.endswith(".dynamic.bak") or fn in ("README.md",)
datas = []
vend = os.path.join(ROOT, "vendor", TAG)
if os.path.isdir(vend):
for fn in os.listdir(vend):
if _skip_vendor(fn) or os.path.isdir(os.path.join(vend, fn)):
continue
datas.append((os.path.join(vend, fn), f"vendor/{TAG}"))
libdir = os.path.join(vend, "lib")
if os.path.isdir(libdir):
for fn in os.listdir(libdir):
datas.append((os.path.join(libdir, fn), f"vendor/{TAG}/lib"))
payload = os.path.join(ROOT, "payload")
if os.path.isdir(payload):
for fn in os.listdir(payload):
datas.append((os.path.join(payload, fn), "payload"))
# FAIL the build (don't ship an unusable artifact) if any required native tool or
# payload for this host is missing.
_required_native = ["usbboot", "mksquashfs", "unsquashfs",
"my_write5_dram.bin", "disc_spl_lpddr3.bin"]
_required_payload = ["mq_ui", "S97diskos_install", "S99usbserial", "diskos-debug.sh", "dropbearmulti"]
_missing = [n for n in _required_native if not os.path.exists(os.path.join(vend, n))]
_missing += [f"payload/{n}" for n in _required_payload if not os.path.exists(os.path.join(payload, n))]
if _missing:
raise SystemExit(f"REFUSING to build: missing bundled files for {TAG}: {_missing}. "
f"Populate vendor/{TAG}/ and payload/ first.")
# pycryptodome loads C submodules dynamically; collect them all so the frozen
# app can AES-decrypt the FiiO OTA chunks.
from PyInstaller.utils.hooks import collect_submodules
hidden = ["usb", "usb.core", "usb.backend.libusb1"] + collect_submodules("Crypto")
a = Analysis(
[os.path.join(ROOT, "diskos_installer", "__main__.py")],
pathex=[ROOT],
binaries=[],
datas=datas,
hiddenimports=hidden,
hookspath=[],
runtime_hooks=[],
excludes=[],
noarchive=False,
)
pyz = PYZ(a.pure)
# onefile: pass binaries + datas straight into EXE with no COLLECT step.
exe = EXE(
pyz, a.scripts, a.binaries, a.datas, [],
name="diskos-installer",
debug=False, bootloader_ignore_signals=False, strip=False, upx=False,
console=True,
)
+114
View File
@@ -0,0 +1,114 @@
#!/bin/bash
# stage-release.sh - assemble the release tarball(s) into build/release/ and generate SHA256SUMS.
#
# The release ships as SOURCE (run with your own Python via ./install.sh) plus the native flash
# tools for the target platform - NOT a bundled onefile binary. Each tarball is self-contained:
# extract it, run ./install.sh once, then ./diskos-installer.
#
# Usage:
# build/stage-release.sh [TAG ...] # default TAG: the host's (e.g. linux-x86_64)
# Build the native tools for each TAG first (Linux: build/build-*-static.sh; macOS: build-macos.sh).
set -euo pipefail
cd "$(dirname "$0")/.." # installer/
ROOT=$(pwd)
REL="$ROOT/build/release"
mkdir -p "$REL"
# default to the host platform tag if none given
if [ "$#" -eq 0 ]; then
_os=$(uname -s | tr '[:upper:]' '[:lower:]'); case "$_os" in darwin) _os=macos;; esac
_arch=$(uname -m); case "$_arch" in amd64) _arch=x86_64;; aarch64|arm64) _arch=arm64;; esac
set -- "${_os}-${_arch}"
fi
# files/dirs that must NEVER go in a public tarball (secrets, FiiO-derived images, build scratch,
# internal docs). Mirrors .gitignore; kept here so staging works even outside a git checkout.
EXCLUer=(
--exclude='./.git' --exclude='./.venv' --exclude='./build/venv' --exclude='./build/work'
--exclude='./build/dist' --exclude='./build/release' --exclude='*/__pycache__/*'
--exclude='__pycache__' --exclude='*.pyc' --exclude='*.pyo' --exclude='*.bak'
--exclude='./signing' --exclude='*.pem' --exclude='*.key'
--exclude='./diskos_dev*.bin' --exclude='./diskos_public*.bin' --exclude='*_recovery.bin'
--exclude='*.squashfs' --exclude='*.sqfs' --exclude='./_retired_unlicensed'
--exclude='./flash/qual_lpddr3.sh' --exclude='./flash/scan_check.sh'
--exclude='./flash/my_write5_scan_dram.bin' --exclude='./flash/usbboot'
--exclude='./mq_ui' --exclude='./S97diskos_install' --exclude='./S99usbserial'
--exclude='./INSTALL.md' --exclude='./mkdiskos.sh' --exclude='./flash/flash_diskos.sh'
--exclude='./flash/extract_stock_rootfs.sh'
--exclude='./PUBLICATION_PLAN.md' --exclude='./BETA_CHECKLIST.md' --exclude='./RELEASE.md'
--exclude='./RELEASE_READINESS.md' --exclude='./UPDATE2_DRAFT.md' --exclude='./UPDATE_ARCHITECTURE.md'
--exclude='./INSTALL_v209_legacy.md' --exclude='./SHA256SUMS' --exclude='*.log' --exclude='*.tmp'
--exclude='.DS_Store'
)
# native tools + payload that MUST be present for a TAG (fail rather than ship an unusable tarball)
REQ_VENDOR=(usbboot mksquashfs unsquashfs my_write5_dram.bin disc_spl_lpddr3.bin)
REQ_PAYLOAD=(mq_ui S97diskos_install S99usbserial diskos-debug.sh dropbearmulti)
made=()
for TAG in "$@"; do
echo "== staging $TAG =="
miss=()
for f in "${REQ_VENDOR[@]}"; do [ -f "vendor/$TAG/$f" ] || miss+=("vendor/$TAG/$f"); done
for f in "${REQ_PAYLOAD[@]}"; do [ -f "payload/$f" ] || miss+=("payload/$f"); done
if [ "${#miss[@]}" -gt 0 ]; then
echo " SKIP $TAG - missing: ${miss[*]}" >&2
echo " (build the native tools for $TAG first)" >&2
continue
fi
# Stage into a temp dir named diskos-installer/, keeping ONLY this TAG's vendor dir, then tar it.
stage=$(mktemp -d)
dest="$stage/diskos-installer"
mkdir -p "$dest"
tar -c "${EXCLUer[@]}" --exclude='./vendor/*' -C "$ROOT" . | tar -x -C "$dest"
mkdir -p "$dest/vendor/$TAG"
cp -a "vendor/$TAG/." "$dest/vendor/$TAG/"
rm -f "$dest/vendor/$TAG/"*.bak 2>/dev/null || true
# macOS build helper that build/build-macos.sh calls - ship it so that path isn't broken
[ -f vendor/setup-macos.sh ] && cp -a vendor/setup-macos.sh "$dest/vendor/setup-macos.sh"
out="$REL/diskos-installer-$TAG.tar.gz"
tar -czf "$out" -C "$stage" diskos-installer
rm -rf "$stage"
echo " -> $out"
made+=("diskos-installer-$TAG.tar.gz")
done
[ "${#made[@]}" -gt 0 ] || { echo "nothing staged." >&2; exit 1; }
echo "== generating SHA256SUMS =="
( cd "$REL" && sha256sum "${made[@]}" > SHA256SUMS ) && cat "$REL/SHA256SUMS"
NOTES="$REL/RELEASE_NOTES.md"
[ -f "$NOTES" ] || cat > "$NOTES" <<'EOF'
# diskOS installer - release
Installer for diskOS on the FiiO Snowsky Disc. Runs from source with your own Python (GUI + CLI). It
builds a diskOS image *from your own official FiiO firmware zip* (FiiO's rootfs is never
redistributed), flashes over mask-ROM with a bad-block-aware verify-every-block writer, and keeps a
checksum-verified stock image so **restore/remove is one action**.
## What's in the tarball
Source + the native flash tools for the platform. **No bundled Python** - you run it with your own.
## Setup
```
tar -xzf diskos-installer-<platform>.tar.gz
cd diskos-installer
./install.sh # builds a local .venv, installs pyusb + pycryptodome
./diskos-installer doctor
```
Needs Python 3.8+. The GUI additionally needs Tk (`apt install python3-tk`); device detection needs
`libusb-1.0` (`apt install libusb-1.0-0`). `install.sh` checks for both and tells you what to install.
## Install / restore / remove
See the bundled `README.md`. Requires putting the device in mask-ROM (power off, hold Vol-Down, plug
USB). ~60-90 min; normally recoverable via mask-ROM, but not guaranteed.
## Honest status
Enthusiast flasher. Linux tested end-to-end on real hardware (V2.09 + V2.28). macOS build validation
in progress. Not affiliated with FiiO.
EOF
echo " -> $NOTES"
echo "Done. Attach $REL/* to the GitHub Release."
+42
View File
@@ -0,0 +1,42 @@
# Corresponding source for the shipped GPL/LGPL native binaries
The installer ships prebuilt native tools under `vendor/<os>-<arch>/`. Some of them are, or
statically link, **GPL-2.0** / **LGPL-2.1** code. To satisfy those licenses this directory carries the
**complete corresponding source** for the exact upstream versions those binaries were built from - so
the source travels **from the same place** as the binaries (GPL-2.0 §3(a) + the "same place" clause
in §3's final paragraph; LGPL-2.1 §6(a)/(d)).
Each item below is a full Debian source package (`.orig` upstream tarball + `.debian` packaging +
`.dsc`); extract with `dpkg-source -x <name>.dsc` (or unpack the `.orig` tarball directly).
| Shipped binary | Component here | Version | License | Source files |
|---|---|---|---|---|
| `mksquashfs` / `unsquashfs` | **squashfs-tools** | 4.6.1-1build1 | GPL-2.0 | `squashfs-tools_4.6.1*` |
| (statically linked into the above) | **liblzo2** (lzo2) | 2.10-2build4 | GPL-2.0-or-later | `lzo2_2.10*` |
| `usbboot` | **libusb-1.0** (statically linked) | 1.0.27-1 | LGPL-2.1 | `libusb-1.0_1.0.27*` |
| all three tools (static C runtime) | **glibc** | 2.39-0ubuntu8.8 | LGPL-2.1-or-later | `glibc_2.39*` |
| `usbboot` | its own C source | - | GPL-2.0-or-later | `../src/usbboot/usbboot.c` |
| `disc_spl_lpddr3.bin` | stage-1 SPL (u-boot-xburst) | see `../SPL_SOURCE.md` | GPL-2.0 | `../spl-src/` |
Also statically linked into `mksquashfs`/`unsquashfs`: **zlib** and **liblzma/xz** - both permissive
(zlib / 0BSD-public-domain), needing attribution only (see `../NOTICE.md`), not corresponding source.
## Rebuilding the binaries from this source
The build scripts that produced the shipped binaries are in `../build/`:
- `build/build-squashfs-static.sh` - static `mksquashfs`/`unsquashfs` (gzip+lzo+xz), with an LZO
round-trip self-test. Uses squashfs-tools + liblzo2 above.
- `build/build-usbboot-static.sh` - fully static `usbboot`, rebuilding libusb (above) with
`--disable-udev --enable-static` so no libudev/libcap is pulled in.
Those scripts fetch the same upstream source via `apt-get source`; the tarballs here pin the exact
versions used so you can rebuild - or substitute your own modified libusb and relink `usbboot`
(the LGPL-2.1 §6 relink path) - without depending on a distribution's source availability.
## The LGPL-2.1 relink path for libusb (usbboot)
`usbboot` statically links `libusb-1.0.a`. To exercise your LGPL right to run `usbboot` against a
modified libusb: extract `libusb-1.0_1.0.27*`, modify it, `./configure --disable-udev --enable-static
--disable-shared && make`, then relink with the app source and the same command
`build/build-usbboot-static.sh` uses (`gcc -O2 -std=c99 -I<libusb-inc> -static -o usbboot
../src/usbboot/usbboot.c <your libusb-1.0.a> -lpthread`).
@@ -0,0 +1,94 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Format: 3.0 (quilt)
Source: glibc
Binary: libc-bin, libc-dev-bin, libc-devtools, libc-l10n, glibc-doc, glibc-source, locales, locales-all, nscd, libc6, libc6-dev, libc6-dbg, libc6-udeb, libc6.1, libc6.1-dev, libc6.1-dbg, libc6.1-udeb, libc0.3, libc0.3-dev, libc0.3-dbg, libc0.3-udeb, libc6-i386, libc6-dev-i386, libc6-sparc, libc6-dev-sparc, libc6-sparc64, libc6-dev-sparc64, libc6-s390, libc6-dev-s390, libc6-amd64, libc6-dev-amd64, libc6-powerpc, libc6-dev-powerpc, libc6-ppc64, libc6-dev-ppc64, libc6-mips32, libc6-dev-mips32, libc6-mipsn32, libc6-dev-mipsn32, libc6-mips64, libc6-dev-mips64, libc6-x32, libc6-dev-x32
Architecture: any all
Version: 2.39-0ubuntu8.8
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Uploaders: Clint Adams <clint@debian.org>, Aurelien Jarno <aurel32@debian.org>, Samuel Thibault <sthibault@debian.org>
Homepage: https://www.gnu.org/software/libc/libc.html
Standards-Version: 4.6.2
Vcs-Browser: https://git.launchpad.net/~ubuntu-core-dev/ubuntu/+source/glibc
Vcs-Git: https://git.launchpad.net/~ubuntu-core-dev/ubuntu/+source/glibc
Testsuite: autopkgtest
Testsuite-Triggers: @builddeps@, binutils, fakeroot, gcc, linux-libc-dev
Build-Depends: gettext, dpkg (>= 1.18.7), dpkg-dev (>= 1.17.14), xz-utils, file, quilt, autoconf, gawk, debhelper-compat (= 13), rdfind, symlinks, netbase, gperf, bison, linux-libc-dev (>= 3.9) [linux-any], systemtap-sdt-dev [linux-any], libaudit-dev [linux-any], libcap-dev [linux-any] <!stage2>, libselinux1-dev [linux-any] <!stage2>, mig-for-host (>= 1.8+git20200618-7~) [hurd-any], gnumach-dev (>= 2:1.8+git20200710-2~) [hurd-any], hurd-dev (>= 1:0.9.git20201127-4~) [hurd-any] | hurd-headers-dev [hurd-any], binutils-for-host (>= 2.38), g++-multilib [amd64 i386 mips mipsel mipsn32 mipsn32el mips64 mips64el mipsr6 mipsr6el mipsn32r6 mipsn32r6el mips64r6 mips64r6el powerpc ppc64 s390x sparc sparc64 x32] <!nobiarch>, g++-x86-64-linux-gnu [amd64] <cross>, g++-arc-linux-gnu [arc] <cross>, g++-aarch64-linux-gnu [arm64] <cross>, g++-arm-linux-gnueabi [armel] <cross>, g++-arm-linux-gnueabihf [armhf] <cross>, g++-hppa-linux-gnu [hppa] <cross>, g++-i686-linux-gnu [i386] <cross>, g++-m68k-linux-gnu [m68k] <cross>, g++-mips-linux-gnu [mips] <cross>, g++-mipsel-linux-gnu [mipsel] <cross>, g++-mips64-linux-gnuabin32 [mipsn32] <cross>, g++-mips64el-linux-gnuabin32 [mipsn32el] <cross>, g++-mips64-linux-gnuabi64 [mips64] <cross>, g++-mips64el-linux-gnuabi64 [mips64el] <cross>, g++-mipsisa32r6-linux-gnu [mipsr6] <cross>, g++-mipsisa32r6el-linux-gnu [mipsr6el] <cross>, g++-mipsisa64r6-linux-gnuabin32 [mipsn32r6] <cross>, g++-mipsisa64r6el-linux-gnuabin32 [mipsn32r6el] <cross>, g++-mipsisa64r6-linux-gnuabi64 [mips64r6] <cross>, g++-mipsisa64r6el-linux-gnuabi64 [mips64r6el] <cross>, g++-nios2-linux-gnu [nios2] <cross>, g++-powerpc-linux-gnu [powerpc] <cross>, g++-powerpc64-linux-gnu [ppc64] <cross>, g++-powerpc64le-linux-gnu [ppc64el] <cross>, g++-riscv64-linux-gnu [riscv64] <cross>, g++-sparc-linux-gnu [sparc] <cross>, g++-sparc64-linux-gnu [sparc64] <cross>, g++-s390x-linux-gnu [s390x] <cross>, g++-sh3-linux-gnu [sh3] <cross>, g++-sh4-linux-gnu [sh4] <cross>, g++-x86-64-linux-gnux32 [x32] <cross>, g++-alpha-linux-gnu [alpha] <cross>, g++-ia64-linux-gnu [ia64] <cross>, python3:native, libidn2-0 (>= 2.0.5~) <!nocheck>, libc-bin (>= 2.39) <cross>, libgd-dev <!stage1 !stage2>
Build-Depends-Indep: perl, po-debconf (>= 1.0)
Package-List:
glibc-doc deb doc optional arch=all profile=!stage1
glibc-source deb devel optional arch=all profile=!stage1
libc-bin deb libs required arch=any profile=!stage1 essential=yes
libc-dev-bin deb libdevel optional arch=any profile=!stage1
libc-devtools deb devel optional arch=any profile=!stage1+!stage2
libc-l10n deb localization standard arch=all profile=!stage1
libc0.3 deb libs optional arch=hurd-i386,hurd-amd64 profile=!stage1
libc0.3-dbg deb debug optional arch=hurd-i386,hurd-amd64 profile=!stage1
libc0.3-dev deb libdevel optional arch=hurd-i386,hurd-amd64
libc0.3-udeb udeb debian-installer optional arch=hurd-i386,hurd-amd64 profile=!noudeb,!stage1
libc6 deb libs optional arch=amd64,arc,arm64,armel,armhf,hppa,i386,m68k,mips,mipsel,mipsn32,mipsn32el,mips64,mips64el,mipsr6,mipsr6el,mipsn32r6,mipsn32r6el,mips64r6,mips64r6el,nios2,powerpc,ppc64,ppc64el,riscv64,sparc,sparc64,s390x,sh3,sh4,x32 profile=!stage1
libc6-amd64 deb libs optional arch=i386,x32 profile=!stage1,!nobiarch
libc6-dbg deb debug optional arch=amd64,arc,arm64,armel,armhf,hppa,i386,m68k,mips,mipsel,mipsn32,mipsn32el,mips64,mips64el,mipsr6,mipsr6el,mipsn32r6,mipsn32r6el,mips64r6,mips64r6el,nios2,powerpc,ppc64,ppc64el,riscv64,sparc,sparc64,s390x,sh3,sh4,x32 profile=!stage1
libc6-dev deb libdevel optional arch=amd64,arc,arm64,armel,armhf,hppa,i386,m68k,mips,mipsel,mipsn32,mipsn32el,mips64,mips64el,mipsr6,mipsr6el,mipsn32r6,mipsn32r6el,mips64r6,mips64r6el,nios2,powerpc,ppc64,ppc64el,riscv64,sparc,sparc64,s390x,sh3,sh4,x32
libc6-dev-amd64 deb libdevel optional arch=i386,x32 profile=!nobiarch
libc6-dev-i386 deb libdevel optional arch=amd64,x32 profile=!nobiarch
libc6-dev-mips32 deb libdevel optional arch=mipsn32,mipsn32el,mips64,mips64el,mipsn32r6,mipsn32r6el,mips64r6,mips64r6el profile=!nobiarch
libc6-dev-mips64 deb libdevel optional arch=mips,mipsel,mipsn32,mipsn32el,mipsr6,mipsr6el,mipsn32r6,mipsn32r6el profile=!nobiarch
libc6-dev-mipsn32 deb libdevel optional arch=mips,mipsel,mips64,mips64el,mipsr6,mipsr6el,mips64r6,mips64r6el profile=!nobiarch
libc6-dev-powerpc deb libdevel optional arch=ppc64 profile=!nobiarch
libc6-dev-ppc64 deb libdevel optional arch=powerpc profile=!nobiarch
libc6-dev-s390 deb libdevel optional arch=s390x profile=!nobiarch
libc6-dev-sparc deb libdevel optional arch=sparc64 profile=!nobiarch
libc6-dev-sparc64 deb libdevel optional arch=sparc profile=!nobiarch
libc6-dev-x32 deb libdevel optional arch=amd64,i386 profile=!nobiarch
libc6-i386 deb libs optional arch=amd64,x32 profile=!stage1,!nobiarch
libc6-mips32 deb libs optional arch=mipsn32,mipsn32el,mips64,mips64el,mipsn32r6,mipsn32r6el,mips64r6,mips64r6el profile=!stage1,!nobiarch
libc6-mips64 deb libs optional arch=mips,mipsel,mipsn32,mipsn32el,mipsr6,mipsr6el,mipsn32r6,mipsn32r6el profile=!stage1,!nobiarch
libc6-mipsn32 deb libs optional arch=mips,mipsel,mips64,mips64el,mipsr6,mipsr6el,mips64r6,mips64r6el profile=!stage1,!nobiarch
libc6-powerpc deb libs optional arch=ppc64 profile=!stage1,!nobiarch
libc6-ppc64 deb libs optional arch=powerpc profile=!stage1,!nobiarch
libc6-s390 deb libs optional arch=s390x profile=!stage1,!nobiarch
libc6-sparc deb libs optional arch=sparc64 profile=!stage1,!nobiarch
libc6-sparc64 deb libs optional arch=sparc profile=!stage1,!nobiarch
libc6-udeb udeb debian-installer optional arch=amd64,arc,arm64,armel,armhf,hppa,i386,m68k,mips,mipsel,mipsn32,mipsn32el,mips64,mips64el,mipsr6,mipsr6el,mipsn32r6,mipsn32r6el,mips64r6,mips64r6el,nios2,powerpc,ppc64,ppc64el,riscv64,sparc,sparc64,s390x,sh3,sh4,x32 profile=!noudeb,!stage1
libc6-x32 deb libs optional arch=amd64,i386 profile=!stage1,!nobiarch
libc6.1 deb libs optional arch=alpha,ia64 profile=!stage1
libc6.1-dbg deb debug optional arch=alpha,ia64 profile=!stage1
libc6.1-dev deb libdevel optional arch=alpha,ia64
libc6.1-udeb udeb debian-installer optional arch=alpha,ia64 profile=!noudeb,!stage1
locales deb localization standard arch=all profile=!stage1
locales-all deb localization optional arch=any profile=!stage1
nscd deb admin optional arch=any profile=!stage1
Checksums-Sha1:
4b043eaba31efbdfc92c85d062e975141870295e 18520988 glibc_2.39.orig.tar.xz
2537168c6bdd25c3d001c9bb1d8dbf0db6f865c0 833 glibc_2.39.orig.tar.xz.asc
d22a241cb8ca1a1e842bedc01f29fdf3951ca264 483068 glibc_2.39-0ubuntu8.8.debian.tar.xz
Checksums-Sha256:
f77bd47cf8170c57365ae7bf86696c118adb3b120d3259c64c502d3dc1e2d926 18520988 glibc_2.39.orig.tar.xz
2cce427ef7933c17379f5514e4f0ccf8dffae5bf8c72f0f7e0bf8b8401f34be5 833 glibc_2.39.orig.tar.xz.asc
ff1aa3bb3eba4f302a99c9b957cacff6d79f26e9b0e663e379bf70a4f39d4283 483068 glibc_2.39-0ubuntu8.8.debian.tar.xz
Files:
be81e87f72b5ea2c0ffe2bedfeb680c6 18520988 glibc_2.39.orig.tar.xz
efe15221b9b609b2c7b96cf5f6743bf0 833 glibc_2.39.orig.tar.xz.asc
741cfbf2894fca266078acdc1a3cd65a 483068 glibc_2.39-0ubuntu8.8.debian.tar.xz
Original-Maintainer: GNU Libc Maintainers <debian-glibc@lists.debian.org>
Original-Vcs-Browser: https://salsa.debian.org/glibc-team/glibc
Original-Vcs-Git: https://salsa.debian.org/glibc-team/glibc.git
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCgAdFiEEUMSg3c8x5FLOsZtRZWnYVadEvpMFAmpieQcACgkQZWnYVadE
vpN5wQ/+MZDhJrtPO651+NCFtukjgZCTBr7CiiGYjk1QhUEBuSC2MMfSFALayIFK
Ziu5ZkasPsnn3WfmuT7ZFictCjSJ3jVWfVH/juiXMoCY8vcS+2CUn/XGfX7cfDcP
E+xFFyBsr0EmenV7pFG867sGp4wKjiw1htq8/on5r59yqAnFgWirjPY1dRSSGGGK
DBz5tC+5Ek0ncIPh6EyceW4d34g2+u48v3PlDZXIZXF9T43mHqXuSOnHZ9+uN5+3
7YonupLm9F5TgH4d8qiqhQaq3mACZMAW8we8WAZqFa2leqYkRfozdzwTwKJCfgFN
cDw14sOQ8GoWjRrO8NkAPzWs2PmXsROgfUvdXa/KGC/ux6n40u7NI9NhfrzhE2B2
PQpDjrdypViODaPTHQdxX+vQtaVOuqMr+L4zMEKSVw0eR1l6OukarC15ZoRgWZEq
M75weFfLktg4oDmgLv2zb/QmCwQZj1fBCwwRXH6surviEL4+rCzoX7+Xe5ZwQ/jp
Oj1iXrUVT+1Wsq35ZnJXHsmf1t3Vd2RuWrCYZ2kRDVLrKds5k1OsqHOW3xoNQOtq
hR6VCb92DWzNgTgsmhWpUtzBJahondQlilqg+20sJuF7mpZo5QzDS86i+wEuuhUq
46mjJV689J534yLBqZWBXdEuqK+PHQV1IYVZnAXqEA96colxbBM=
=imHV
-----END PGP SIGNATURE-----
Binary file not shown.
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEEcnNUKzmWLfeymZMUFnkrTqJTQPgFAmW6xDIACgkQFnkrTqJT
QPgAAg/9FnW6kXC3eth/BhuzaEEjOmy8BiTSrEHVLWz9veRTuBBYavxH/XUKfLrg
dAFMnASU4DtDUFI2kFWGJIDLk8E/rUau8a0f5Skh4W3VSrc7MDvQhMMt1HggRIqE
O2G7fS6uKZokZElcvEKYrTnq7iwH25K1lvXUKAeaUnVQg6upGYnCe8vuZutuZR9x
OFkewctLM8Canc6wvW0V92Oy+6eZsDq08HCJenFklSh1wz9+MUzyivkv/b6fXK6E
lKGLxpPH7vzfKao6YJBrAHT5raFxdz3yUGzevfeBE9S8UrOYHhsoBRZsaQUWkyKU
A3Gn1ioTkxj8szfgHCrweN6A4Y4MlGgMeQbplQnrjQEfUTVo9N2zkQwWRsM4VGeF
RkbWwpIQg6zMi3BFfizHqAZZWjjWb0wu6mDWmnQBaQ97dN0DAuKJ7cDNmLe6+vOE
OkXRTses8Ta3npAxKjrWNm6WjcrYAzEYLGUT6hLBmZj+WulHmRDPEyuo8H3eihuL
JzJXc7X6O3HntgCqqGrC4yNGtjRF0r3FjZ9Zrv6snEzWHVBnDw/9C5Ss9aZ+VSxO
Uqo0nESWKHtz9UBS73yA/H1k1rMnQS9yeugMoqBil+cJD5xMZETNKFbUGwR8feQ4
O6w8uH1q70ZwtTVf3l6sbijMeORfcrS0WEErxm8IREmUbqPIMRw=
=uGia
-----END PGP SIGNATURE-----
@@ -0,0 +1,49 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Format: 3.0 (quilt)
Source: libusb-1.0
Binary: libusb-1.0-0, libusb-1.0-0-dev, libusb-1.0-doc, libusb-1.0-0-udeb
Architecture: linux-any hurd-any all
Version: 2:1.0.27-1
Maintainer: Aurelien Jarno <aurel32@debian.org>
Homepage: http://www.libusb.info
Standards-Version: 4.6.2
Testsuite: autopkgtest
Testsuite-Triggers: autoconf, automake, build-essential, libudev-dev, libumockdev-dev, pkg-config, umockdev
Build-Depends: debhelper-compat (= 13), libudev-dev [linux-any], pkg-config, umockdev <!nocheck>, libumockdev-dev <!nocheck>
Build-Depends-Indep: doxygen
Package-List:
libusb-1.0-0 deb libs optional arch=linux-any,hurd-any
libusb-1.0-0-dev deb libdevel optional arch=linux-any,hurd-any
libusb-1.0-0-udeb udeb debian-installer optional arch=linux-any,hurd-any profile=!noudeb
libusb-1.0-doc deb doc optional arch=all
Checksums-Sha1:
7c169047f5970e767d937b598f60979de5f036e3 643680 libusb-1.0_1.0.27.orig.tar.bz2
ffb7e3e03c672d154bfc9e8aa840cd9c1db656a7 833 libusb-1.0_1.0.27.orig.tar.bz2.asc
9eee768d76ee4a490beeeade2e17a5cb0b334cb3 17044 libusb-1.0_1.0.27-1.debian.tar.xz
Checksums-Sha256:
ffaa41d741a8a3bee244ac8e54a72ea05bf2879663c098c82fc5757853441575 643680 libusb-1.0_1.0.27.orig.tar.bz2
1cd22bbfe4ce382ca9b091e2a6275c48f1c776253815cbb615da295ae0bfe687 833 libusb-1.0_1.0.27.orig.tar.bz2.asc
560bc02e704b8f28b04be3e6a551ccbf2b5c5cb0850864d6a5416ad05723f0b4 17044 libusb-1.0_1.0.27-1.debian.tar.xz
Files:
1fb61afe370e94f902a67e03eb39c51f 643680 libusb-1.0_1.0.27.orig.tar.bz2
be3b4265eb0ba77ea2a4bbe78539e1d7 833 libusb-1.0_1.0.27.orig.tar.bz2.asc
9ab0e4b8a46ea6c3456343bba278398a 17044 libusb-1.0_1.0.27-1.debian.tar.xz
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCgAdFiEEUryGlb40+QrX1Ay4E4jA+JnoM2sFAmW75icACgkQE4jA+Jno
M2vR2g/8CAvEt2Ea1iT/cc/HmAm6InO5RdG82FbqpQABSK9JNgN+EuuIA861GfSf
jCjrLE2B55oioAKSx6zKxadAC59dP9VdFMmfTBvfpDJrYlXyYLlQpKDUrok23nT2
C9w2EI7lnQLpqbuuefxXzpmTqoGja1pSsX8BSmQxb2oqo8W516YPswItBhY7v6WQ
yBILaPGlrdUibqxIw0Qw+jbbi4VT1XIE7l+30XtZ7NK5nvBTVK83vi1OU7+yjPop
tVoFp99LWQS3M3q6LK94UtRYpi2XQqL+0ZgoomhkZZ/NUOzDehGguiyLUBlvv3yD
yq4DQsi8EmaWQzuofqtEO4BpdMZT2A3pZ17LU3LBx4AmHSdrSiJIK/nXMWtn3r+1
qUsFzMQi0DufpyYCU+JUOvLoSg+v1ab42/yupvDzpbp0gQcO72/av+c8Y5u6XAIC
fZSmCast8kqLsFY9GACEe5def3Ua2UT9M5Hm6fMoR33+AQJhcURPVC/qzeykEoSP
K2Uq5PAO0qJa2frGD0Op3vyfpETIjWXylj725tGFLw87+Ckug5tYyGPh/rZ5Oh/k
1xRVApEeiu6ppsis5cJwo6yXSewCS0aqo71KGdurcR4/kqoRa+DjZJqzdkOh+cSF
ClCWGsD3BAL8fHB9vrkeWsuv0PvQ0EItXX0fmBQdlc/AprzMqCk=
=Uhhm
-----END PGP SIGNATURE-----
Binary file not shown.
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEEnH6pSTnGnE+8Pb+oqgY5B577YbkFAmW6xoMACgkQqgY5B577
YbmEWg/9Fp2VLICEVOIUYT5dMQt9d3nRf6hSNHepUj8sSq2F7AYDWLTMQjhU1JZg
0uuLqcBMDjRQL22L5AVoC/Gfyg8Xe2fWGFKWOFEqOeK6wz+zGVvzOI5Wq58fqgLG
z3aIuvMLU3YflGQGfKhNo4O1RRWtt18mI81vJWL6iKN2FJeDSQ/fpqrgVYjk87IX
XpkE4ukzb5xJ97iORfZxHIvE20Y00wTWloMm/dGnhh9c+Wxa3tKwXL3H4g+pQjli
SIEzYNFKXXic2U6jgAdlSw8pll4VPoALQAmrYD4Bb7uR0KYD3PL0Ln2rXWB252+T
ZGGS6kQFN/Ju6wz36RqbYfzVf3GxdlPagBYyZx/UQgj7r7HuvxhS5FaBaWr0U5e6
D7bQZDwqc7WoDEpGAkAkdCBp/qs9JWbWW8CgTKkLPcnT+oZDOJxlj3ADoDivS91c
QBDg28Wia7BWMesDgWYlvMsDNd6zSTPcQLpiJjb7wBdlYuU9ELNgVziwlz8vEyt2
4U0Ec7180nJpzn6BpabHx1V2NEMXIwOqBjC8zisjLluRi7S8Vj/Ts6DDyw9SGqN7
ncTeSEU+LK2a9nvsIaXIyZ/N+0sic7rdjWbqHcCtneQ1QdqjFtsAXW48AbG6vJvY
sYh610vVqHXGlwbJlzO4HnhoAPAKbFxGsXgZa1YTATGN+4TO2QE=
=e8dx
-----END PGP SIGNATURE-----
Binary file not shown.
@@ -0,0 +1,46 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Format: 3.0 (quilt)
Source: lzo2
Binary: liblzo2-dev, liblzo2-2, liblzo2-2-udeb
Architecture: any
Version: 2.10-2build4
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Homepage: https://www.oberhumer.com/opensource/lzo/
Standards-Version: 4.5.0
Vcs-Browser: https://salsa.debian.org/debian/lzo2
Vcs-Git: https://salsa.debian.org/debian/lzo2.git
Build-Depends: debhelper-compat (= 12), pkg-config
Package-List:
liblzo2-2 deb libs optional arch=any
liblzo2-2-udeb udeb debian-installer optional arch=any
liblzo2-dev deb libdevel optional arch=any
Checksums-Sha1:
4924676a9bae5db58ef129dc1cebce3baa3c4b5d 600622 lzo2_2.10.orig.tar.gz
9d219fb0dfdf031f2cb0fda60d26a23cb2163530 7120 lzo2_2.10-2build4.debian.tar.xz
Checksums-Sha256:
c0f892943208266f9b6543b3ae308fab6284c5c90e627931446fb49b4221a072 600622 lzo2_2.10.orig.tar.gz
3115ad74a2495f0ca5f7f0e8761b6c3c81e14d19abd9d7b47c7fc020091fcb47 7120 lzo2_2.10-2build4.debian.tar.xz
Files:
39d3f3f9c55c87b1e5d6888e1420f4b5 600622 lzo2_2.10.orig.tar.gz
26aeb09697919dcf8ba93508f6c9c4c2 7120 lzo2_2.10-2build4.debian.tar.xz
Original-Maintainer: Stephen Kitt <skitt@debian.org>
-----BEGIN PGP SIGNATURE-----
iQJHBAEBCgAxFiEET7WIqEwt3nmnTHeHb6RY3R2wP3EFAmYUF6MTHGp1bGlhbmtA
dWJ1bnR1LmNvbQAKCRBvpFjdHbA/cYOhD/0bsopVacb07CzRBODJRwgSUJnrtov2
031RHKNrCYK+d1SoVkTtIr0XEwzgH1t7caVcfD2GaYl0sNwikVEyvNF1EEh1aG4n
Wb+h3YNJBqS2hBgKdQnTcnY9booE9B0Xw+o6He9AxM9go9xcng4YUC59w8P0JFn7
9i5rnV55eJjrWpCdV7UXwBh/1nqnsyVyXc0HuyjHg0Nroad5AyvSXCtNpWwZW99Z
VL8GkWqs2Hkb4fu8nOPBIBR+nwuCp+tBEqH3Wl3Ph6sHX7WVDqVdcuPvF5JHyd0y
PaStokpxAlwYp6kILuxJ4UUZAmAv8c+KE4uhvVxV5ymv9CzCffBc7/4sFyiH5+7S
mKCVDfG2aCTRENJTZBp5KOZMHDpuPVfVKw6Wpn7sZVQuooo6CBhiOneWIjeB/X0x
ZO/Vq5qtNSBRkQjCPSZGLR2wdqON/OjK65oA/UXlBnP+NH/20ivknbpsrwowgYgW
dZmXKjou4M9CqCc7zTf4N/l7NKv8TixQcSOVOGpTnc3/ORAoIZZz9M7V2Wg0ezlF
PQ5O1+CC8k8EL3QRY8ZF+S/p0oJWvZ55Qrm2tevqj/u79rFAgQi2xyWJyjMU8noU
JVyXdifyRrxWv5SR7ltOdKloK7iqIjYHcJiIauIeIASeWQrw2V9MChUxxEoAhBhn
amHCUqiG5/H2wg==
=dcLM
-----END PGP SIGNATURE-----
Binary file not shown.
@@ -0,0 +1,42 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Format: 3.0 (quilt)
Source: squashfs-tools
Binary: squashfs-tools
Architecture: linux-any kfreebsd-any
Version: 1:4.6.1-1build1
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Homepage: https://github.com/plougher/squashfs-tools
Standards-Version: 4.6.2
Build-Depends: debhelper-compat (= 13), libattr1-dev, liblzma-dev, liblzo2-dev, liblz4-dev, zlib1g-dev, libzstd-dev, help2man
Package-List:
squashfs-tools deb kernel optional arch=linux-any,kfreebsd-any
Checksums-Sha1:
daad956aa77ccddf5df20db6a2eebcc4a226cab5 286848 squashfs-tools_4.6.1.orig.tar.gz
fd8e9ac4845148e6b48c6f38dc27d54ac3a02e25 10376 squashfs-tools_4.6.1-1build1.debian.tar.xz
Checksums-Sha256:
94201754b36121a9f022a190c75f718441df15402df32c2b520ca331a107511c 286848 squashfs-tools_4.6.1.orig.tar.gz
e0774865d7d9988633534276139f199ab4db59109f9ee1a5355eb9c1e5b300e1 10376 squashfs-tools_4.6.1-1build1.debian.tar.xz
Files:
db23a40fa0dc54b4d6d225fb20ee6555 286848 squashfs-tools_4.6.1.orig.tar.gz
8b71b3fa5c85a74aa967f0ffc4f795dc 10376 squashfs-tools_4.6.1-1build1.debian.tar.xz
Original-Maintainer: Laszlo Boszormenyi (GCS) <gcs@debian.org>
-----BEGIN PGP SIGNATURE-----
iQJHBAEBCgAxFiEET7WIqEwt3nmnTHeHb6RY3R2wP3EFAmYUGWYTHGp1bGlhbmtA
dWJ1bnR1LmNvbQAKCRBvpFjdHbA/cZkHEACNuqQFoqN+q3SjLFRyHvoQpgnuCgMF
zdtmvovEK/4pnEOdY1sGmjL7OlPi77/0TeQmLp4NKUOOHleM7L1N1Ho6Kjy81RU2
mkgaZ4D0IK0ttEuRPFQZTSs6lIGgmGvZmnxvwM/QYODrj09F1PFeNeW7vO9rmTWI
FitEgsb8ZQotLGiyM1YZWo1P4bIcSXzjy4gZEKGJ22DPXS3K4U0xSdijKMHffaK+
W3a1bIkqdy58VInDKwFaeN0/qSmISJomTLFsZMrlMDXpIZpQudr/dzJEh9yMSjYw
SoAgFsCf4o8jI4MXz1JvxzUFo8QZpigdahg9JW70M0evnHHU5cJl68Iz/4tUpQZH
ER2Lmd9lRttanZp/ltj+jEDQzPXYp0fS+YHdaQNJdhNh6b1fiJWwxiJb2IDKeGGV
7F08rI48N26jdxb9RllJM8qEa7jGN7yEWYvia0TKWMRG6WAm432tC1smjGcpDUmL
rVqErVoyiacraWU382jrS0HYLX27p1GefQ+Fs8tjrGQ6Cban3bsgkEmYeLd/jD8f
8BCXVvTqHipfjtL8ielSNz2ULpwTdd+/1LqsMbb7XOWJgGIv0+NWNvfrxYLCQEdM
oUsuem+fl01KceXXCa/9xHjpnVoU7QBfZvUBfk39cjkHG/MvCcuT1Y6Z0NJB/dUv
0/vsx4OAD+5qVg==
=NebR
-----END PGP SIGNATURE-----
+21
View File
@@ -0,0 +1,21 @@
#!/bin/sh
# diskOS installer launcher. Runs the installer from source using the local .venv (created by
# ./install.sh); falls back to the system python3 if no venv is present. Pass any subcommand
# straight through, e.g. ./diskos-installer doctor or ./diskos-installer gui
set -eu
HERE=$(CDPATH= cd "$(dirname "$0")" && pwd)
if [ -x "$HERE/.venv/bin/python" ]; then PY="$HERE/.venv/bin/python"
elif [ -x "$HERE/.venv/Scripts/python.exe" ]; then PY="$HERE/.venv/Scripts/python.exe"
elif command -v python3 >/dev/null 2>&1; then PY=$(command -v python3)
elif command -v python >/dev/null 2>&1; then PY=$(command -v python)
else
echo "diskos-installer: no Python 3 found. Run ./install.sh first." >&2
exit 1
fi
# Make the diskos_installer package importable regardless of the caller's working directory,
# without changing it (so relative --firmware paths still resolve against where the user is).
PYTHONPATH="$HERE${PYTHONPATH:+:$PYTHONPATH}"
export PYTHONPATH
exec "$PY" -m diskos_installer "$@"
+12
View File
@@ -0,0 +1,12 @@
"""diskOS installer - cross-platform (Linux/macOS) installer for the FiiO Snowsky Disc.
The whole tool is Python; the two bricking-sensitive operations (the Ingenic
mask-ROM USB flash and squashfs packing) delegate to PROVEN native binaries that
ship alongside this package (see ``bundle.py``) rather than being reimplemented.
Run from source with your own Python: ``./install.sh`` creates a local virtualenv and
installs the two pip dependencies (pyusb, pycryptodome), then ``./diskos-installer``
runs it. The GUI additionally needs the system's Tk; the flash step needs libusb-1.0.
"""
__version__ = "1.0.0"
+220
View File
@@ -0,0 +1,220 @@
"""diskOS installer CLI.
Commands:
doctor Report host, bundled tools, device presence, and saved state.
install Build a diskOS image from YOUR stock firmware and flash it.
restore-stock Deactivate diskOS: reflash your saved stock-rootfs image (leaves /usr/data files).
remove Delete everything this tool created (its full uninstall footprint).
Design: the whole tool is Python; the bricking-sensitive steps delegate to bundled
proven native binaries. Nothing is installed system-wide on Linux/macOS.
"""
import argparse
import fcntl
import os
import sys
import tempfile
from diskos_installer import (__version__, bundle, errors, flasher, imagebuild,
platform_probe, service, state, ui)
from diskos_installer.reporter import CLIReporter
# --- single-run lock so two installers can't touch the ONE physical device at once. It must be
# SHARED across all users on the host (a GUI as your user and a CLI under sudo must not both flash),
# so it lives at a FIXED /tmp path - NOT per-user. Advisory flock (auto-released on death -> no
# stale-lock hazard). Opened READ-ONLY so any user can take the flock on a 0644 file, and O_NOFOLLOW
# so a planted symlink can't redirect the open (we bail instead of following it). ---
class _Lock:
def __init__(self):
# A FIXED absolute path, not tempfile.gettempdir(): $TMPDIR differs between a normal run and a
# sudo run (and per-user on macOS), which would hand them SEPARATE locks and defeat the whole
# point. /tmp is world-accessible on every supported host (Linux/macOS); Windows is unsupported.
self.path = "/tmp/diskos-installer.lock"
self.fd = None
def __enter__(self):
import stat as _stat
flags = os.O_CREAT | os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0) | getattr(os, "O_CLOEXEC", 0)
try:
self.fd = os.open(self.path, flags, 0o644)
except OSError as e:
raise SystemExit(ui.red(
f"could not open the run-lock at {self.path} ({e}). If it exists as a symlink, "
"remove it and retry."))
# A planted symlink is refused by O_NOFOLLOW above; also refuse a non-regular file.
if not _stat.S_ISREG(os.fstat(self.fd).st_mode):
os.close(self.fd); self.fd = None
raise SystemExit(ui.red(f"run-lock {self.path} is not a regular file - refusing."))
try:
fcntl.flock(self.fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
except OSError:
os.close(self.fd)
self.fd = None
raise SystemExit(ui.red(
"another diskOS installer is already running. Close it and retry "
"(only one may touch the device at a time)."))
return self
def __exit__(self, *exc):
try:
if self.fd is not None:
fcntl.flock(self.fd, fcntl.LOCK_UN)
os.close(self.fd)
except OSError:
pass
return False
def _set_phase(st, phase):
st["phase"] = phase
state.save(st)
def cmd_doctor(args):
ui.step("diskOS installer - doctor")
o, a = platform_probe.host()
ui.info(f"version : {__version__}")
ui.info(f"host : {o}-{a} ({'supported' if platform_probe.is_supported() else 'UNSUPPORTED'})")
ui.info(f"state dir : {state.state_dir()}")
ui.info("bundled tools:")
all_ok = True
for name in ("usbboot", "mksquashfs", "unsquashfs", "my_write5_dram.bin", "disc_spl_lpddr3.bin"):
p = bundle.native(name, required=False)
(ui.ok if p else ui.err)(f" {name}: {p or 'MISSING'}")
all_ok = all_ok and bool(p)
for name in ("mq_ui", "S97diskos_install", "S99usbserial", "diskos-debug.sh", "dropbearmulti"):
p = bundle.data(name, required=False)
(ui.ok if p else ui.err)(f" {name}: {p or 'MISSING'}")
all_ok = all_ok and bool(p) # payload files are required to build a flashable image
n = platform_probe.maskrom_count()
if n < 0:
ui.warn("device: cannot enumerate USB (pyusb/lsusb unavailable)")
elif n == 0:
ui.info("device: none in mask-ROM mode (normal unless you're about to flash)")
else:
(ui.ok if n == 1 else ui.warn)(f"device: {n} in mask-ROM mode")
st = state.load()
if st.get("installed"):
ui.info(f"diskOS installed via this tool: yes (variant={st.get('variant')}, at {st.get('installed_at')})")
else:
ui.info("diskOS installed via this tool: no record")
ui.info(f"saved bone-stock image (for restore): {'yes' if state.have_stock_image() else 'no'}")
return 0 if all_ok else 1
def _cli_confirm(yes):
"""Build a service `confirm` callback for the CLI (prints the summary, then
y/N - or auto-yes with --yes)."""
def confirm(summary):
ui.step("Ready - please confirm")
for k in ("action", "variant", "image", "duration", "consequence"):
if summary.get(k):
ui.info(f" {k}: {summary[k]}")
if yes:
return True
return ui.confirm("Proceed?", default=False)
return confirm
def cmd_install(args):
if not platform_probe.is_supported():
ui.err(f"[E101] unsupported host {platform_probe.host_tag()} - Linux/macOS only for now")
return 2
if not args.firmware and not args.stock:
ui.err("[E140] need --firmware <FiiO official update .zip> (or --stock <rootfs.squashfs>).")
return 2
params = {"firmware": args.firmware, "stock": args.stock,
"ui_binary": args.ui, "variant": args.variant}
r = service.do_install(params, CLIReporter(), _cli_confirm(args.yes))
if r.get("ok"):
ui.info("The UI is embedded in the flashed image - just reboot the device and it installs")
ui.info("diskOS automatically on first boot (no microSD step needed).")
ui.info("To deactivate diskOS later (reflash your saved stock rootfs): diskos-installer restore-stock")
return 0
return 3 if r.get("aborted") else 1
def cmd_restore_stock(args):
r = service.do_restore({"firmware": args.firmware}, CLIReporter(), _cli_confirm(args.yes))
return 0 if r.get("ok") else (3 if r.get("aborted") else 1)
def cmd_remove(args):
def confirm(summary):
ui.warn(summary.get("consequence", ""))
return args.yes or ui.confirm("Delete the installer's files anyway?", default=False)
r = service.do_remove({"force": args.force}, CLIReporter(), confirm)
if r.get("ok"):
if getattr(sys, "frozen", False):
ui.info(f"To finish: delete this executable ({sys.executable}).")
else:
ui.info(f"To finish: delete the installer folder ({bundle.resource_root()}).")
ui.info("Nothing was installed system-wide, so there is nothing else to clean up.")
return 0
if r.get("errors"):
return 1 # partial-removal errors already reported by the service
ui.info("aborted; nothing removed.")
return 3
def build_parser():
p = argparse.ArgumentParser(prog="diskos-installer",
description="Standalone diskOS installer for the FiiO Snowsky Disc.")
p.add_argument("--version", action="version", version=f"diskos-installer {__version__}")
# no subcommand -> GUI (running ./diskos-installer with no arguments); subcommands = CLI
sub = p.add_subparsers(dest="cmd", required=False)
sub.add_parser("gui", help="launch the graphical installer (also the default with no arguments)")
d = sub.add_parser("doctor", help="report host, bundled tools, device, and state")
d.set_defaults(func=cmd_doctor)
i = sub.add_parser("install", help="build from YOUR stock firmware and flash diskOS")
i.add_argument("--firmware", help="FiiO official update .zip (your stock firmware)")
i.add_argument("--stock", help="pre-extracted stock rootfs.squashfs (instead of --firmware)")
i.add_argument("--ui", help="diskOS UI binary (default: bundled mq_ui)")
i.add_argument("--variant", choices=["public", "dev"], default="public",
help="public (no always-on shell; Debug Mode enables SSH on demand) or dev (adds an ALWAYS-ON PASSWORDLESS ROOT SHELL over "
"USB - anyone with physical access gets root every boot; dev devices only)")
i.add_argument("-y", "--yes", action="store_true", help="don't prompt before flashing")
i.set_defaults(func=cmd_install)
r = sub.add_parser("restore-stock", help="deactivate diskOS (reflash your saved stock rootfs)")
r.add_argument("--firmware", help="FiiO update .zip (only needed if no stock image is saved)")
r.add_argument("-y", "--yes", action="store_true", help="don't prompt before flashing")
r.set_defaults(func=cmd_restore_stock)
rm = sub.add_parser("remove", help="delete the installer and everything it created")
rm.add_argument("-y", "--yes", action="store_true", help="don't prompt")
rm.add_argument("--force", action="store_true", help="remove even if diskOS is still on the device")
rm.set_defaults(func=cmd_remove)
return p
def main(argv=None):
args = build_parser().parse_args(argv)
# no subcommand, or 'gui' -> launch the graphical installer (under the lock)
if getattr(args, "cmd", None) in (None, "gui"):
from diskos_installer import gui
with _Lock():
return gui.main()
try:
if args.cmd == "doctor": # doctor is read-only; no lock needed
return args.func(args)
with _Lock():
return args.func(args)
except errors.DiskOSError as e: # any coded installer error (Build/Flash/Preflight)
ui.err(str(e))
return 1
except KeyboardInterrupt:
ui.err("interrupted.")
return 130
if __name__ == "__main__":
sys.exit(main())
+85
View File
@@ -0,0 +1,85 @@
"""Locate the bundled native binaries and data files.
Layout (in the source tree AND inside the PyInstaller bundle):
<root>/vendor/<os>-<arch>/ usbboot, mksquashfs, unsquashfs,
my_write5_dram.bin, disc_spl_lpddr3.bin,
lib/ (bundled .so/.dylib for usbboot)
<root>/payload/ mq_ui, S97diskos_install, S99usbserial,
diskos_manifest templates, etc.
When frozen by PyInstaller, data is unpacked under sys._MEIPASS; in the source
tree it sits next to this package. `resource_root()` resolves both."""
import os
import stat
import sys
from . import platform_probe
def resource_root():
"""Directory that contains vendor/ and payload/.
- Frozen (PyInstaller): sys._MEIPASS.
- Source tree: the installer/ dir (parent of this package)."""
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
return sys._MEIPASS
# this file is installer/diskos_installer/bundle.py -> installer/
return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
def vendor_dir():
return os.path.join(resource_root(), "vendor", platform_probe.host_tag())
def payload_dir():
return os.path.join(resource_root(), "payload")
def _ensure_exec(path):
try:
st = os.stat(path)
os.chmod(path, st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
except OSError:
pass
return path
def native(name, required=True):
"""Absolute path to a bundled native binary for this host, made executable.
Raises FileNotFoundError if required and missing."""
p = os.path.join(vendor_dir(), name)
if os.path.exists(p):
return _ensure_exec(p)
if required:
from .errors import PreflightError
raise PreflightError(
f"bundled tool '{name}' not found for {platform_probe.host_tag()}",
code="E102",
action="this build may not include binaries for your platform - "
"re-download the correct build")
return None
def data(name, required=True):
"""Absolute path to a bundled data/payload file."""
p = os.path.join(payload_dir(), name)
if os.path.exists(p):
return p
if required:
from .errors import PreflightError
raise PreflightError(f"bundled payload '{name}' not found", code="E102",
action="the install is incomplete - re-download the installer")
return None
def native_env():
"""Environment for running a bundled native binary, with its private lib dir
on the loader path (so a bundled libusb is found without touching the system)."""
env = dict(os.environ)
libdir = os.path.join(vendor_dir(), "lib")
if os.path.isdir(libdir):
o, _ = platform_probe.host()
var = "DYLD_LIBRARY_PATH" if o == "macos" else "LD_LIBRARY_PATH"
env[var] = libdir + (os.pathsep + env[var] if env.get(var) else "")
return env
+63
View File
@@ -0,0 +1,63 @@
"""Stable, user-quotable error codes for the diskOS installer.
Every user-facing failure carries a short code a beta tester can quote from a
screenshot so we can triage it instantly. Namespaces:
E1xx environment / preflight (nothing written to the device yet)
E2xx firmware extract & image build
E3xx flash orchestration (host side)
F1xx device writer result (mirrors the on-device dbg[16] codes)
An exception's str() renders as: "[E301] <what happened> - <what to do>"
so existing `rep.error(str(e))` call sites show the code with no other change.
"""
class DiskOSError(Exception):
"""Base installer error carrying a stable `code` and an optional `action`
(a short, plain-language "what to do next")."""
code = "E000"
def __init__(self, message, code=None, action=None):
self.message = message
if code:
self.code = code
self.action = action
super().__init__(self.render())
def render(self):
s = f"[{self.code}] {self.message}"
if self.action:
s += f" - {self.action}"
return s
class PreflightError(DiskOSError):
"""E1xx - environment/preflight; the device has NOT been touched."""
code = "E100"
class BuildError(DiskOSError):
"""E2xx - firmware extraction / diskOS image build."""
code = "E200"
class FlashError(DiskOSError):
"""E3xx - flash orchestration (host side). F0xx = device-writer verdicts."""
code = "E300"
# Device-writer result codes (from my_write5.c dbg[16]) → stable F-codes for the user.
DEVICE_RESULT_CODES = {
0x600DF10C: ("F001", "SUCCESS"),
0xDEAD0001: ("F101", "ABORT init/ECC"),
0xDEAD0002: ("F102", "ABORT out-of-space"),
0xDEAD0003: ("F103", "ABORT persistent block-write fail"),
0xDEAD0004: ("F104", "ABORT too many bad blocks"),
0xDEAD0005: ("F105", "ABORT ECC re-enable failed"),
0xDEAD0006: ("F106", "ABORT bad-block marker unreadable"),
}
RECOVERABLE = ("The device is normally recoverable via mask-ROM (not guaranteed for every unit "
"or failure): power the device OFF, hold Volume-Down, plug in USB to return to "
"mask-ROM, and re-flash your saved stock image or diskOS.")
+273
View File
@@ -0,0 +1,273 @@
"""Mask-ROM USB flashing - Python wrapper around the PROVEN native binaries
(usbboot + the my_write5 DRAM NAND writer + the X2000 SPL). We do NOT reimplement
the flashing protocol; we orchestrate it, watch it, and interpret the result.
Faithful port of flash_diskos.sh, with the python helper snippets (poison blob,
debug-struct parse) folded in natively, plus honest progress and fail-closed
result interpretation.
"""
import os
import shutil
import signal
import struct
import subprocess
import tempfile
from . import bundle, platform_probe
from .reporter import CLIReporter
from .errors import FlashError, DEVICE_RESULT_CODES, RECOVERABLE
IMG_SIZE = 76021760
SQUASH_MAGIC = b"hsqs"
RESULT_NAMES = {code: name for code, (_fcode, name) in DEVICE_RESULT_CODES.items()}
FLASH_EXPECT_SECS = 75 * 60 # ~60-90 min; expected writer duration
# Hard ceiling for the whole usbboot invocation: the writer's own --wait is 5400s (90 min);
# give it that plus margin for the image download + result readback, then treat a still-running
# usbboot as a hung/reset device and terminate it (E303) rather than blocking forever.
FLASH_HARD_TIMEOUT_SECS = 5400 + 20 * 60 # 90 min writer + 20 min margin
def _probe_helpers():
"""Confirm every bundled native tool can actually execute (and load its libs)
BEFORE the destructive gate. Catches a noexec temp mount / missing dylibs while
the device is still untouched. Non-zero exit is fine; an OSError is not."""
probes = [(bundle.native("usbboot"), ["--help"]),
(bundle.native("mksquashfs"), ["-version"]),
(bundle.native("unsquashfs"), ["-version"])]
for path, args in probes:
try:
subprocess.run([path] + args, env=bundle.native_env(),
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
timeout=15)
except OSError as e:
raise FlashError(
f"bundled helper '{os.path.basename(path)}' cannot execute ({e})",
code="E103",
action="the tool's directory may be on a noexec mount, or a required library is "
"missing; move the installer to an exec-capable filesystem and retry")
except subprocess.TimeoutExpired:
pass # it started (that's all we needed to prove)
def preflight(image_path, rep=None):
"""Validate the image and that exactly one device is in mask-ROM. Fail closed."""
rep = rep or CLIReporter()
if not os.path.exists(image_path):
raise FlashError(f"image not found: {image_path}", code="E120")
sz = os.path.getsize(image_path)
if sz != IMG_SIZE:
raise FlashError(f"wrong image size {sz} (must be {IMG_SIZE})", code="E121",
action="use a diskOS image built by this installer")
with open(image_path, "rb") as f:
if f.read(4) != SQUASH_MAGIC:
raise FlashError("image is not a squashfs (bad magic) - not a diskOS/stock image", code="E122")
_probe_helpers() # every bundled tool must actually execute (catches noexec /tmp, missing libs)
n = platform_probe.maskrom_count()
if n == 0:
raise FlashError(
"no device in mask-ROM mode", code="E110",
action="power the device OFF, hold Volume-Down, plug in USB (screen stays "
"black), then retry")
if n > 1:
raise FlashError(f"{n} devices in mask-ROM mode - need exactly 1", code="E111",
action="unplug the other Ingenic devices")
if n < 0:
# FAIL CLOSED: we could not prove exactly one device (no libusb backend or a
# permission error). Never cross the destructive gate on an unproven count.
raise FlashError(
"cannot confirm exactly one device (USB enumeration failed - missing libusb "
"backend or insufficient USB permissions)", code="E112",
action="refusing to flash on an unproven device count; fix USB access and retry")
def _parse_debug(dbg_path):
"""Parse the 1KB little-endian debug readback (256 x uint32). Returns a dict.
Mirrors the field offsets in flash_diskos.sh."""
with open(dbg_path, "rb") as f:
raw = f.read(1024)
if len(raw) < 1024:
raise FlashError(f"short debug readback ({len(raw)} bytes) - flash result UNKNOWN", code="E302",
action=RECOVERABLE)
w = struct.unpack("<256I", raw)
nbad = w[20]
return {
"magic": w[0],
"done": w[9],
"skipped": w[10],
"result": w[16],
"retried": w[17],
"worst_retries": w[18],
"bad_found": nbad,
"bad_list": [w[40 + i] for i in range(min(nbad, 64))],
}
def flash(image_path, log_path=None, rep=None):
"""Flash `image_path` to the device via mask-ROM. Returns the parsed debug dict
on SUCCESS; raises FlashError otherwise (fail-closed)."""
rep = rep or CLIReporter()
preflight(image_path, rep)
image_path = os.path.abspath(image_path)
usbboot = bundle.native("usbboot")
writer = bundle.native("my_write5_dram.bin")
spl = bundle.native("disc_spl_lpddr3.bin")
tmp = tempfile.mkdtemp(prefix="diskos-flash-")
poison = os.path.join(tmp, "poison.bin")
dbg = os.path.join(tmp, "dbg.bin")
with open(poison, "wb") as f:
f.write(b"\xee" * 128)
cmd = [
usbboot, "-v", "--cpu", "x2000", "--stage1", spl, "--wait", "2",
"--addr", "0xa0c00000", "--download", writer,
"--addr", "0xa1000000", "--download", image_path,
"--addr", "0xa0a00000", "--download", poison,
"--start1", "0xa0c00030", "--wait", "5400",
"--addr", "0xa0a00000", "--length", "0x400", "--upload", dbg,
]
rep.phase("Flashing diskOS (mask-ROM) - ~60-90 minutes", destructive=True)
rep.warning("Do NOT disconnect the device or let the host sleep during the flash.")
logf = open(log_path, "w") if log_path else open(os.path.join(tmp, "flash.log"), "w")
rep.indeterminate(True, note="flashing (scan → erase → program → verify → retry)",
expect_secs=FLASH_EXPECT_SECS)
try:
try:
with _sleep_inhibited(rep):
# own session so a GUI/parent crash can't SIGPIPE the flasher; output goes
# to a file (never a pipe) so a closed reader can't deadlock or kill it.
proc = subprocess.Popen(cmd, stdout=logf, stderr=subprocess.STDOUT,
env=bundle.native_env(), start_new_session=True)
def _kill_flasher():
# The flasher runs in its OWN session (start_new_session) so a parent SIGPIPE
# can't kill it mid-write - but that also means it SURVIVES us. Kill the whole
# process group so NAND writes actually stop, then reap without blocking.
try:
os.killpg(os.getpgid(proc.pid), signal.SIGKILL)
except OSError:
proc.kill()
try:
proc.wait(timeout=30) # reap; don't block if stuck in D-state
except subprocess.TimeoutExpired:
pass
try:
# A3: bound the wait. If the device resets/re-enumerates mid-flash,
# usbboot can block on a dead handle forever - never hang the app.
rc = proc.wait(timeout=FLASH_HARD_TIMEOUT_SECS)
except subprocess.TimeoutExpired:
_kill_flasher()
raise FlashError(
f"flash timed out - the device stopped responding after "
f"{FLASH_HARD_TIMEOUT_SECS // 60} min (it most likely reset "
"mid-flash)", code="E303", action=RECOVERABLE)
except BaseException:
# Ctrl-C, SIGTERM, a GUI/parent crash, or any error during the wait: WITHOUT
# this the flasher keeps writing NAND after we return, and a tester who believes
# flashing stopped may unplug mid-write and brick the device. Kill it, then
# propagate the original interruption/error.
_kill_flasher()
raise
finally:
rep.indeterminate(False)
logf.close()
rep.log(f"usbboot exit={rc}")
if not os.path.exists(dbg):
raise FlashError(
"no debug readback produced - flash result UNKNOWN; assume FAILED",
code="E301", action=RECOVERABLE)
d = _parse_debug(dbg)
ok = (d["magic"] == 0x4004E005 and d["done"] == 0x55555555
and d["result"] == 0x600DF10C)
rep.log(f"scan: bad-blocks-found={d['bad_found']} list={d['bad_list']}")
# B4: dbg[17]/[18] mean retried/worst only on SUCCESS; on the out-of-space /
# block-write-fail aborts they hold the last phys/logical block; on the other
# aborts they are 0 and must NOT be shown as "last block" (would be misleading).
if ok:
rep.log(f"write: skipped={d['skipped']} retried={d['retried']} "
f"worst={d['worst_retries']}")
elif d["result"] in (0xDEAD0002, 0xDEAD0003):
rep.log(f"write: skipped={d['skipped']} last-phys-block={d['retried']} "
f"last-logical-block={d['worst_retries']}")
else:
rep.log(f"write: skipped={d['skipped']}")
fcode, name = DEVICE_RESULT_CODES.get(d["result"], ("F000", "UNKNOWN"))
rep.log(f"result: 0x{d['result']:08X} [{fcode}] {name}")
if not ok:
raise FlashError(
f"flash FAILED (device result [{fcode}] {name}, "
f"magic=0x{d['magic']:08X} done=0x{d['done']:08X})",
code="E310", action=RECOVERABLE)
rep.ok("flash verified OK")
return d
finally:
# B3: never leak the per-flash tempdir (poison/dbg/flash.log), but keep the log
# debuggable: if no external log_path was given, preserve the internal log to a
# single stable file (overwritten each flash - bounded, not a growing leak).
internal_log = os.path.join(tmp, "flash.log")
if not log_path and os.path.exists(internal_log):
try:
# Unique, 0600, no symlink-follow: write THROUGH the mkstemp fd (never reopen the path,
# which could follow a swapped-in symlink and truncate an arbitrary target). Path reported.
fd, kept = tempfile.mkstemp(prefix="diskos-flash-", suffix=".log")
with os.fdopen(fd, "wb") as out, open(internal_log, "rb") as src:
shutil.copyfileobj(src, out)
rep.log(f"flash log saved to {kept}")
except OSError:
pass
shutil.rmtree(tmp, ignore_errors=True)
class _sleep_inhibited:
"""Best-effort host sleep inhibitor for the duration of the flash. No-op if the
platform tool isn't available; never blocks or fails the flash. If it CAN'T
inhibit sleep, it warns (B5) - a suspend mid-flash would abort it."""
def __init__(self, rep=None):
self.rep = rep
def __enter__(self):
self.proc = None
o, _ = platform_probe.host()
try:
if o == "macos":
self.proc = subprocess.Popen(["caffeinate", "-dimsu"])
elif o == "linux":
import shutil
if shutil.which("systemd-inhibit"):
# keep a long-lived inhibitor process alive; we kill it on exit
self.proc = subprocess.Popen(
["systemd-inhibit", "--what=sleep:idle",
"--why=diskOS flash in progress", "sleep", "infinity"])
except Exception:
self.proc = None
if self.proc is None and self.rep is not None:
self.rep.warning(
"could not auto-inhibit system sleep on this host - make sure your "
"computer will NOT sleep/suspend for the next ~90 minutes (a suspend "
"mid-flash aborts it; the device stays recoverable).")
return self
def __exit__(self, *exc):
if self.proc:
try:
self.proc.terminate()
self.proc.wait(timeout=5) # reap so no zombie / stray 'sleep infinity' lingers
except Exception:
try:
self.proc.kill()
except Exception:
pass
return False
+570
View File
@@ -0,0 +1,570 @@
"""Tkinter/ttk graphical installer.
Architecture:
* All Tk work on the main thread; a single worker thread runs the engine.
* The worker drives a QueueReporter; the GUI drains the queue via root.after.
* A blocking confirm() gate: the worker asks, the main thread shows a modal
acknowledgement dialog, the worker resumes on the user's decision.
* Explicit operation states; no Cancel once the destructive flash starts;
window-close is intercepted while flashing.
"""
import os
import queue
import sys
import threading
import time
from diskos_installer import __version__, bundle, platform_probe, service, state
from diskos_installer.reporter import QueueReporter
ACCENT = "#FF375F" # diskOS accent
BG = "#1c1c1e"
FG = "#f2f2f7"
SUBFG = "#9a9aa0"
PANEL = "#2c2c2e"
WARN = "#ffcc00"
OKC = "#34c759"
ERRC = "#ff453a"
# operation states
IDLE, RUNNING, CONFIRM, SUCCESS, FAILED = "idle", "running", "confirm", "success", "failed"
class App:
def __init__(self, root):
self.root = root
self.q = queue.Queue()
self.reporter = QueueReporter(self.q)
self.worker = None
self.state = IDLE
self.flashing = False # True only during the destructive phase
self._confirm_event = threading.Event()
self._confirm_result = False
self.start_time = None
root.title("diskOS Installer")
root.configure(bg=BG)
root.minsize(560, 640)
root.protocol("WM_DELETE_WINDOW", self._on_close)
self._build_style()
self._build_widgets()
self._refresh_state_labels()
self.root.after(80, self._drain)
self.root.after(1000, self._tick_elapsed)
self.root.after(4000, self._tick_device)
# ---- styling -----------------------------------------------------------
def _build_style(self):
import tkinter.font as tkfont
from tkinter import ttk
self.ttk = ttk
st = ttk.Style()
try:
st.theme_use("clam") # consistent across Linux/macOS
except Exception:
pass
# Derive from the platform's NAMED fonts (always present) rather than
# hard-coding families that may be absent (Helvetica/Menlo on Linux).
def _font(base, size, weight="normal"):
f = tkfont.nametofont(base).copy()
f.configure(size=size, weight=weight)
return f
self.f_title = _font("TkDefaultFont", 20, "bold")
self.f_h = _font("TkDefaultFont", 12, "bold")
self.f_b = _font("TkDefaultFont", 11)
self.f_mono = _font("TkFixedFont", 9)
st.configure("TFrame", background=BG)
st.configure("Panel.TFrame", background=PANEL)
st.configure("TLabel", background=BG, foreground=FG, font=self.f_b)
st.configure("Sub.TLabel", background=BG, foreground=SUBFG)
st.configure("Panel.TLabel", background=PANEL, foreground=FG)
st.configure("H.TLabel", background=BG, foreground=FG, font=self.f_h)
st.configure("TRadiobutton", background=BG, foreground=FG, font=self.f_b)
st.map("TRadiobutton", background=[("active", BG)])
st.configure("TCheckbutton", background=BG, foreground=FG, font=self.f_b)
st.map("TCheckbutton", background=[("active", BG)])
st.configure("Accent.TButton", font=self.f_h, padding=10)
st.configure("TButton", padding=6)
st.configure("diskos.Horizontal.TProgressbar", background=ACCENT, troughcolor=PANEL)
# ---- layout ------------------------------------------------------------
def _build_widgets(self):
ttk = self.ttk
pad = {"padx": 16}
head = ttk.Frame(self.root)
head.pack(fill="x", pady=(16, 4), **pad)
ttk.Label(head, text="diskOS Installer", font=self.f_title,
background=BG, foreground=FG).pack(anchor="w")
self.host_lbl = ttk.Label(head, text="", style="Sub.TLabel")
self.host_lbl.pack(anchor="w")
# mode
self.mode_frame = ttk.Frame(self.root)
self.mode_frame.pack(fill="x", pady=(10, 4), **pad)
self.mode = __import__("tkinter").StringVar(value="install")
for val, txt in (("install", "Install diskOS"),
("restore", "Remove diskOS (restore stock)"),
("remove", "Uninstall this tool")):
ttk.Radiobutton(self.mode_frame, text=txt, value=val, variable=self.mode,
command=self._on_mode).pack(anchor="w", pady=2)
# config panel (per-mode)
self.cfg = ttk.Frame(self.root, style="Panel.TFrame")
self.cfg.pack(fill="x", pady=10, **pad)
self._build_config()
# primary action
self.action_btn = ttk.Button(self.root, text="Install diskOS…",
style="Accent.TButton", command=self._on_action)
self.action_btn.pack(fill="x", pady=(4, 8), **pad)
# progress
prog = ttk.Frame(self.root)
prog.pack(fill="both", expand=True, **pad)
self.phase_lbl = ttk.Label(prog, text="Ready.", style="H.TLabel")
self.phase_lbl.pack(anchor="w")
self.status_lbl = ttk.Label(prog, text="", style="Sub.TLabel")
self.status_lbl.pack(anchor="w", pady=(0, 6))
self.bar = ttk.Progressbar(prog, style="diskos.Horizontal.TProgressbar",
mode="determinate", maximum=100)
self.bar.pack(fill="x")
self.elapsed_lbl = ttk.Label(prog, text="", style="Sub.TLabel")
self.elapsed_lbl.pack(anchor="w", pady=(2, 6))
self.warn_banner = __import__("tkinter").Label(
prog, text="", bg=WARN, fg="#111", font=self.f_h, anchor="center")
# packed only while flashing
import tkinter as tk
logwrap = ttk.Frame(prog)
logwrap.pack(fill="both", expand=True, pady=(4, 12))
self.log = tk.Text(logwrap, height=10, bg="#111", fg="#cfcfd4",
font=self.f_mono, wrap="word", relief="flat",
insertbackground=FG)
sb = ttk.Scrollbar(logwrap, command=self.log.yview)
self.log.configure(yscrollcommand=sb.set, state="disabled")
self.log.pack(side="left", fill="both", expand=True)
sb.pack(side="right", fill="y")
def _build_config(self):
for w in self.cfg.winfo_children():
w.destroy()
ttk = self.ttk
import tkinter as tk
m = self.mode.get()
inner = ttk.Frame(self.cfg, style="Panel.TFrame")
inner.pack(fill="x", padx=12, pady=12)
if m == "install":
ttk.Label(inner, text="Your FiiO firmware (.zip):", style="Panel.TLabel").grid(
row=0, column=0, sticky="w")
self.fw_var = tk.StringVar()
ttk.Entry(inner, textvariable=self.fw_var, width=44).grid(row=1, column=0, sticky="we", pady=(2, 8))
ttk.Button(inner, text="Browse…", command=self._pick_firmware).grid(row=1, column=1, padx=(8, 0))
ttk.Label(inner, text="Variant:", style="Panel.TLabel").grid(row=2, column=0, sticky="w")
self.variant = tk.StringVar(value="public")
vr = ttk.Frame(inner, style="Panel.TFrame")
vr.grid(row=3, column=0, sticky="w")
ttk.Radiobutton(vr, text="Public (recommended)", value="public",
variable=self.variant, command=self._variant_warn).pack(side="left")
ttk.Radiobutton(vr, text="Dev (root shell)", value="dev",
variable=self.variant, command=self._variant_warn).pack(side="left", padx=(12, 0))
self.variant_warn_lbl = tk.Label(
inner, text="", bg=PANEL, fg=WARN, font=self.f_b, justify="left", wraplength=460)
self.variant_warn_lbl.grid(row=4, column=0, sticky="w", pady=(4, 0))
inner.columnconfigure(0, weight=1)
elif m == "restore":
have = state.stock_image_exists() # fast; full verify happens at restore time
msg = ("A saved bone-stock image is available - restore is one click."
if have else
"No saved stock image. Pick your FiiO firmware .zip so I can rebuild it.")
ttk.Label(inner, text=msg, style="Panel.TLabel", wraplength=460).grid(
row=0, column=0, columnspan=2, sticky="w")
if not have:
self.fw_var = tk.StringVar()
ttk.Entry(inner, textvariable=self.fw_var, width=44).grid(row=1, column=0, sticky="we", pady=(8, 0))
ttk.Button(inner, text="Browse…", command=self._pick_firmware).grid(row=1, column=1, padx=(8, 0), pady=(8, 0))
inner.columnconfigure(0, weight=1)
else: # remove
ttk.Label(inner, wraplength=460, style="Panel.TLabel",
text=("Deletes this installer's saved files from THIS computer. "
"Nothing was installed system-wide. If diskOS is still on the "
"device, use ‘Remove diskOS’ first.")).pack(anchor="w")
# ---- helpers -----------------------------------------------------------
def _pick_firmware(self):
from tkinter import filedialog
p = filedialog.askopenfilename(title="Select FiiO firmware .zip",
filetypes=[("Firmware zip", "*.zip"), ("All", "*")])
if p:
self.fw_var.set(p)
def _variant_warn(self):
lbl = getattr(self, "variant_warn_lbl", None)
if lbl is None:
return
if self.variant.get() == "dev":
lbl.config(text="⚠ Dev installs an ALWAYS-ON PASSWORDLESS ROOT SHELL over USB - "
"anyone with physical access gets root on every boot. It bypasses "
"device security. Development devices only, never an everyday one.")
else:
lbl.config(text="")
def _refresh_state_labels(self):
o, a = platform_probe.host()
n = platform_probe.maskrom_count()
dev = {0: "no device in flash mode", -1: "USB not enumerable"}.get(n, f"{n} device(s) in flash mode")
self.host_lbl.config(text=f"{o}-{a} · v{__version__} · {dev}")
def _on_mode(self):
self._build_config()
self.action_btn.config(text={"install": "Install diskOS…",
"restore": "Remove diskOS (restore stock)…",
"remove": "Uninstall this tool"}[self.mode.get()])
def _log(self, line, color=None):
self.log.config(state="normal")
self.log.insert("end", line + "\n")
# cap the log so it can't grow unbounded
if int(self.log.index("end-1c").split(".")[0]) > 500:
self.log.delete("1.0", "100.0")
self.log.see("end")
self.log.config(state="disabled")
# ---- action / worker ---------------------------------------------------
def _on_action(self):
if self.state == RUNNING:
return
m = self.mode.get()
params = {}
if m == "install":
fw = getattr(self, "fw_var", None) and self.fw_var.get().strip()
if not fw:
self._log("Choose your FiiO firmware .zip first.")
return
params = {"firmware": fw, "variant": self.variant.get()}
fn = service.do_install
elif m == "restore":
fw = getattr(self, "fw_var", None)
params = {"firmware": (fw.get().strip() if fw else None)}
fn = service.do_restore
else:
params = {"force": False}
fn = service.do_remove
self.state = RUNNING
self.start_time = time.monotonic()
self._set_controls(False)
self.bar.config(mode="determinate", value=0)
self.status_lbl.config(text="")
self.elapsed_lbl.config(text="")
self.phase_lbl.config(text="Starting…")
self._clear_finish_extra()
def run():
try:
r = fn(params, self.reporter, self._worker_confirm)
self.q.put(("done", r))
except Exception as e: # BuildError/FlashError/etc.
self.q.put(("failed", {"error": str(e)}))
self.worker = threading.Thread(target=run, daemon=True)
self.worker.start()
def _set_controls(self, enabled):
"""Enable/disable all pre-flight controls (mode + config + action) so nothing
can be changed or re-triggered while a worker is running."""
st = "normal" if enabled else "disabled"
def walk(w):
for c in w.winfo_children():
cls = c.winfo_class()
if cls in ("TRadiobutton", "TButton", "TEntry", "TCheckbutton",
"Radiobutton", "Button", "Entry", "Checkbutton"):
try:
c.config(state=st)
except Exception:
pass
walk(c)
walk(self.mode_frame)
walk(self.cfg)
self.action_btn.config(state=st)
def _clear_finish_extra(self):
w = getattr(self, "_finish_extra", None)
if w is not None:
w.destroy()
self._finish_extra = None
def _worker_confirm(self, summary):
"""Called ON THE WORKER THREAD. Ask the UI (main thread) and block."""
self._confirm_result = False
self._confirm_event.clear()
self.q.put(("confirm", summary))
self._confirm_event.wait()
return self._confirm_result
def _show_confirm_dialog(self, summary):
import tkinter as tk
from tkinter import ttk
W = 480
dlg = tk.Toplevel(self.root)
dlg.title("Confirm")
dlg.configure(bg=BG)
dlg.transient(self.root)
dlg.resizable(False, False)
destructive = summary.get("action") in ("install", "restore-stock")
body = ttk.Frame(dlg)
body.pack(fill="both", expand=True, padx=18, pady=16)
ttk.Label(body, text=summary.get("action", "confirm").upper(),
style="H.TLabel").pack(anchor="w", pady=(0, 6))
for k in ("variant", "duration", "consequence"):
if summary.get(k):
ttk.Label(body, text=f"{k}: {summary[k]}", style="Sub.TLabel",
wraplength=W - 36, justify="left").pack(anchor="w", pady=1)
def _resolve(val):
# Mark the destructive boundary SYNCHRONOUSLY (main thread) the instant the
# user accepts - before the worker unblocks and spawns usbboot - so the
# window can't be closed in the gap before the 'phase' event is drained.
if val and destructive:
self.flashing = True
self._confirm_result = val
dlg.destroy()
self._confirm_event.set()
# button row FIRST (both buttons are direct children of it)
row = ttk.Frame(body)
row.pack(side="bottom", fill="x", pady=(14, 0))
ttk.Button(row, text="Cancel", command=lambda: _resolve(False)).pack(side="right", padx=(8, 0))
begin = ttk.Button(row, text=("Begin 60-90 minute flash" if destructive else "Proceed"),
style="Accent.TButton", command=lambda: _resolve(True))
begin.pack(side="right")
ack = tk.BooleanVar(value=not destructive)
if destructive:
# classic tk.Checkbutton (ttk.Checkbutton has no wraplength)
tk.Checkbutton(body, variable=ack, wraplength=W - 40, justify="left",
text="I understand this rewrites my device and must not be interrupted.",
bg=BG, fg=FG, selectcolor=PANEL, activebackground=BG,
activeforeground=FG, highlightthickness=0, font=self.f_b,
command=lambda: begin.config(state=("normal" if ack.get() else "disabled"))
).pack(anchor="w", pady=(12, 8))
begin.config(state="disabled")
# size to content, then centre over the main window
dlg.update_idletasks()
h = dlg.winfo_reqheight()
self.root.update_idletasks()
px, py = self.root.winfo_rootx(), self.root.winfo_rooty()
pw = self.root.winfo_width()
dlg.geometry(f"{W}x{h}+{px + max(0, (pw - W) // 2)}+{py + 110}")
dlg.grab_set()
dlg.protocol("WM_DELETE_WINDOW", lambda: _resolve(False))
dlg.bind("<Escape>", lambda e: _resolve(False))
dlg.bind("<Return>", lambda e: _resolve(True) if str(begin["state"]) == "normal" else None)
(begin if not destructive else dlg).focus_set()
# ---- queue drain (main thread) ----------------------------------------
def _drain(self):
budget = 200 # bounded per tick so a flood of events can't starve Tk
try:
while budget > 0:
kind, payload = self.q.get_nowait()
budget -= 1
try:
self._handle(kind, payload)
except Exception as e: # one malformed event must not stop the drain
self._log(f"[ui error handling {kind}: {e}]")
except queue.Empty:
pass
self.root.after(80, self._drain)
def _handle(self, kind, p):
if kind == "phase":
self.phase_lbl.config(text=p["name"])
if p.get("destructive"):
self.flashing = True
self.bar.config(mode="indeterminate")
self.bar.start(12)
self.warn_banner.config(text="DO NOT DISCONNECT THE DEVICE OR LET THE HOST SLEEP")
self.warn_banner.pack(fill="x", pady=6, before=self.log.master)
self._log("▶ " + p["name"])
elif kind == "status":
self.status_lbl.config(text=p["message"])
self._log(p["message"])
elif kind == "log":
self._log(" " + p["line"])
elif kind == "progress":
if self.bar["mode"] == "indeterminate":
self.bar.stop(); self.bar.config(mode="determinate")
total = p["total"] or 1
self.bar.config(maximum=total, value=p["completed"])
elif kind == "indeterminate":
if p["active"]:
self.bar.config(mode="indeterminate"); self.bar.start(12)
self.status_lbl.config(text=p.get("note", ""))
else:
self.bar.stop(); self.bar.config(mode="determinate")
elif kind == "warning":
self._log("! " + p["message"])
elif kind == "ok":
self._log("✓ " + p["message"])
elif kind == "error":
self._log("✗ " + p["message"])
elif kind == "confirm":
self._show_confirm_dialog(p)
elif kind == "done":
self._finish(p)
elif kind == "failed":
self._fail(p.get("error", "unknown error"))
def _finish(self, r):
self.flashing = False
if self.bar["mode"] == "indeterminate":
self.bar.stop()
self.warn_banner.pack_forget()
self._set_controls(True)
if r.get("aborted"):
self.state = IDLE
self.phase_lbl.config(text="Cancelled - device unchanged.")
elif r.get("errors"): # e.g. uninstall couldn't remove everything
self.state = FAILED
self.phase_lbl.config(text="Finished with problems - see log.")
else:
self.state = SUCCESS
self.bar.config(mode="determinate", maximum=100, value=100)
if self.mode.get() == "install":
self.phase_lbl.config(text="Flashed ✓ One more step ↓")
self._install_followup()
elif self.mode.get() == "remove":
self.phase_lbl.config(text="Removed ✓ Delete the app to finish.")
else:
self.phase_lbl.config(text="Done ✓ Power-cycle the device.")
self._refresh_state_labels()
def _install_followup(self):
"""The UI is embedded in the flashed image, so first boot installs diskOS on its own -
no microSD step. Offer an OPTIONAL SD copy only as a recovery fallback."""
import tkinter as tk
from tkinter import ttk
self._clear_finish_extra()
box = tk.Frame(self.root, bg=OKC)
box.pack(fill="x", padx=16, pady=(0, 8))
self._finish_extra = box
tk.Label(box, bg=OKC, fg="#111", font=self.f_h, justify="left", wraplength=500,
text="Done - just power-cycle the device. diskOS is embedded in the flash and "
"installs itself on first boot; no microSD step needed.").pack(
anchor="w", padx=10, pady=(8, 4))
tk.Label(box, bg=OKC, fg="#111", font=self.f_b, justify="left", wraplength=500,
text="Optional: you can also stage a fallback copy on a microSD (used only if the "
"embedded copy is ever unreadable).").pack(anchor="w", padx=10, pady=(0, 2))
ttk.Button(box, text="Copy fallback UI to microSD…", command=self._export_ui).pack(
anchor="w", padx=10, pady=(0, 8))
def _export_ui(self):
from tkinter import filedialog, messagebox
src = bundle.data("mq_ui", required=False)
if not src:
messagebox.showerror("diskOS Installer", "bundled mq_ui not found.")
return
d = filedialog.askdirectory(title="Select your microSD card (root)")
if not d:
return
try:
dest_dir = os.path.join(d, "diskos")
os.makedirs(dest_dir, exist_ok=True)
dest = os.path.join(dest_dir, "mq_ui")
with open(src, "rb") as s, open(dest, "wb") as o:
o.write(s.read())
os.chmod(dest, 0o755)
self._log(f"✓ copied UI to {dest}")
messagebox.showinfo("diskOS Installer",
f"Copied a fallback diskOS UI to:\n{dest}\n\nThis is optional - the "
"device installs the embedded copy on its own. The card is only used "
"if that embedded copy is ever unreadable.")
except OSError as e:
messagebox.showerror("diskOS Installer", f"Could not copy to the card:\n{e}")
def _fail(self, msg):
self.flashing = False
try:
self.bar.stop()
except Exception:
pass
self.warn_banner.pack_forget()
self.state = FAILED
self._set_controls(True)
self.phase_lbl.config(text="Failed")
self._log("✗ " + msg)
from tkinter import messagebox
messagebox.showerror("diskOS Installer", msg)
def _tick_elapsed(self):
if self.state == RUNNING and self.start_time:
secs = int(time.monotonic() - self.start_time)
self.elapsed_lbl.config(text=f"elapsed {secs // 60}m{secs % 60:02d}s")
self.root.after(1000, self._tick_elapsed)
def _tick_device(self):
# keep the device-status line fresh, but never scan USB mid-operation
if self.state != RUNNING:
self._refresh_state_labels()
self.root.after(4000, self._tick_device)
def _on_close(self):
from tkinter import messagebox
if self.flashing:
messagebox.showwarning(
"Flash in progress",
"A flash is in progress. Closing now can leave the device needing a "
"mask-ROM recovery. Please wait until it finishes.")
return
if self.state == RUNNING:
if not messagebox.askokcancel(
"Operation in progress",
"An operation is still running. Close anyway?"):
return
self.root.destroy()
def main():
try:
import tkinter as tk
except Exception as e:
sys.stderr.write(f"diskOS Installer: Tkinter unavailable ({e}). Use the CLI: "
"diskos-installer --help\n")
return 2
try:
root = tk.Tk()
App(root)
root.mainloop()
return 0
except Exception as e:
# A packaged GUI hides early tracebacks - persist one and show a dialog.
import tempfile
import traceback
# Unique, 0600 crash log (a fixed name in a world-writable temp dir could be pre-placed as a
# symlink to truncate an arbitrary target). The exact path is shown in the message below.
try:
fd, logp = tempfile.mkstemp(prefix="diskos-installer-startup-", suffix=".log")
with os.fdopen(fd, "w") as f:
f.write(traceback.format_exc())
except OSError:
logp = "(could not write a log file)"
sys.stderr.write(f"diskOS Installer failed to start: {e}\n(log: {logp})\n"
"Try the CLI: diskos-installer doctor\n")
try:
import tkinter.messagebox as mb
mb.showerror("diskOS Installer",
f"Failed to start:\n{e}\n\nDetails: {logp}\n"
"You can still use the command line: diskos-installer doctor")
except Exception:
pass
return 1
if __name__ == "__main__":
sys.exit(main())
+511
View File
@@ -0,0 +1,511 @@
"""Build a flashable diskOS image from the user's OWN stock firmware.
Faithful Python port of the proven mkdiskos.sh / extract_stock_rootfs.sh logic:
extract_stock_rootfs(zip) -> stock rootfs.squashfs (byte-exact from FiiO's zip)
build_image(stock, mq_ui, variant) -> diskos_<variant>.bin (76021760 bytes)
We NEVER ship FiiO's rootfs; the user supplies their official firmware zip and we
build locally. squashfs pack/unpack delegates to the bundled mksquashfs/unsquashfs
(reference tools) - we do not reimplement squashfs.
"""
import os
import re
import subprocess
import zipfile
from . import bundle
from .reporter import CLIReporter
IMG_SIZE = 76021760 # diskOS image size: 580 NAND blocks (~72.5 MiB); written to the start of the mtd2 rootfs partition (RO squashfs need not fill the 128 MB partition)
# Known-good stock rootfs.squashfs, verified out-of-band (NOT trusting the in-zip OTA manifest,
# which an attacker could modify consistently). A tested firmware whose extracted rootfs does not
# match its pin is refused: this rejects a modified/tampered/corrupt rootfs before it is patched
# and flashed. Map: MAIN_OS_VER -> (sha256, size_bytes). Add a version's pin only after hashing an
# authentic copy of that firmware.
PINNED_ROOTFS = {
"228": ("0ffd877bca2c69ddff9ca70f4494da0d9e580c18d0f587e2c6d9921f2db82bd2", 72957952),
"209": ("f1e3c69fb0e88b923c135558e01f4387a661f68839c8118e8ad490bdc9fc74e6", 75919360),
}
# Firmware versions diskOS has been flash-tested against. Others have DIFFERENT command-tag
# meanings, so diskOS built on them can send wrong commands and misbehave/reboot.
TESTED_FW = {"209", "228"}
SQUASH_MAGIC = b"hsqs"
def validate_stock_rootfs(stock_squashfs, rep=None):
"""Validate that `stock_squashfs` is a genuine, supported, known-good Snowsky Disc rootfs -
a SHARED gate called BEFORE the image is saved as the recovery copy, BEFORE build, and BEFORE
every restore-flash (so a wrong-device or crafted rootfs can never be saved or flashed on the
strength of a size/magic preflight alone). Raises BuildError (E220 not-a-Disc-rootfs / E221
untested version / E224 hash mismatch). Returns the MAIN_OS_VER string. Only extracts the tiny
version.in - cheap enough to run on every path. DISKOS_ALLOW_UNTESTED_FW=1 relaxes E221/E224."""
rep = rep or CLIReporter()
import hashlib, tempfile, shutil
unsq = bundle.native("unsquashfs")
with open(stock_squashfs, "rb") as f:
if f.read(4) != SQUASH_MAGIC:
raise BuildError("not a squashfs image (bad magic) - not a Snowsky Disc rootfs", code="E220")
tmp = tempfile.mkdtemp(prefix="diskos-vchk-")
try:
_run([unsq, "-d", os.path.join(tmp, "x"), "-f", stock_squashfs,
"etc/product_version/version.in"], capture_output=True, text=True)
ver_in = os.path.join(tmp, "x", "etc/product_version/version.in")
prod = _grep1(ver_in, r"PRODUCT=([A-Za-z0-9_]+)")
mver = _grep1(ver_in, r"MAIN_OS_VER=([0-9]+)")
finally:
shutil.rmtree(tmp, ignore_errors=True)
override = os.environ.get("DISKOS_ALLOW_UNTESTED_FW") == "1"
if prod != "SNOWSKY_DISC":
raise BuildError(f"not a Snowsky Disc rootfs (PRODUCT={prod!r})", code="E220")
if mver not in TESTED_FW and not override:
raise BuildError(
f"firmware MAIN_OS_VER={mver or '?'} is not tested (supported: {', '.join(sorted(TESTED_FW))}). "
"Other versions can have incompatible command meanings. Re-run with "
"DISKOS_ALLOW_UNTESTED_FW=1 at your own risk.", code="E221")
pin = PINNED_ROOTFS.get(mver)
if pin:
exp_sha, exp_sz = pin
got_sz = os.path.getsize(stock_squashfs)
# The pin is over the EXACT extracted rootfs (exp_sz bytes). But the SAVED recovery copy is
# those same bytes zero-PADDED to the partition size (_save_stock pads to IMG_SIZE), so this
# gate is called with both the unpadded (install/build) and padded (restore) forms. Validate
# the first exp_sz bytes against the pin and require every byte AFTER to be zero padding - so a
# padded copy verifies identically to the original, while arbitrary appended data still fails.
got_sha, tail_zero = None, False
if exp_sz <= got_sz <= IMG_SIZE:
with open(stock_squashfs, "rb") as f:
h = hashlib.sha256(); remaining = exp_sz
while remaining > 0:
chunk = f.read(min(1 << 20, remaining))
if not chunk:
break
h.update(chunk); remaining -= len(chunk)
got_sha = h.hexdigest() if remaining == 0 else None
tail_zero = True # anything past exp_sz must be pure zero padding
while True:
chunk = f.read(1 << 20)
if not chunk:
break
if chunk.strip(b"\x00"):
tail_zero = False; break
if got_sha != exp_sha or not tail_zero:
if override:
rep.warning(f"stock rootfs hash {(got_sha or '?')[:12]}... != pinned V{mver} - proceeding (override set)")
else:
raise BuildError(
f"stock rootfs does not match the known-good V{mver} image (got "
f"{(got_sha or 'short/oversize')[:12]}..., expected {exp_sha[:12]}...). The firmware "
"may be modified, corrupt, or repackaged - re-download the official FiiO firmware. "
"(Set DISKOS_ALLOW_UNTESTED_FW=1 at your own risk.)", code="E224")
else:
rep.log(f"stock rootfs matches the pinned known-good V{mver} image (sha256 verified)")
elif mver in TESTED_FW:
rep.warning(f"no pinned hash for V{mver} yet - rootfs authenticity is NOT verified against a pin")
rep.log(f"stock rootfs OK: PRODUCT={prod} MAIN_OS_VER={mver or '?'}")
return mver
from .errors import BuildError # coded (E2xx); re-exported so imagebuild.BuildError still resolves
# --- safe zip extraction (reject traversal / symlink escape / bombs) ---------
def _safe_extract_member(zf, member, dest_root):
name = member.filename
if name.startswith("/") or os.path.isabs(name) or ".." in name.replace("\\", "/").split("/"):
raise BuildError(f"unsafe path in zip: {name!r}", code="E202")
target = os.path.realpath(os.path.join(dest_root, name))
if not (target == os.path.realpath(dest_root) or
target.startswith(os.path.realpath(dest_root) + os.sep)):
raise BuildError(f"zip entry escapes extraction dir: {name!r}", code="E202")
return target
# FiiO chunks the rootfs and wraps each chunk (and the manifest) in AES-256-CBC
# (openssl -pbkdf2) under the fixed key "fo123" (their reused OTA string -
# obfuscation, not protection). We decrypt + concatenate in index order. We only
# READ the image; no signature is involved.
_OTA_KEY = "fo123"
def _openssl_aes_decrypt(data, password):
"""Replicate `openssl enc -d -aes-256-cbc -pbkdf2 -k <password>`:
'Salted__' + 8-byte salt header, PBKDF2-HMAC-SHA256 (10000 iters) -> 32B key +
16B IV, AES-256-CBC, PKCS7 padding."""
import hashlib
from Crypto.Cipher import AES # pycryptodome (bundled)
if data[:8] != b"Salted__":
raise BuildError("encrypted blob missing openssl 'Salted__' header (not a FiiO OTA chunk?)", code="E211")
salt = data[8:16]
ct = data[16:]
if len(ct) == 0 or len(ct) % 16 != 0:
raise BuildError("encrypted blob has bad length (truncated chunk?)", code="E211")
keyiv = hashlib.pbkdf2_hmac("sha256", password.encode(), salt, 10000, 48)
pt = AES.new(keyiv[:32], AES.MODE_CBC, keyiv[32:48]).decrypt(ct)
pad = pt[-1] if pt else 0
if pad < 1 or pad > 16 or pt[-pad:] != bytes([pad]) * pad:
raise BuildError("bad PKCS7 padding after AES decrypt (wrong key or firmware?)", code="E211")
return pt[:-pad]
def extract_stock_rootfs(fw_zip, out_squashfs, workdir, rep=None):
"""Pull the exact stock rootfs.squashfs out of FiiO's official update zip by
decrypting + reassembling the main_os OTA chunks. Byte-exact; written only
after it validates (manifest size + squashfs magic), so a failure never
clobbers the output."""
rep = rep or CLIReporter()
rep.phase("Extracting stock firmware")
if not zipfile.is_zipfile(fw_zip):
raise BuildError(f"not a zip archive: {fw_zip}", code="E201")
ex = os.path.join(workdir, "fw_unzip")
import shutil
if os.path.isdir(ex): # fresh every time - never mix two firmwares' chunks
shutil.rmtree(ex, ignore_errors=True)
os.makedirs(ex)
total_uncompressed = 0
with zipfile.ZipFile(fw_zip) as zf:
infos = zf.infolist()
if len(infos) > 20000: # per-entry count bound (not just aggregate size)
raise BuildError("zip has an implausible number of entries - refusing.", code="E202")
for m in infos:
total_uncompressed += m.file_size
if total_uncompressed > 4 * (1 << 30): # 4 GiB bomb guard
raise BuildError("zip expands beyond 4 GiB - refusing (possible zip bomb)", code="E202")
rep.status("Unpacking firmware zip")
for i, m in enumerate(infos):
tgt = _safe_extract_member(zf, m, ex)
if m.is_dir():
os.makedirs(tgt, exist_ok=True)
else:
os.makedirs(os.path.dirname(tgt), exist_ok=True)
with zf.open(m) as src, open(tgt, "wb") as dst:
while True:
chunk = src.read(1 << 20)
if not chunk:
break
dst.write(chunk)
rep.progress(i + 1, len(infos))
# locate the ONE main_os OTA manifest (refuse ambiguity)
import glob
mans = sorted(glob.glob(os.path.join(ex, "**", "main_os", "ota_v*", "ota_update.in.enc"),
recursive=True))
if len(mans) == 0:
raise BuildError("no main_os/ota_v*/ota_update.in.enc in this zip - not a Disc "
"main-OS firmware?", code="E210")
if len(mans) > 1:
raise BuildError(f"{len(mans)} main_os manifests in this zip - ambiguous, aborting.", code="E210")
man_enc = mans[0]
ota_dir = os.path.dirname(man_enc)
rep.log(f"OTA dir: {os.path.relpath(ota_dir, ex)}")
manifest = _openssl_aes_decrypt(open(man_enc, "rb").read(), _OTA_KEY).decode("utf-8", "ignore")
img_name, img_size = _parse_rootfs_manifest(manifest)
if not img_name:
raise BuildError("no rootfs image in the OTA manifest.", code="E210")
# img_name must be a bare basename (no path separators / traversal)
if img_name != os.path.basename(img_name) or img_name in ("", ".", "..") or "/" in img_name or "\\" in img_name:
raise BuildError(f"OTA manifest rootfs image name is not a safe basename: {img_name!r}", code="E210")
if img_size is not None:
if not img_size.isdigit() or not (0 < int(img_size) <= 256 * (1 << 20)):
raise BuildError(f"OTA manifest img_size is implausible: {img_size!r}", code="E210")
rep.log(f"rootfs image={img_name} expected_size={img_size or '?'}")
# order the $img.NNNN.enc chunks by numeric index (skip ota_sha256_* etc.);
# reject DUPLICATE indices and require a contiguous 0..N-1 sequence.
by_idx = {}
for f in glob.glob(os.path.join(ota_dir, glob.escape(img_name) + ".*.enc")):
rest = os.path.basename(f)[len(img_name) + 1:] # "NNNN.<hash>.enc"
idx = rest.split(".", 1)[0]
if not idx.isdigit():
continue
i = int(idx)
if i in by_idx:
raise BuildError(f"duplicate rootfs chunk index {i} in the OTA dir - refusing.", code="E212")
by_idx[i] = f
if not by_idx:
raise BuildError(f"no {img_name}.NNNN.*.enc chunks found in the OTA dir.", code="E212")
idxs = sorted(by_idx)
if idxs != list(range(len(idxs))):
raise BuildError(f"rootfs chunk indices are not a contiguous 0..{len(idxs)-1} sequence "
f"(got {idxs[:3]}…{idxs[-1]}) - missing chunk, refusing.", code="E212")
chunks = [(i, by_idx[i]) for i in idxs]
tmpout = os.path.join(workdir, "rootfs.assembled")
rep.status("Decrypting + assembling rootfs")
with open(tmpout, "wb") as out:
for i, (_idx, f) in enumerate(chunks):
out.write(_openssl_aes_decrypt(open(f, "rb").read(), _OTA_KEY))
rep.progress(i + 1, len(chunks))
got = os.path.getsize(tmpout)
rep.log(f"assembled {len(chunks)} chunks ({got} bytes)")
if img_size and got != int(img_size):
raise BuildError(f"assembled size {got} != manifest {img_size} (missing/dup chunk?)", code="E213")
with open(tmpout, "rb") as f:
if f.read(4) != SQUASH_MAGIC:
raise BuildError("assembled output is not a squashfs (bad magic) - wrong key/firmware.", code="E213")
os.replace(tmpout, out_squashfs)
rep.ok(f"stock rootfs extracted -> {out_squashfs} ({got} bytes)")
return out_squashfs
def _parse_rootfs_manifest(text):
"""From the decrypted ota_update.in, return (img_name, img_size) for the block
whose img_type=rootfs (mirrors the awk in extract_stock_rootfs.sh)."""
in_rootfs = False
name = size = None
for line in text.splitlines():
line = line.strip()
if line == "img_type=rootfs" or line.endswith("=rootfs") and line.startswith("img_type"):
in_rootfs = True
continue
if in_rootfs:
if line.startswith("img_name="):
name = line[len("img_name="):]
elif line.startswith("img_size="):
size = line[len("img_size="):]
if name and size:
break
return name, size
def _copyfile(src, dst):
with open(src, "rb") as s, open(dst, "wb") as d:
while True:
b = s.read(1 << 20)
if not b:
break
d.write(b)
# --- fiio_init.sh boot-hook patch (python-native, single-match-or-refuse) ----
_OLD_IF = 'if [ "$COREDUMP_FLAG" == "1" ]; then'
_LAUNCH = _OLD_IF + "\n /usr/data/mq_ui &"
_BLOCK = (
"if [ -f /usr/data/mq_ui ] && [ -f /usr/data/mq_player ]; then\n"
" # diskOS override: run our UI + the player from /usr/data (persists across\n"
" # rootfs flashes). Falls back to the stock rootfs binaries if either is absent.\n"
" /usr/data/mq_ui &\n sleep 2\n /usr/data/mq_player &\n"
'elif [ "$COREDUMP_FLAG" == "1" ]; then'
)
def _patch_fiio_init(path, rep):
with open(path, encoding="utf-8", errors="surrogateescape") as f:
s = f.read()
# We always start from freshly-extracted OFFICIAL stock, so the file must be
# UNpatched: refuse anything already containing our marker (corrupt/re-used tree)
# rather than trusting it.
if "diskOS override" in s:
raise BuildError("fiio_init.sh already contains a diskOS marker - refusing to "
"patch a non-pristine rootfs. Re-extract from official firmware.", code="E223")
n = s.count(_LAUNCH)
if n != 1:
raise BuildError(
"boot-hook anchor (COREDUMP launch block) "
f"{'not found' if n == 0 else 'ambiguous'} in fiio_init.sh - "
"incompatible firmware boot structure; do not ship this base untested.", code="E223")
i = s.index(_LAUNCH)
s = s[:i] + _BLOCK + s[i + len(_OLD_IF):]
with open(path, "w", encoding="utf-8", errors="surrogateescape") as f:
f.write(s)
# --- ELF sanity for the UI binary -------------------------------------------
def _validate_ui_elf(ui_path):
if not os.path.exists(ui_path):
raise BuildError(f"UI binary not found: {ui_path}", code="E222")
with open(ui_path, "rb") as f:
hdr = f.read(20)
if hdr[:4] != b"\x7fELF":
raise BuildError(f"'{ui_path}' is not an ELF", code="E222")
if hdr[4:6] != b"\x01\x01":
raise BuildError(f"'{ui_path}' is not ELF32 little-endian (EI_CLASS/DATA)", code="E222")
if hdr[18:20] != b"\x08\x00":
raise BuildError(f"'{ui_path}' e_machine is not MIPS-LE", code="E222")
def _run(cmd, **kw):
return subprocess.run(cmd, env=bundle.native_env(), **kw)
def _validate_squashfs_output(sq_path, unsq, expect_ui_sha, expect_ui_sz, rep=None):
"""Validate a freshly-repacked squashfs by its CONTENT, not the repacker's exit status. Does a
COMPLETE independent extraction (so silent corruption ANYWHERE fails, not just in two files),
then verifies every boot-critical artefact: the boot-hook patch in fiio_init.sh, the executable
first-boot installer hook, the manifest (agreeing with the embedded UI), and the embedded UI
itself (exact sha256 + size + exec bit). Raises BuildError (E232) on any problem."""
import hashlib, tempfile, shutil
with open(sq_path, "rb") as f:
if f.read(4) != b"hsqs":
raise BuildError("repacked image is not a valid squashfs (bad superblock magic) - "
"the repacker produced a corrupt file", code="E232")
tmp = tempfile.mkdtemp(prefix="diskos-sqcheck-")
try:
dst = os.path.join(tmp, "x")
# FULL extraction (no file subset): a corrupt inode / metadata block / file anywhere in the
# bootable filesystem makes this fail, which two-file extraction would miss.
r = _run([unsq, "-d", dst, "-f", sq_path], capture_output=True, text=True)
if r.returncode != 0:
raise BuildError(f"repacked image failed full extraction (unsquashfs rc={r.returncode}) - "
f"corrupt/truncated repack: {r.stderr.strip()[:200]}", code="E232")
def _need(rel, what):
p = os.path.join(dst, rel)
if not os.path.exists(p):
raise BuildError(f"repacked image is missing {what} ({rel}) - do NOT flash", code="E232")
return p
# boot hook present + patched
with open(_need("usr/project/fiio_init.sh", "boot script"), encoding="utf-8", errors="ignore") as f:
if "diskOS override" not in f.read():
raise BuildError("repacked image: fiio_init.sh lacks the diskOS boot-hook patch", code="E232")
# first-boot installer hook present + executable
s97 = _need("etc/init.d/S97diskos_install", "first-boot installer hook")
if not (os.stat(s97).st_mode & 0o111):
raise BuildError("repacked image: S97diskos_install is not executable", code="E232")
# embedded UI: exact identity + exec bit
ui = _need("opt/diskos/mq_ui", "embedded UI")
if os.path.getsize(ui) != expect_ui_sz:
raise BuildError(f"repacked image: embedded UI size {os.path.getsize(ui)} != {expect_ui_sz}", code="E232")
if hashlib.sha256(open(ui, "rb").read()).hexdigest() != expect_ui_sha:
raise BuildError("repacked image: embedded UI hash mismatch (repack corrupted it) - do NOT flash", code="E232")
if not (os.stat(ui).st_mode & 0o111):
raise BuildError("repacked image: embedded UI is not executable", code="E232")
# manifest present + agrees with the embedded UI (the on-device hook trusts it)
man = _need("etc/diskos_manifest", "diskOS manifest")
if (_grep1(man, r"SHA256=([0-9a-fA-F]+)") != expect_ui_sha
or _grep1(man, r"SIZE=([0-9]+)") != str(expect_ui_sz)):
raise BuildError("repacked image: manifest/UI mismatch - do NOT flash", code="E232")
finally:
shutil.rmtree(tmp, ignore_errors=True)
if rep is not None:
rep.log("output squashfs validated (full extraction + boot hook + S97 + manifest + UI hash/mode)")
def build_image(stock_squashfs, ui_binary, variant, out_bin, workdir, rep=None):
"""Build diskos_<variant>.bin from a stock rootfs + the diskOS UI."""
rep = rep or CLIReporter()
if variant not in ("public", "dev"):
raise BuildError(f"variant must be 'public' or 'dev', got {variant!r}", code="E250")
rep.phase(f"Building diskOS image ({variant})")
unsq = bundle.native("unsquashfs")
mksq = bundle.native("mksquashfs")
rf = os.path.join(workdir, "rf")
if os.path.isdir(rf):
import shutil
shutil.rmtree(rf)
rep.status("[1/6] unpacking stock rootfs")
r = _run([unsq, "-d", rf, stock_squashfs], capture_output=True, text=True)
if r.returncode != 0:
raise BuildError(f"unsquashfs failed: {r.stderr.strip()[:400]}", code="E230")
rep.status("[2/6] validating base is a Snowsky Disc rootfs")
validate_stock_rootfs(stock_squashfs, rep) # product / tested-version / known-good-hash gate
rep.status("[3/6] validating the diskOS UI binary")
_validate_ui_elf(ui_binary)
rep.status("[4/6] patching fiio_init.sh + installing first-boot hook")
fiio_path = os.path.join(rf, "usr/project/fiio_init.sh")
_assert_within_rf(rf, fiio_path) # a crafted rootfs must not redirect the in-place patch
_patch_fiio_init(fiio_path, rep)
_install(bundle.data("S97diskos_install"), os.path.join(rf, "etc/init.d/S97diskos_install"), 0o755, rf)
import hashlib
ui_sha = hashlib.sha256(open(ui_binary, "rb").read()).hexdigest()
ui_sz = os.path.getsize(ui_binary)
import time
manifest_path = os.path.join(rf, "etc/diskos_manifest")
_assert_within_rf(rf, manifest_path)
if os.path.islink(manifest_path):
os.unlink(manifest_path) # never follow a planted symlink at the manifest path
with open(manifest_path, "w") as f:
f.write(f"SHA256={ui_sha}\nSIZE={ui_sz}\nARCH=mips-le\nVARIANT={variant}\n"
f"BUILT={time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}\n")
# Embed the UI INSIDE the rootfs at a fixed path the S97 hook installs from FIRST (SD is only a
# fallback source). This makes first boot need no SD card: flash -> reboot -> diskOS. The hook
# still verify_ui's this copy against the manifest above, so a corrupt flash can't run it.
_install(ui_binary, os.path.join(rf, "opt/diskos/mq_ui"), 0o755, rf)
# Debug-access tooling (BOTH variants): the diskos-debug helper + a static dropbear. mq_ui's
# "Debug Mode" toggle drives these to start SSH (random per-enable password) and/or the USB
# serial shell on demand. Shipping them in the public image too means a normal user can enable
# debug access from the UI without needing the dev build.
_install(bundle.data("dropbearmulti"), os.path.join(rf, "usr/project/dropbearmulti"), 0o755, rf)
_install(bundle.data("diskos-debug.sh"), os.path.join(rf, "usr/project/diskos-debug.sh"), 0o755, rf)
if variant == "dev":
# Dev only: an ALWAYS-ON USB serial recovery shell (builds the gadget + attaches the one
# diskos-debug shell at boot), so a dev build is reachable over USB even before the UI runs.
_install(bundle.data("S99usbserial"), os.path.join(rf, "etc/init.d/S99usbserial"), 0o755, rf)
rep.status("[5/6] repacking squashfs (stock params: lzo, -b 131072)")
out_sq = os.path.join(workdir, "out.squashfs")
if os.path.exists(out_sq):
os.remove(out_sq)
r = _run([mksq, rf, out_sq, "-comp", "lzo", "-b", "131072",
"-no-xattrs", "-all-root", "-noappend"], capture_output=True, text=True)
if r.returncode != 0:
raise BuildError(f"mksquashfs failed: {r.stderr.strip()[:400]}", code="E230")
sqsz = os.path.getsize(out_sq)
if sqsz > IMG_SIZE:
raise BuildError(
f"squashfs is {sqsz} > {IMG_SIZE} partition - refusing (truncating would "
"make it unbootable). Trim content or use a smaller UI.", code="E231")
# Trust the OUTPUT, not the repacker's exit code: confirm the superblock magic AND that the
# embedded UI extracts byte-identical (an independent unsquashfs round-trip). Catches a
# silently-corrupt/truncated repack - the exact failure mode a nonzero-exit-but-valid (or, worse,
# zero-exit-but-corrupt) mksquashfs could hide - before it ever reaches the device.
_validate_squashfs_output(out_sq, unsq, ui_sha, ui_sz, rep)
rep.status("[6/6] finalizing image (pad to partition size)")
_copyfile(out_sq, out_bin)
with open(out_bin, "r+b") as f: # pad to exact partition size
f.truncate(IMG_SIZE)
import hashlib as _h
md5 = _h.md5(open(out_bin, "rb").read()).hexdigest()
rep.ok(f"image built: {out_bin} ({os.path.getsize(out_bin)} bytes) md5={md5}")
return out_bin
def _grep1(path, pattern):
try:
with open(path, encoding="utf-8", errors="ignore") as f:
m = re.search(pattern, f.read())
return m.group(1) if m else None
except OSError:
return None
def _assert_within_rf(rf, dst, code="E233"):
"""Refuse a write target that, via a symlink AT the target or in any PARENT component, resolves
OUTSIDE the extracted rootfs `rf`. Image building runs with the caller's privileges (often sudo,
since mask-ROM USB needs it), so a crafted stock squashfs that ships e.g.
`etc/init.d/S97diskos_install -> /etc/cron.d/x` could make a plain open() clobber a host file.
realpath() resolves every symlink on the path, so an escape is caught here before any write."""
rroot = os.path.realpath(rf)
real = os.path.realpath(dst)
if not (real == rroot or real.startswith(rroot + os.sep)):
raise BuildError(
f"refusing to write outside the rootfs: {dst!r} resolves to {real!r} via a symlink - "
"the stock firmware may be crafted or corrupt. Re-download the official FiiO firmware.",
code=code)
def _install(src, dst, mode, rf):
_assert_within_rf(rf, dst)
os.makedirs(os.path.dirname(dst), exist_ok=True)
if os.path.islink(dst):
os.unlink(dst) # replace a planted symlink with a real file - never follow it
_copyfile(src, dst)
os.chmod(dst, mode)
+104
View File
@@ -0,0 +1,104 @@
"""Host OS/arch detection and Snowsky-Disc device presence checks.
Device USB identities we care about:
- Ingenic X2000 mask-ROM (flashing mode): VID:PID 0a108:eaef (a108:eaef)
- normal running device (not used for flashing) is a different id.
We enumerate USB via pyusb (bundled) so we don't depend on `lsusb` being present.
"""
import platform
import sys
MASKROM_VID = 0x0a108 & 0xFFFF # printed as a108 by lsusb; VID field is 0xa108
MASKROM_PID = 0xeaef
# lsusb shows "a108:eaef"; libusb reports idVendor=0xa108 idProduct=0xeaef
MASKROM_VID = 0xa108
def host():
"""Return (os_key, arch_key) e.g. ('linux','x86_64') / ('macos','arm64')."""
sysname = platform.system().lower()
if sysname == "darwin":
os_key = "macos"
elif sysname == "linux":
os_key = "linux"
else:
os_key = sysname # 'windows' etc. - unsupported for now
machine = platform.machine().lower()
arch = {
"x86_64": "x86_64", "amd64": "x86_64",
"arm64": "arm64", "aarch64": "arm64",
}.get(machine, machine)
return os_key, arch
def host_tag():
o, a = host()
return f"{o}-{a}"
def is_supported():
o, _ = host()
return o in ("linux", "macos")
def _bundled_libusb_backend():
"""A pyusb libusb1 backend pointed at OUR bundled libusb, so USB enumeration
works in the frozen app even when the system has no libusb. Returns a backend
or None (caller falls back to pyusb's default search)."""
try:
import glob
import os
import usb.backend.libusb1 as libusb1
from . import bundle
libdir = os.path.join(bundle.vendor_dir(), "lib")
# macOS dylib or Linux .so, whatever we bundled
for pat in ("libusb-1.0*.dylib", "libusb-1.0.so*", "libusb-1.0*"):
hits = sorted(glob.glob(os.path.join(libdir, pat)))
if hits:
return libusb1.get_backend(find_library=lambda _n, _p=hits[0]: _p)
except Exception:
pass
return None
def _maskrom_count_pyusb():
"""Count devices in Ingenic mask-ROM mode via pyusb. Returns int or None if
pyusb/backend is unavailable."""
try:
import usb.core # pyusb (bundled)
except Exception:
return None
try:
backend = _bundled_libusb_backend() # prefer our bundled libusb
devs = list(usb.core.find(find_all=True, idVendor=MASKROM_VID,
idProduct=MASKROM_PID, backend=backend))
return len(devs)
except Exception:
return None
def _maskrom_count_lsusb():
"""Fallback: parse `lsusb` if present (Linux)."""
import shutil
import subprocess
if not shutil.which("lsusb"):
return None
try:
out = subprocess.run(["lsusb"], capture_output=True, text=True, timeout=10).stdout
except Exception:
return None
return sum(1 for ln in out.splitlines() if "a108:eaef" in ln.lower())
def maskrom_count():
"""How many devices are currently in mask-ROM mode. Prefers pyusb, falls back
to lsusb, returns -1 if neither is available (caller should warn)."""
n = _maskrom_count_pyusb()
if n is not None:
return n
n = _maskrom_count_lsusb()
if n is not None:
return n
return -1
+137
View File
@@ -0,0 +1,137 @@
"""Reporter interface - decouples the engine (imagebuild/flasher/state) from the
front-end. The engine reports FACTS; it never touches widgets or prints directly.
CLIReporter -> renders to the terminal via ui.py
QueueReporter -> enqueues immutable events for the Tk GUI to drain on its main
thread (the engine runs on a worker thread)
Contract:
phase(name, destructive=False) a new stage began
status(message) transient 'what's happening now' line
log(line) detail/log line
progress(completed, total) determinate progress (total > 0)
indeterminate(active, note="") long op with no count (the flash) on/off
warning(message) / ok(message) / error(message)
"""
import threading
from . import ui
class Reporter:
def phase(self, name, destructive=False): ...
def status(self, message): ...
def log(self, line): ...
def progress(self, completed, total): ...
def indeterminate(self, active, note="", expect_secs=None): ...
def warning(self, message): ...
def ok(self, message): ...
def error(self, message): ...
class CLIReporter(Reporter):
"""Terminal renderer - preserves the existing CLI look via ui.py."""
def __init__(self):
self._phase = ""
self._bar = None
self._hb = None
self._hb_stop = None
self._hb_thread = None
def phase(self, name, destructive=False):
self._end_bar()
self._phase = name
ui.step(name + (" (this rewrites the device)" if destructive else ""))
def status(self, message):
self._end_bar()
ui.info(message)
def log(self, line):
ui.info(ui.dim(line))
def progress(self, completed, total):
if not total or total <= 0:
return
if self._bar is None:
self._bar = ui.Bar(self._phase or "working", total)
self._bar.update(completed)
if completed >= total:
self._bar.done()
self._bar = None
def _end_bar(self):
if self._bar is not None:
self._bar.done()
self._bar = None
def indeterminate(self, active, note="", expect_secs=None):
if active:
if self._hb is not None:
return
self._hb = ui.Heartbeat(note or self._phase or "working", expect_secs=expect_secs)
self._hb_stop = threading.Event()
def _run(hb, stop):
while not stop.is_set():
hb.tick()
stop.wait(0.5)
hb.stop()
self._hb_thread = threading.Thread(target=_run, args=(self._hb, self._hb_stop), daemon=True)
self._hb_thread.start()
else:
if self._hb_stop:
self._hb_stop.set()
if self._hb_thread:
self._hb_thread.join(timeout=2)
self._hb = self._hb_stop = self._hb_thread = None
def warning(self, message):
self._end_bar()
ui.warn(message)
def ok(self, message):
self._end_bar()
ui.ok(message)
def error(self, message):
self._end_bar()
ui.err(message)
class QueueReporter(Reporter):
"""Enqueues immutable (kind, payload) events for the GUI to drain via
root.after on the main thread. NEVER touches Tk widgets itself."""
def __init__(self, q):
self.q = q
def _emit(self, kind, **kw):
self.q.put((kind, kw))
def phase(self, name, destructive=False):
self._emit("phase", name=name, destructive=destructive)
def status(self, message):
self._emit("status", message=message)
def log(self, line):
self._emit("log", line=line)
def progress(self, completed, total):
self._emit("progress", completed=completed, total=total)
def indeterminate(self, active, note="", expect_secs=None):
self._emit("indeterminate", active=active, note=note, expect_secs=expect_secs)
def warning(self, message):
self._emit("warning", message=message)
def ok(self, message):
self._emit("ok", message=message)
def error(self, message):
self._emit("error", message=message)
+168
View File
@@ -0,0 +1,168 @@
"""Application service - the install / restore-stock / remove flows, independent
of any front-end. CLI and GUI both call these with a Reporter and a `confirm`
callback, so the two front-ends can never diverge in behaviour or safety checks.
`confirm(summary: dict) -> bool` is the destructive-action gate:
- CLI: a y/N prompt.
- GUI: the CONFIRMATION screen (acknowledge checkbox + explicit button),
driven from the worker thread via a blocking Event.
Each flow returns a result dict; raises BuildError/FlashError on failure.
"""
import os
import time
from . import bundle, flasher, imagebuild, state
def _save_stock(stock_sq, rep):
"""Copy the user's bone-stock image into state (padded to the partition size)
so restore-stock can always reflash exactly it. Returns its sha256."""
rep.status("Saving your stock rootfs image (so diskOS can always be deactivated/reverted)")
sz = os.path.getsize(stock_sq)
if sz > imagebuild.IMG_SIZE:
# NEVER truncate a larger image - a truncated file can still look flashable
# (hsqs magic + right size) yet be a corrupt, unbootable stock.
raise imagebuild.BuildError(
f"stock rootfs is {sz} bytes > {imagebuild.IMG_SIZE} partition - refusing "
"(truncating it would produce a corrupt 'stock' image).", code="E240")
if sz < imagebuild.IMG_SIZE:
padded = stock_sq + ".padded"
imagebuild._copyfile(stock_sq, padded)
with open(padded, "r+b") as f:
f.truncate(imagebuild.IMG_SIZE)
src = padded
else:
src = stock_sq
digest = state.save_stock_image(src, progress=lambda r, t: rep.progress(r, t))
rep.ok(f"bone-stock image saved (sha256={digest[:16]}…)")
return digest
def _save_state_soft(st, rep):
"""Persist state, but NEVER let a bookkeeping failure masquerade as a flash
failure. Call only AFTER a verified flash."""
try:
state.save(st)
except Exception as e: # disk full, permissions, etc.
rep.warning(f"flash succeeded, but saving local history failed: {e}")
def do_install(params, rep, confirm):
"""params: dict(firmware=?, stock=?, ui_binary=?, variant='public'|'dev').
Extract -> save bone-stock -> build -> confirm -> flash. Returns result dict."""
ui_bin = params.get("ui_binary") or bundle.data("mq_ui", required=False)
if not ui_bin or not os.path.exists(ui_bin):
raise imagebuild.BuildError("no diskOS UI binary (bundled 'mq_ui' missing).", code="E102",
action="the install is incomplete; re-download the installer")
variant = params.get("variant", "public")
work = state.build_dir()
st = state.load()
st.update({"phase": "prepared", "variant": variant})
state.save(st)
# 1) obtain the stock rootfs + save it as the restore image
stock_sq = os.path.join(work, "stock_rootfs.squashfs")
if params.get("stock"):
imagebuild._copyfile(params["stock"], stock_sq)
elif params.get("firmware"):
imagebuild.extract_stock_rootfs(params["firmware"], stock_sq, work, rep=rep)
else:
raise imagebuild.BuildError("need a firmware .zip or a stock rootfs.squashfs.", code="E140",
action="pass your official FiiO firmware .zip")
# Validate the stock image is a genuine, supported, known-good Disc rootfs BEFORE it overwrites
# the saved recovery copy - so a wrong/corrupt image can't destroy a good recovery then abort.
imagebuild.validate_stock_rootfs(stock_sq, rep)
_save_stock(stock_sq, rep)
# 2) build the diskOS image
out_bin = os.path.join(work, f"diskos_{variant}.bin")
imagebuild.build_image(stock_sq, ui_bin, variant, out_bin, work, rep=rep)
# 3) preflight + confirm (destructive gate), then flash
flasher.preflight(out_bin, rep)
summary = {
"action": "install",
"variant": variant,
"image": out_bin,
"duration": "~60-90 minutes",
"consequence": "This rewrites the device root filesystem. Do not disconnect.",
}
if not confirm(summary):
rep.warning("aborted before flashing (nothing written to the device).")
return {"ok": False, "aborted": True}
st.update({"phase": "flash-started"})
_save_state_soft(st, rep)
# From here, flash() either raises (real failure) or returns verified. A later
# state-save error must NOT turn a verified flash into a reported failure.
d = flasher.flash(out_bin, log_path=os.path.join(state.state_dir(), "last-flash.log"), rep=rep)
st.update({"phase": "flash-verified", "installed": True,
"installed_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())})
_save_state_soft(st, rep)
rep.ok("diskOS flashed and verified. Power-cycle the device to boot it.")
return {"ok": True, "debug": d}
def do_restore(params, rep, confirm):
"""Reflash the saved stock-rootfs image (deactivates diskOS; leaves /usr/data files). If no image
is saved, a firmware .zip must be provided to rebuild it."""
stock_bin, _ = state.stock_paths()
if not state.have_stock_image():
if not params.get("firmware"):
raise flasher.FlashError(
"no saved bone-stock image", code="E141",
action="provide FiiO's firmware .zip so I can rebuild your stock rootfs image")
work = state.build_dir()
stock_sq = os.path.join(work, "stock_rootfs.squashfs")
imagebuild.extract_stock_rootfs(params["firmware"], stock_sq, work, rep=rep)
imagebuild.validate_stock_rootfs(stock_sq, rep)
_save_stock(stock_sq, rep)
# Never restore-flash an unvalidated image: validate whatever is about to be written (the saved
# copy or the freshly-extracted one) - product/version/known-good-hash, not just size+magic.
imagebuild.validate_stock_rootfs(stock_bin, rep)
flasher.preflight(stock_bin, rep)
summary = {
"action": "restore-stock",
"image": stock_bin,
"duration": "~60-90 minutes",
"consequence": "This reflashes bone-stock and removes diskOS. Do not disconnect.",
}
if not confirm(summary):
rep.warning("aborted (device unchanged).")
return {"ok": False, "aborted": True}
st = state.load()
st.update({"phase": "restore-started"})
_save_state_soft(st, rep)
d = flasher.flash(stock_bin, log_path=os.path.join(state.state_dir(), "last-restore.log"), rep=rep)
st.update({"phase": "restore-verified", "installed": False})
_save_state_soft(st, rep)
rep.ok("Stock system reflashed. Power-cycle to boot stock.")
rep.warning("This deactivates diskOS but is not a byte-for-byte factory wipe: the diskOS "
"files under /usr/data (a separate partition) remain, inert - they do nothing "
"without the boot hook this reflash removed. (The UI embedded in the diskOS "
"rootfs is gone, since this reflash overwrote that partition with stock.)")
return {"ok": True, "debug": d}
def do_remove(params, rep, confirm):
"""Delete everything the tool created on this computer (its full uninstall
footprint). Nothing was installed system-wide, so this is the whole cleanup."""
if state.load().get("installed") and not params.get("force"):
if not confirm({"action": "remove-tool",
"consequence": "diskOS still appears to be on the device. This only "
"removes the installer + its saved files from THIS "
"computer (run restore-stock first to clear the device)."}):
return {"ok": False, "aborted": True}
d, errors = state.wipe_all()
if errors:
rep.error(f"could not fully remove {len(errors)} item(s) under {d}:")
for p, m in errors[:8]:
rep.log(f" {p}: {m}")
return {"ok": False, "errors": errors, "removed": d}
rep.ok(f"removed all tool state: {d}")
return {"ok": True, "removed": d}
+258
View File
@@ -0,0 +1,258 @@
"""Per-user state so the tool can always put the device back to bone-stock and
so `remove` can clean up after itself.
Everything the tool creates lives under ONE directory (state_dir()); nothing is
written system-wide. `remove` deletes that directory (and, if the user asks, the
tool itself) - that's the whole uninstall footprint on Linux/macOS.
Contents:
state.json what we've done (installed?, versions, timestamps)
stock/stock.bin the saved stock-rootfs image, rebuilt from the user's firmware (for restore-stock)
stock/stock.sha256 its checksum
build/ scratch for extract/build (cleaned opportunistically)
"""
import hashlib
import json
import os
import shutil
import sys
import time
from . import errors
APP = "diskos-installer"
# A marker file dropped in our state dir. wipe_all() refuses to recursively delete any directory
# that does not contain it, so a mis-set DISKOS_INSTALLER_HOME can never delete an arbitrary tree.
SENTINEL = ".diskos-installer-state"
# The diskOS install/restore lifecycle values written to state.json["phase"]. Used to recognise a
# legacy (pre-sentinel) state dir by CONTENT, specifically enough that a foreign project's state.json
# cannot masquerade as ours. Keep in sync with service.py.
_KNOWN_PHASES = {"prepared", "flash-started", "flash-verified", "restore-started", "restore-verified"}
def _fsync_dir(path):
"""Fsync a directory so a rename/create inside it is durable across a crash."""
try:
fd = os.open(path, os.O_RDONLY)
try:
os.fsync(fd)
finally:
os.close(fd)
except OSError:
pass
def _state_base():
"""Compute the state-dir PATH only - no directory creation, no side effects.
Used by wipe_all() so validation never re-creates the sentinel it is about to check."""
env = os.environ.get("DISKOS_INSTALLER_HOME")
if env:
return env
if sys.platform == "darwin":
return os.path.expanduser(f"~/Library/Application Support/{APP}")
xdg = os.environ.get("XDG_DATA_HOME")
return os.path.join(xdg, APP) if xdg else os.path.expanduser(f"~/.local/share/{APP}")
def _is_our_statedir(base):
"""STRONG test that `base` is (or was) a diskOS state dir - governs whether we may adopt it and,
in wipe_all(), recursively delete it. Requires GENUINE evidence, never a merely-common basename,
so an unrelated directory that happens to contain a 'build/' or a 'state.json' is NEVER matched:
- our sentinel file, OR
- our exact stock-recovery pair stock/stock.bin + stock/stock.sha256, OR
- a state.json that parses AND matches our specific schema (a boolean `installed` plus a
`phase` drawn from our known lifecycle values) - not merely the generic key NAMES, so an
unrelated project's state.json cannot be mistaken for ours and later deleted."""
if os.path.isfile(os.path.join(base, SENTINEL)):
return True
if (os.path.isfile(os.path.join(base, "stock", "stock.bin"))
and os.path.isfile(os.path.join(base, "stock", "stock.sha256"))):
return True
sj = os.path.join(base, "state.json")
if os.path.isfile(sj):
try:
with open(sj) as f:
d = json.load(f)
if (isinstance(d, dict) and isinstance(d.get("installed"), bool)
and isinstance(d.get("phase"), str) and d.get("phase") in _KNOWN_PHASES):
return True
except (OSError, ValueError, TypeError):
pass
return False
def state_dir():
"""A single, per-user, non-system directory for all tool state (created on first use)."""
base = _state_base()
marker = os.path.join(base, SENTINEL)
# SAFETY, only for an EXPLICITLY-set home: refuse to adopt a pre-existing, non-empty directory
# that shows NO sign of being ours, so a mis-set DISKOS_INSTALLER_HOME (e.g. $HOME) can't be
# tagged here and later wiped by 'remove'. The DEFAULT XDG/APP path is always ours; and an
# existing state dir (even one predating the sentinel) is recognised by its contents.
if (os.environ.get("DISKOS_INSTALLER_HOME") and os.path.isdir(base)
and not _is_our_statedir(base)):
try:
nonempty = bool(os.listdir(base))
except OSError:
nonempty = True
if nonempty:
raise errors.PreflightError(
f"DISKOS_INSTALLER_HOME={base!r} is a non-empty directory that is not a diskOS "
"state dir - refusing to use it. Point it at a new or empty path.", code="E142")
os.makedirs(base, exist_ok=True)
if not os.path.exists(marker):
try:
with open(marker, "w") as f:
f.write("diskOS installer state directory - safe to delete via 'diskos-installer remove'\n")
except OSError:
pass
return base
def _state_path():
return os.path.join(state_dir(), "state.json")
def load():
"""Return the saved state. A corrupt file is reported (not silently erased) so
'never installed' and 'state damaged' stay distinguishable."""
p = _state_path()
if not os.path.exists(p):
return {}
try:
with open(p) as f:
return json.load(f)
except ValueError:
return {"_corrupt": True}
except OSError:
return {}
def save(d):
d = {k: v for k, v in d.items() if k != "_corrupt"}
d["updated"] = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
tmp = _state_path() + ".tmp"
with open(tmp, "w") as f:
json.dump(d, f, indent=2)
f.flush()
os.fsync(f.fileno())
os.replace(tmp, _state_path())
_fsync_dir(state_dir())
def sha256_file(path, progress=None):
h = hashlib.sha256()
total = os.path.getsize(path)
read = 0
with open(path, "rb") as f:
while True:
chunk = f.read(1 << 20)
if not chunk:
break
h.update(chunk)
read += len(chunk)
if progress:
progress(read, total)
return h.hexdigest()
def stock_paths():
d = os.path.join(state_dir(), "stock")
os.makedirs(d, exist_ok=True)
return os.path.join(d, "stock.bin"), os.path.join(d, "stock.sha256")
def save_stock_image(src_bin, progress=None):
"""Copy the saved stock-rootfs flashable image into state so restore-stock can
always reflash exactly it. Atomic + validated: the previous good image is only
replaced once the new one is fully written, hashed, magic-checked, and fsynced -
so a crash/disk-full can't destroy your recovery image. Returns its sha256."""
dst, shafile = stock_paths()
d = os.path.dirname(dst)
tmp_bin, tmp_sha = dst + ".tmp", shafile + ".tmp"
h = hashlib.sha256()
total = os.path.getsize(src_bin)
read = 0
with open(src_bin, "rb") as s, open(tmp_bin, "wb") as o:
while True:
chunk = s.read(1 << 20)
if not chunk:
break
o.write(chunk)
h.update(chunk)
read += len(chunk)
if progress:
progress(read, total)
o.flush()
os.fsync(o.fileno())
digest = h.hexdigest()
# validate BEFORE committing (never publish a truncated/non-squashfs image)
with open(tmp_bin, "rb") as f:
if f.read(4) != b"hsqs":
os.unlink(tmp_bin)
raise ValueError("refusing to save a non-squashfs stock image (bad magic).")
with open(tmp_sha, "w") as f:
f.write(digest + "\n")
f.flush()
os.fsync(f.fileno())
# commit: rename sha first, then the image, then fsync the dir. If interrupted
# between renames, have_stock_image() sees a mismatch and reports 'no valid image'
# rather than trusting a half-committed pair.
os.replace(tmp_sha, shafile)
os.replace(tmp_bin, dst)
_fsync_dir(d)
return digest
def stock_image_exists():
"""Fast existence check (no hashing) - safe to call on the UI thread."""
dst, shafile = stock_paths()
return os.path.exists(dst) and os.path.exists(shafile)
def have_stock_image():
dst, shafile = stock_paths()
try:
if not (os.path.exists(dst) and os.path.exists(shafile)):
return False
want = open(shafile).read().strip()
return sha256_file(dst) == want
except OSError:
return False
def build_dir():
d = os.path.join(state_dir(), "build")
os.makedirs(d, exist_ok=True)
return d
def wipe_all():
"""Delete the entire tool state directory (the full uninstall footprint).
Returns (path, errors): errors is a list of (path, message) for anything that
could NOT be removed, so the caller reports the truth instead of a false success."""
d = _state_base() # PATH only - never re-create the sentinel we are about to verify
errs = []
# SAFETY: only ever recursively delete a directory we can PROVE is our own state dir. This
# guards against DISKOS_INSTALLER_HOME being set to '/', '$HOME', the cwd, or any other tree.
real = os.path.realpath(d)
forbidden = {os.path.realpath(os.sep), os.path.realpath(os.path.expanduser("~"))}
try:
forbidden.add(os.path.realpath(os.getcwd()))
except OSError:
pass
if real in forbidden:
return d, [(d, "refusing to delete a root/home/current directory")]
if not (os.path.isdir(d) and _is_our_statedir(d)):
return d, [(d, "not a diskOS state dir (no sentinel or known state) - refusing to delete")]
try:
if os.stat(d).st_uid != os.getuid():
return d, [(d, "state dir is not owned by you - refusing to delete")]
except OSError as e:
return d, [(d, str(e))]
shutil.rmtree(d, onerror=lambda fn, path, exc: errs.append((path, str(exc[1]))))
return d, errs
+153
View File
@@ -0,0 +1,153 @@
"""Terminal progress + messaging. TTY-aware: renders live bars/spinners on a
terminal, and degrades to plain timestamped log lines when piped to a file so a
saved log stays readable."""
import sys
import time
# --- colour (only on a TTY that isn't dumb) ---------------------------------
_TTY = sys.stdout.isatty()
def _c(code, s):
return f"\033[{code}m{s}\033[0m" if _TTY else s
def bold(s): return _c("1", s)
def dim(s): return _c("2", s)
def red(s): return _c("31", s)
def green(s): return _c("32", s)
def yellow(s): return _c("33", s)
def cyan(s): return _c("36", s)
def _t():
return time.strftime("%H:%M:%S")
def info(msg):
print(f"{dim(_t())} {msg}", flush=True)
def step(msg):
print(f"\n{cyan('▶')} {bold(msg)}", flush=True)
def ok(msg):
print(f"{green('✓')} {msg}", flush=True)
def warn(msg):
print(f"{yellow('!')} {msg}", flush=True)
def err(msg):
print(f"{red('✗')} {msg}", file=sys.stderr, flush=True)
def fmt_dur(secs):
secs = int(secs)
h, rem = divmod(secs, 3600)
m, s = divmod(rem, 60)
if h:
return f"{h}h{m:02d}m{s:02d}s"
if m:
return f"{m}m{s:02d}s"
return f"{s}s"
class Bar:
"""A determinate progress bar for steps with a known total (0..total)."""
def __init__(self, label, total, width=28):
self.label = label
self.total = max(1, total)
self.width = width
self.start = time.monotonic()
self.last_len = 0
self.update(0)
def update(self, done, note=""):
frac = min(1.0, done / self.total)
elapsed = time.monotonic() - self.start
eta = (elapsed / frac - elapsed) if frac > 0.02 else 0
if _TTY:
fill = int(self.width * frac)
bar = "█" * fill + "·" * (self.width - fill)
line = (f"\r {self.label} {cyan(bar)} {int(frac*100):3d}%"
f" {dim(fmt_dur(elapsed))}"
+ (f" · ETA {fmt_dur(eta)}" if eta > 0 else "")
+ (f" {note}" if note else ""))
pad = max(0, self.last_len - len(line))
sys.stdout.write(line + " " * pad)
sys.stdout.flush()
self.last_len = len(line)
else:
# non-TTY: emit occasional milestone lines, not a live bar
pct = int(frac * 100)
if pct in (0, 25, 50, 75, 100) and pct != getattr(self, "_last_pct", -1):
self._last_pct = pct
print(f" {self.label}: {pct}% ({fmt_dur(elapsed)}){(' ' + note) if note else ''}",
flush=True)
def done(self, note=""):
self.update(self.total, note)
if _TTY:
sys.stdout.write("\n")
sys.stdout.flush()
class Heartbeat:
"""Indeterminate progress for a long step with no reliable progress channel
(the ~60-90 min mask-ROM flash). Shows elapsed time + a spinner and a fixed
'do not disconnect' reminder. Call tick() periodically; stop() to finish."""
FRAMES = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
def __init__(self, label, expect_secs=None, reminder="do NOT disconnect the device"):
self.label = label
self.expect = expect_secs
self.reminder = reminder
self.start = time.monotonic()
self.i = 0
self.last_len = 0
def tick(self, note=""):
elapsed = time.monotonic() - self.start
self.i = (self.i + 1) % len(self.FRAMES)
if _TTY:
spin = self.FRAMES[self.i]
approx = ""
if self.expect:
approx = f" / ~{fmt_dur(self.expect)}"
line = (f"\r {cyan(spin)} {self.label} {dim(fmt_dur(elapsed) + approx)}"
f" {yellow('· ' + self.reminder)}"
+ (f" {note}" if note else ""))
pad = max(0, self.last_len - len(line))
sys.stdout.write(line + " " * pad)
sys.stdout.flush()
self.last_len = len(line)
else:
# non-TTY: a line every ~30s so a log shows liveness without spamming
if int(elapsed) % 30 == 0 and int(elapsed) != getattr(self, "_last_log", -1):
self._last_log = int(elapsed)
print(f" {self.label}: {fmt_dur(elapsed)} elapsed ({self.reminder})", flush=True)
def stop(self):
if _TTY:
sys.stdout.write("\n")
sys.stdout.flush()
def confirm(prompt, default=False):
"""Yes/no prompt. Non-interactive stdin -> returns default (never blocks a pipe)."""
if not sys.stdin.isatty():
return default
d = "Y/n" if default else "y/N"
try:
ans = input(f"{yellow('?')} {prompt} [{d}] ").strip().lower()
except EOFError:
return default
if not ans:
return default
return ans in ("y", "yes")
+257
View File
@@ -0,0 +1,257 @@
# Snowsky Disc V2.09 - mq_player full command map
Dispatch entry = `{tag_str_ptr, handler_thunk_ptr}` (8B); thunks tail-jump via GOT to the real handler.
Confidence: **V**=string-verified · **I**=inferred from family · **U**=unknown (runtime-registered, GOT slot 0).
⚠ = static reading conflicts with our 1.95-era LIVE tests (trust live; V2.09 meanings need live re-verify).
## SOURCE / WORK-MODE SWITCH - 0657 (corrected; supersedes "close player" reading)
`0657` = switch audio SOURCE, payload = integer mode index (jump table @0x6736b0). Frame = `0657000C000<hex>`:
- `0657000C0001` = **LOCALPLAYER** (safe recover) · `0657000C0009` = **USB-DAC (UAC)** · `0657000C000C` = **BTSINK**
- **Network receivers (AirPlay/DLNA/Roon):** `0657000C0008` PLUS companion `0642000C000X` (NETWORK_MODE selector, X in {0,1,2,5}; exact AirPlay value UNMAPPED). Prereq: WLAN up.
- ✅ **PRE-STOP PINNED + CONFIRMED (2026-08-03, live strace of stock mq_ui + fixed on device):** the pre-stop is **`0666000C0006`** (out_dev=6, local). Stock always sends it BEFORE `0666000C0002` (route to BT). Skipping it = the **g_fiio_local trap** → mq_player SIGSEGV → SD freed → MCU reboot. Mechanism: direct→2 can leave shadow-out=2 with DAC-flag=1 (split state); 6→2 normalizes DAC-flag=0. **This was THE cause of every BT-route reboot.** See "BT AUDIO OUTPUT" section below.
- ⚠ AirPlay discovery CANNOT be tested on an iPhone Personal Hotspot (client/mDNS isolation) - needs a normal router. PARKED pending router + 0666 pre-stop.
NB: this 0657 is the V2.09 SOURCE switch; the 1.95 "0657=play-mode" was a different binary/table. Our earlier play-mode toggle using 0657 on V2.09 was therefore WRONG (it sent source-switch values) - FIXED 2026-06-25 (now uses 0102, below).
## PLAY-MODE - 0102 (GROUND TRUTH, captured from stock UI 2026-06-25)
`0102` = LOCAL play-mode setter. Frame = `0102000C000<v>`. Captured by strace'ing the stock
`/usr/bin/mq_ui`'s `mq_timedsend` while tapping its play-mode control (the loop icon, NP
transport page) - the stock UI cycles these 5 values 0→1→2→3→4→0:
| value | frame | stock icon | mode |
|---|---|---|---|
| 0 | `0102000C0000` | →→ (two arrows) | Sequential (play in order) |
| 1 | `0102000C0001` | ⇄ (crossed) | Shuffle (random) |
| 2 | `0102000C0002` | ↻ with "1" | Repeat One (single loop) |
| 3 | `0102000C0003` | ↻ (loop) | Repeat All (list loop) |
| 4 | `0102000C0004` | "1" + arrow | Single (play one track, stop) |
NB: this SUPERSEDES the old "0102 = Roon-only no-op" reading - stock uses 0102 for LOCAL
play-mode live. diskOS sends this via ui_set_workmode (main.c). The cycle order above is
the stock order; diskOS's prior 4-mode icons (seq/shuffle/repeat-one/repeat-all) already
match values 0-3.
## LIVE-tested (ground truth)
| tag | meaning |
|---|---|
| 0100 | Play by list (list_type + start index) ✅ |
| 0102 | **Play-mode** 0102000C000<0..4> (seq/shuffle/rep-one/rep-all/single) ✅ stock-captured 2026-06-25 |
| 0103 | Seek (ms) ✅ verified live 2026-06-25 (pos jumped to target) |
| 0104 | Favorite toggle (current song) |
| 0201 | Transport play/pause toggle (generic, VALUE1-driven) - verified NOT Roon-specific |
| 0622 | Rescan SD / rebuild DB |
| 0657 | **SOURCE switch** (NOT play-mode) - see section above |
| 0666 | Output route (→set_out_device 0x461e74): 2=BTSRC 4=SPDIF 6=local-DAC. V2.09-confirmed; the "close_player" sighting was a shared teardown preamble, not this cmd's meaning. |
| 0715 | Volume absolute 0-120 ✅ verified 2026-06-25 (set 20 via 0715000C0014, persisted+displayed) |
## BT AUDIO OUTPUT (transmit to a BT speaker, a2dp-source) - ✅ WORKING (2026-08-03)
Captured from a live strace of stock mq_ui doing a working transmit, then replicated + fixed in diskOS `ui_route_bt()`. **Plays stereo, no stutter, no reboot.** The device IS designed to transmit (not only the "Bluetooth Receiving Mode"/a2dp-sink); stock transmit works but STUTTERS because its default-quality stereo SBC exceeds the X2000 CPU.
Working route-to-BT sequence (diskOS, MAC = the connected speaker, uppercased):
```
0666000C0006 PRE-STOP: switch output to LOCAL first (MANDATORY - skip = g_fiio_local crash → MCU reboot)
0642000C0000 reset network/output mode
0657000C0008 work-mode 8
06c1000C0000 start player BT-init thread (06b3 no-ops until this completes; async on cold start)
0666000C0002 route: out_dev = BT source
0657000C0008 work-mode 8 (again, as stock does)
06b3001D0000<MAC> codec select: 0=SBC (our bluealsa is sbc-only) + MAC payload (stock frame-shape; worker ignores it)
0715000C<vol> volume
```
Then play normally (`0100…`). Reverse (BT→local) = `ui_route_analog()`: `0666000C0006` then `0657000C0008`.
**No-stutter requires bluealsa `--sbc-quality=medium`** (bit-pool ~33): stock default-quality stutters; medium plays clean stereo (~86% CPU idle on device). Set in `bt.c` bt_enable/bt_ensure_services. `--a2dp-force-mono` also works but is NOT needed (stereo is fine at medium quality).
## Table A @0x7c9d30 - 131 entries (terminator 0x7ca148)
| tag | thunk | meaning | conf |
|---|---|---|---|
| 0802 | 0x411790 | get total song count (SELECT count(*) FROM SONG) | V |
| 0620 | 0x4117b0 | get WIFI MAC (/usr/data/fiio/nb.txt) | V |
| 0710 | 0x4117d0 | network/wifi getter | I |
| 0711 | 0x4117f0 | network/wifi getter | I |
| 0712 | 0x411810 | network/wifi op | I |
| 0713 | 0x411830 | network/wifi op | I |
| 0714 | 0x411850 | network/wifi op | I |
| 0715 | 0x411870 | network/wifi op (NB: vs live 0715=volume - table-A 0715 differs) | I |
| 0716 | 0x411890 | network/wifi op | U |
| 0601 | 0x4118b0 | media getter | U |
| 0651 | 0x4118d0 | media getter/setter | U |
| 0602 | 0x4118f0 | media getter | U |
| 0652 | 0x411910 | media getter/setter | U |
| 0606 | 0x411930 | media DB getter | I |
| 0656 | 0x411950 | media DB getter/setter | I |
| 0603 | 0x411970 | media DB getter | I |
| 0653 | 0x411990 | media DB getter/setter | I |
| 0604 | 0x4119b0 | media DB getter | I |
| 0654 | 0x4119d0 | media DB getter/setter | I |
| 0605 | 0x4119f0 | media query -> reply ([PLAY] send) | V |
| 0655 | 0x411a10 | media DB getter/setter | I |
| 0608 | 0x411a30 | media DB getter | I |
| 0658 | 0x411a50 | media DB getter/setter | I |
| 0611 | 0x411a70 | media DB getter | I |
| 0661 | 0x411a90 | media DB getter/setter | I |
| 0612 | 0x411ab0 | media DB getter | I |
| 0662 | 0x411ad0 | media DB getter/setter | I |
| 0613 | 0x411af0 | media DB getter | I |
| 0663 | 0x411b10 | media DB getter/setter | I |
| 0609 | 0x411b30 | media DB getter | I |
| 0659 | 0x411b50 | media DB getter/setter | I |
| 0615 | 0x411b70 | media DB getter | I |
| 0665 | 0x411b90 | media DB getter/setter | I |
| 0614 | 0x411bb0 | media DB getter | I |
| 0664 | 0x411bd0 | media DB getter/setter | I |
| 0607 | 0x411bf0 | media query -> reply ([PLAY] send) | V |
| 0657 | 0x411c10 | reads "close_player"/killall avahi-publish (⚠ 1.95=play-mode) | V⚠ |
| 0801 | 0x411c30 | playback/system getter | I |
| 0702 | 0x411c50 | wifi/network getter | I |
| 0703 | 0x411c70 | wifi/network getter | I |
| 0704 | 0x411c90 | get wifi scan list | V |
| 0705 | 0x411cb0 | connect wifi (psid/passwd) / SET_POWER_DOWN_TO_MCU | V |
| 0706 | 0x411cd0 | wifi/network op | I |
| 0707 | 0x411cf0 | wifi/network op | U |
| 0708 | 0x411cf0 | wifi/network op | U |
| 0639 | 0x411d30 | media-info query -> reply a639 | V |
| 0689 | 0x411d50 | **EQ PRESET SELECT** - invokes 21-way preset engine 0x449544 (via 0x4961bc), updates rate caps, replies a639. NOT a media-info query. | V |
| 0690 | 0x411d70 | media-info query -> play-send | V |
| 0675 | 0x411d90 | get EQ/PEQ (gain/filterType/frequency/loading) | V |
| 0626 | 0x411db0 | EQ getter (family) | I |
| 0627 | 0x411dd0 | EQ getter | I |
| 0677 | 0x411df0 | EQ getter/setter | I |
| 0628 | 0x411e10 | EQ getter/setter (PEQ) | I |
| 0678 | 0x411e30 | SET PEQ band (filterType/frequency/gain/qValue) | V |
| 0629 | 0x411e50 | EQ getter/setter | I |
| 0630 | 0x411e70 | get EQ (gain/filterType/frequency/loading) | V |
| 0803 | 0x411e90 | playback/system getter | I |
| 0724 | 0x411eb0 | system/OTA op | I |
| 0720 | 0x411ed0 | OTA/network (killall wget, ip route, wlan0) | V |
| 0624 | 0x411ef0 | mount/storage path (mnt/) | V |
| 0622 | 0x411f10 | system getter (NB: live 0622=rescan; table-A differs) | I |
| 0800 | 0x411f30 | write wpa_supplicant.conf (country=%s) | V |
| 0623 | 0x411f50 | system getter | I |
| 0616 | 0x411f70 | media/system getter | I |
| 0a51 | 0x411f90 | extended command (only 0aXX tag) | I |
| 0634 | 0x411fb0 | media-info query -> play-send | V |
| 0684 | 0x411fd0 | media getter | I |
| 0725 | 0x411ff0 | system/OTA op | I |
| 0617 | 0x412010 | media/system getter | I |
| 0667 | 0x412030 | media getter/setter | I |
| 0621 | 0x412050 | DROP DB tables (SONG/MY_LOVE/PLAY_LIST) | V |
| 06a0 | 0x412070 | BT/media getter | I |
| 06a1 | 0x412090 | BT/media getter | I |
| 06a3 | 0x4120b0 | BT/media getter | I |
| 0640 | 0x4120d0 | media getter/setter | I |
| 0644 | 0x4120f0 | media getter/setter | I |
| 0643 | 0x412110 | media op | U |
| 06a2 | 0x412130 | BT/media getter | I |
| 06b1 | 0x412150 | BT sample-rate param (→0x496ac4→change_rate_set_params 0x40d4d8; VALUE1 selects 44100/48000/82000?/96000) | V |
| 06b2 | 0x412170 | BT bit-depth param (→0x496b58→change_format_set_param 0x40d66c; 16/24/32-bit) | V |
| 06b3 | 0x412190 | **BT CODEC SELECT** (→0x496bb8→worker 0x40eaf4): VALUE1 0=SBC 1=AAC 2=LDAC-mob 3=LDAC-std 4=LDAC-high. Stock's connect callback sends `06b3<len>000X<MAC>` (X=persisted BT_CODEC, MAC as ignored-by-worker payload for frame-shape). **diskOS sends `06b3001D0000<MAC>` (X=0 SBC, our bluealsa is `--codec=sbc` only) - value 3 only "works" on an SBC sink via a fragile `/usr/data/bt_codec` fallback, so pick the codec our bluealsa actually enables.** Worker requires `06c1` BT-init done first (else no-ops). | V (live) |
| 06b4 | 0x4121b0 | LDAC **quality** only (→0x496c94→0x40dbe8 via /usr/data/bt_pipe_recv): VALUE1 0=mobile 1=standard 2=high. Does NOT select SBC or set rate. | V |
| 06b6 | 0x4121d0 | BT op | I |
| 06b7 | 0x4121f0 | BT get paired addr+name | V |
| 06b8 | 0x412210 | BT send connected device list | V |
| 06c3 | 0x412230 | BT op | I |
| 06c2 | 0x412250 | BT op | I |
| 06c0 | 0x412270 | BT trust/power (trust/power off/hci down) | V |
| 06c4 | 0x412290 | BT disconnect/remove (bluetooth.db) | V |
| 06c5 | 0x4122b0 | BT op | I |
| 06c1 | 0x4122d0 | BT set device alias | V |
| 0679 | 0x4122f0 | media getter/setter | I |
| 0666 | 0x412310 | reads close_player (⚠ 1.95=output route) | V⚠ |
| 06b5 | 0x412330 | BT op | I |
| 0804 | 0x412350 | playback/system getter | I |
| 0805 | 0x412370 | playback/system op | U |
| 0701 | 0x412390 | wifi init/restart (init_wifi; killall udhcpc/wpa) | V |
| 0700 | 0x4123b0 | close network card (network.c) | V |
| 0808 | 0x4123d0 | playback/system getter | I |
| 0813 | 0x4123f0 | playback/system getter | I |
| 0816 | 0x412410 | playback/system getter | I |
| 0818 | 0x412430 | playback/system getter | I |
| 0817 | 0x412450 | playback/system getter | I |
| 0811 | 0x412470 | playback/system getter | I |
| 0809 | 0x412490 | playback/system getter | I |
| 0815 | 0x4124b0 | set MEMORY_PLAY position (UPDATE ... POSITION) | V |
| 0810 | 0x4124d0 | playback/system getter/setter | I |
| 0812 | 0x4124f0 | playback/system getter/setter | I |
| 0806 | 0x412510 | playback/system getter | I |
| 0645 | 0x412530 | media getter/setter | I |
| 0646 | 0x412550 | media getter/setter | I |
| 0807 | 0x412570 | playback/system getter | I |
| 0660 | 0x412590 | media op | U |
| 0610 | 0x4125b0 | media op | U |
| 0687 | 0x4125d0 | media getter | I |
| 0637 | 0x4125f0 | media op | U |
| 0814 | 0x412610 | playback/system getter/setter | I |
| 0642 | 0x412630 | media getter/setter | I |
| 0641 | 0x412650 | media-info query -> play-send | V |
| 0618 | 0x412670 | media op | U |
| 0668 | 0x412690 | media op | U |
| 0619 | 0x4126b0 | media op | U |
| 0669 | 0x4126d0 | media op | U |
| 0722 | 0x412710 | OTA update (wget ota_patch_user.json) | V |
| 0820 | 0x412730 | set key SINGLE-click action | V |
| 0821 | 0x412750 | set key DOUBLE-click action | V |
| 0822 | 0x412770 | set key LONG-press action | V |
| 06b9 | 0x4126f0 | BT op | U |
| 0647 | 0x412790 | set gapless | V |
| 0648 | 0x4127b0 | set artist_class_type | V |
| 0649 | 0x4127d0 | system-config op | U |
## Table B @0x7ca150 - 75 entries (terminator 0x7ca3a8); many NULL=unimplemented
| tag | handler | meaning | conf |
|---|---|---|---|
| 0425 0435 0445 | NULL | unimplemented | V |
| 0501 | 0x4130f0 | media/thumb type (png/gif/mp4) -> a501/a60a | I |
| 0105 | 0x413110 | emits a102 (status/ack) | I |
| 0202 | 0x413130 | NAS getter/setter | I |
| 0599 | 0x413150 | system/version (-> a599) | I |
| 0401 | 0x413170 | boolean setter -> a401 | I |
| 0411 0450 0451 0452 0453 | NULL | unimplemented (04xx settings) | V |
| 0402 | 0x413190 | boolean setter -> a402 | I |
| 0416 0460 0461 0462 | NULL | unimplemented | V |
| 0403 | 0x4131b0 | boolean setter -> a403 | I |
| 0410 0470 0471 0473 0474 | NULL | unimplemented | V |
| 0404 | 0x4131d0 | setter -> a404 | I |
| 0417 0480 0481 0482 | NULL | unimplemented | V |
| 0405 0418 0419 0420 0421 0422 | NULL | unimplemented (replies declared) | V |
| 0406 | 0x4131f0 | setter -> a406 | I |
| 0426 0407 | NULL | unimplemented | V |
| 0502 | 0x413210 | 05xx misc -> a502 | I |
| 0201 | 0x413230 | Transport play/pause toggle (generic, VALUE1-driven → 0x419ff4) - verified NOT Roon-specific | V |
| 0102 | 0x413250 | playback control (transport) | I |
| 0104 | 0x413270 | playback control (72-byte frame; live: favorite) | I |
| 0111 | 0x413290 (GOT0) | unimplemented stub | V |
| 0112 | 0x4132b0 | playlist: add song (playlist idx, song_path) | V |
| 0115 | 0x4132d0 | add to custom list | V |
| 0113 | 0x4132f0 | love-list delete | V |
| 0114 | 0x413310 | custom-list delete | V |
| 0116 | 0x413330 | playlist op (list mutation) | I |
| 0203 | 0x413350 | NAS op (shares worker w/0412) | I |
| 0412 | 0x413370 | -> reply a412 | I |
| 0413 | 0x413390 | album query (unknown_album) -> a413 | V |
| 0414 | 0x4133b0 | style/genre query (unknown_style) -> a414 | V |
| 0415 | 0x4133d0 | query w/ strcmp -> a415 | I |
| 0465 | 0x4133f0 | -> a465 | I |
| 0495 0496 0497 0498 | NULL | unimplemented | V |
| 0408 | 0x413410 | file/folder browse (mnt/, path build) -> a408 | V |
| 0490 0491 0409 | NULL | unimplemented | V |
| 0117 | 0x413490 | playlist reorder/move (src_list/dst_list) | V |
| 0463 0464 0483 0484 | GOT0 | unimplemented stubs | V |
| 0210 | 0x4134b0 (GOT0) | NAS stub | V |
| 0211 | 0x4134d0 (GOT0) | NAS (json_data, /tmp/nas/) stub | V |
| 0212 0213 0214 | GOT0 | NAS folder op stubs | V |
| 0103 | 0x413430 | song-info/get op | I |
| 0100 | 0x413450 | MAIN PLAY (jumptable @0x650e2c by list_type; unknown_artist) | V |
| 0101 | 0x413470 (GOT0) | unimplemented stub (a101 declared) | V |
## MCU / SPI name-commands (hw_ctrl.c @0x48d0b8, over internal SPI to MCU)
GET_FIRMWARE_VERSION · GET/SET_DEVICE_MAX_VOL · GET/SET_BALANCED_VOL · REPORT/READ_DEVICE_VOL · SET_DEVICE_VOL ·
REPORT_LCD_ACTION · GET/SET_INPUT_MODE · SET_OUTPUT_MODE · SET_GAIN · GET/SET_DAC_FILTER · SET_USB_MODE ·
GET/SET_EQ_PRE · GET/SET_EQ_PARAMETER · SET_EQ_RESET · SAVE_EQ/RESAVE_EQ · SET/REPORT_AUDIO_FORMAT ·
MCU/ARM_REPORT_STATUS · SET_FACTORY · ENTER_MCU_UPDATE_MODE/REPORT_UPDATE_STATUS ·
GET/SET_ZERO_DATA_DETECT_TIME + ZERO_DATA_STATUS · SET_MCU_POWER · SET_MUTE ·
SET_STATUS_TO_MCU/SET_POWER_DOWN_TO_MCU (shutdown, 63 call sites) · BT_REPORT_RATE/STATE/CODEC_TO_MCU
## sysconfig-key setters (system_c... @0x488000)
RGB_COLOUR · TRIGGER_IN · SYS_THEME · LANGUAGE · USB_MODE · NETWORK_MODE · EQ_TYPE · MAX_VOL · BALANCE_VOL ·
POWER_SAVE · FILTER_TYPE · PLAY_MODE · FOLDER_JUMP · PLAY_GAP · INPUT_MODE · VOL_KNOB_MODE · OTA_CFG ·
PO_PRE_VOL · PO_VOL · PRE_VOL · TREBLE · BASS · LO_DISABLE · OS_MODE · DSD_DECODE
## Reply frames
~102 `axxx` player->UI frames. Known: a639=media-info, a706=net status, a714=volume, aa1b=UAC srate, a644=now-playing JSON, a704/a705=wifi status, a6c*=BT. Most undocumented.
+298
View File
@@ -0,0 +1,298 @@
# Snowsky Disc - Hardware Capability Map
Live-probed from the device root shell (serial `/dev/ttyACM0`) on 2026-06-25, while
running **stock firmware** (V2.09 family, kernel built 2026-06-03). This documents what
the *hardware* can do, independent of what stock software chooses to use - to scope
diskOS enhancements and the "write our own mq_player/mq_ui" question.
Probing was read-only (`/proc`, `/sys`, `aplay --dump-hw-params`, `i2cdetect`-equivalent
via sysfs names, `dmesg`). Nothing was written to the device during this survey.
---
## 1. SoC & Compute
| Item | Value | Source |
|---|---|---|
| SoC | Ingenic **X2000** (xburst2), board `ingenic,x2000_halley5_module_base` | `/proc/cpuinfo` |
| Cores | **2× XBurst II V2**, SMP | `/proc/cpuinfo` (processor 0,1) |
| Clock | ~1.2 GHz (BogoMIPS ≈ 2390) | `/proc/cpuinfo` |
| FPU | Yes (per-core) | `/proc/cpuinfo` |
| SIMD | **MSA** (MIPS SIMD Architecture, 128-bit) - `ASEs implemented: msa` | `/proc/cpuinfo` |
| ISA | mips1 / mips2 / mips32r2 + MSA | `/proc/cpuinfo` |
| TLB | 288 entries; 1 HW watchpoint; 6 kscratch regs | `/proc/cpuinfo` |
| DVFS | **None exposed** - no `cpufreq/scaling_available_frequencies` | `/sys/.../cpufreq` |
| Thermal | **No thermal zones** - `/sys/class/thermal` empty | sysfs |
| GPU | **None** (X2000 has no GPU) | `/dev` has no gpu node |
| VPU / video decode | **None** - no `vpu`/`video`/`mem2mem` dev nodes | `/dev` |
| Hardware JPEG | **None** as a dev node (stock `jpg_to_png.c` is software) | `/dev`, RE |
**Implication:** all audio DSP and all UI rendering are CPU-bound. The single biggest
untapped compute lever is **MSA SIMD** - diskOS's LVGL is almost certainly built without
`-mmsa`, so blends/scales/rotations run scalar. Rebuilding LVGL (and any DSP/resampler)
with MSA is the highest-leverage perf win available.
---
## 2. Memory
| Item | Value |
|---|---|
| RAM total | **120 MB** (`MemTotal: 120308 kB`) |
| Free / available (stock running) | ~19 MB free / ~64 MB available |
Tight but workable. diskOS already runs in this budget. Big in-RAM buffers (e.g. a
full-res rotating album-art layer) must be sized carefully.
---
## 3. Storage
NAND (MTD) with **A/B dual-boot** for OTA, plus the user microSD:
| mtd | size | name | notes |
|---|---|---|---|
| mtd0 | 2 MB | uboot | bootloader |
| mtd1 | 8 MB | kernel | slot A |
| mtd2 | 128 MB | rootfs | slot A - **squashfs, read-only** (why `fiio_init.sh` can't be edited in place) |
| mtd3 | 8 MB | kernel2 | slot B |
| mtd4 | 25 MB | rootfs2 | slot B (smaller - recovery/fallback) |
| mtd5 | 1 MB | ota | OTA state |
| mtd6 | 1 MB | mac | MAC/calibration |
| mtd7 | 83 MB | **userdata** | writable - mounted as `/usr/data`, where **diskOS lives** |
| mmcblk0 | ~238 GB | microSD | single partition `mmcblk0p1` - the music card |
**Implication:** the **boot hook** is a small edit patched into the read-only rootfs's
`usr/project/fiio_init.sh` (which is why enabling it requires rewriting the rootfs partition - the
flash). The **payload it launches** - the `mq_ui` binary and diskOS's runtime state - lives in the
writable `/usr/data` (mtd7), the safe persistent target. So: the hook is baked into the RO rootfs;
only the UI/state are on `/usr/data`.
---
## 4. Audio - the headline subsystem
### 4.1 DACs - quad CS43131, fully balanced
Four Cirrus **CS43131** chips on I²C bus 3:
| I²C addr | sysfs name | /dev node (major) |
|---|---|---|
| 3-0030 | cs43131 | `/dev/cs43131` (248) |
| 3-0031 | cs43131b | `/dev/cs43131b` (247) |
| 3-0032 | cs43131c | `/dev/cs43131c` (246) |
| 3-0033 | cs43131d | `/dev/cs43131d` (245) |
dmesg tags include `cs43131_left_negetive` and `cs43131b_open` → the four DACs are wired
as **L+/L−/R+/R− (fully differential / balanced)**, two CS43131 per channel. This is an
unusually serious analog design for the form factor. *(Whether the physical jack exposes
balanced (4.4 mm) or sums to single-ended (3.5 mm) is a board question - confirm against
the unit's connectors.)*
Each CS43131 is a stereo DAC + integrated headphone amp; the family supports PCM to
384 kHz and **DSD64/128/256**. Control is via a **custom FiiO `cs43131` kernel driver**
exposing the four char devices above; stock `mq_player` drives them with **ioctl** (not
ALSA controls). Raw `/dev/i2c-3` is also present as a fallback.
### 4.2 SoC I²S/DMA path - the streaming ceiling
The Ingenic audio controller (ALSA card 0 `x2000`) exposes **5 playback + 5 capture DMA
channels** (`hw:0,0`-`hw:0,4` playback). `aplay --dump-hw-params` on an idle channel:
```
FORMAT: ALL
SAMPLE_BITS: [3 64]
CHANNELS: [1 8]
RATE: [8000 768000]
```
So the **kernel/I²S link can stream up to 768 kHz / 64-bit / 8-channel** - far beyond the
current track (S32_LE / 48 kHz / 2ch on DMA3). The real output ceiling is set by the
CS43131 (~384 kHz PCM, DSD256), not the SoC.
### 4.3 ALSA mixer surface
`amixer controls` shows only the **SoC internal codec** (`ICODEC HPOUTL/MIC GAIN`,
`MICBIAS`), digital mic (`DMIC ...`), line-out muxes (`LO0_MUX`…`LO11_MUX`), and the five
audio-interface formatters (`baic0_fmt`…`baic4_fmt`). There is **no CS43131 control, no
DSD switch, and no digital-filter control in ALSA** - all of that is the kernel driver +
mq_player ioctl path. `BAIC: baic start/stop` in dmesg marks I²S on/off per track.
### 4.4 Decode & format support (from mq_player RE)
- Decoder backend: **libavcodec.so.58 (ffmpeg)** - string `decoder_ffmpeg`.
- DSD: `DSD_MODE_NONE` / `DSD_MODE_NATIVE` / `DSD_MODE_DOP` - native DSD **and** DoP.
- MQA: `is_mqa` flag (detection/passthrough).
- Containers: FLAC, APE, DSF/DFF, **SACD ISO**, CUE sheets; ffmpeg covers ALAC/OPUS/
WavPack/etc.
- Param validation: `check_sample_param`, `reset hw params`, `AudioCodecOpen dsd`,
`no support sample! dsd_mode/out_dev/...` - the player gates rate/format per DAC mode.
**Tools present:** `aplay`, `amixer`, `tinyplay`, `tinymix` - raw PCM playback is possible
today (the DAC just has to already be configured for the rate).
---
## 5. Display
| Item | Value |
|---|---|
| Driver | `ingenicfb` |
| Visible | 360×360, 32 bpp (XRGB8888/BGRA, panel mounted 180°-rotated) |
| Framebuffer virtual | 360×**1080** = triple-buffered 360×360 |
| **Overlay layers** | `fb0`-`fb3` = **4 hardware LCDC planes** (`/dev/fb0..fb3`) |
| Backlight | standard `backlight` class, **41 levels (0-40)** |
**Layer control interface (confirmed via sysfs):** `ingenicfb` exposes `layer0`-`layer3`
under `/sys/class/graphics/fb0/device/`, each with `enable`, `src_fmt`, `src_size`,
`target_pos`, and **`target_size`**. `target_size` ≠ `src_size` ⇒ the LCDC has a
**per-layer hardware scaler** (notable, since there's otherwise no GPU/VPU). layer0 is the
active UI plane (`enable: 1`, src 360×360). Layers position + scale in hardware but **do
not rotate**.
**Implication:** static scaled art/backdrops *could* be HW-composited on fb1-3 (e.g. a
scaled cover or a dim backdrop under the LVGL UI) with no CPU blend. BUT:
- A **spinning** cover still needs software rotation (layers don't rotate) - LVGL already
does this fine, so the overlay is an optimization, not a requirement.
- **Alpha/blend mode is NOT in sysfs** (no alpha/zorder/colorkey node) - likely an FBIO
ioctl in the ingenicfb driver; blending behavior is **unverified**.
- **Visual confirmation needs a camera:** `fbshot` reads fb0's memory, but overlays
composite at *scanout*, so an fb1 test pattern won't appear in an fb0 capture. Defer the
live overlay test until we're ready to pursue HW-layer art and can eyeball the panel.
---
## 6. Input
| Device | node | notes |
|---|---|---|
| Touch | `/dev/input/event1` - **cst816t** | single-finger panel, but speaks **MT type-B** protocol (slot/tracking-id/ABS_MT_POSITION_X/Y/TOUCH_MAJOR/PRESSURE; no plain ABS_X/Y). Caps `EV=0xb`, `ABS=0x6618000` (high word). |
| Keys | `/dev/input/event0` - **x2000_key** | **physical buttons** (GPIO keys) |
We can synthesize input by writing the 32-bit-ABI `input_event` (16-byte) MT-B sequence to
`/dev/input/event1` - verified working (used to drive stock's UI pages over serial during RE). diskOS can also read the hardware keys via event0.
---
## 7. Power
| IC | I²C | role |
|---|---|---|
| **SGM41513** | 2-001a | battery charger (Li-ion, ~3A class) |
| **CW221X** (Cellwise) | 2-0064 | battery **fuel gauge** → `/sys/class/power_supply/cw221X-bat` |
| **AW35615** | 2-0022 | **USB-C PD / CC** controller (Type-C orientation + power delivery) |
Live read: capacity 100%, 4.32 V, source "Mains". The fuel gauge gives real %/voltage;
`/dev/usbcc_ioctl` (from RE) is the PD/CC control path. **PD negotiation hardware exists**,
so faster charging / power-role awareness is at least theoretically addressable.
---
## 8. Connectivity (wireless)
| Item | Value | Source |
|---|---|---|
| Module | **AP6212** = Broadcom **BCM43438 / 4343A1** | dmesg: `chip:0xa9a6`, `fw_bcm43438a1.bin`, `nvram_ap6212a.txt` |
| WiFi | **2.4 GHz only**, 802.11 b/g/n (single-band) | BCM43438 spec |
| WiFi attach | SDIO (`[dhd]` driver v101.10.591.91.40, 512 KB dongle RAM) | dmesg |
| Bluetooth | Broadcom BT over **UART `/dev/ttyS0`** @3Mbaud (`hci0`, BD address (device-specific, redacted)) | `hciconfig` |
| BT firmware | `BCM4343A1_001.002.009.1026.1055.hcd` (the `BCM4345C5/C0` `.hcd` files are leftovers for other FiiO models) | `/lib/firmware/bt_bcm` |
| BT bring-up | **hci0 is NOT attached at boot** - `bcmdhd.ko` only loads the driver/GPIOs. The HCI iface is created on-demand by `brcm_patchram_plus --enable_lpm --enable_hci --baudrate 3000000 --patchram <.hcd> /dev/ttyS0`, then `/usr/project/bluetoothd` (a2dp,avrcp,source) + `bluealsa --device=hci0` (SBC/LDAC). **Stock = bluez; `bsa_server`/`bt_enable_bsa*.sh` = dead code for the wrong chip.** Decoded from `mq_player` strings. | mq_player RE |
> **Corrects prior note:** earlier memory said "BCM4345C5". The actual silicon is
> **BCM43438 (AP6212)** - single-band 2.4 GHz + BT 4.x.
**Implication:** no 5 GHz → WiFi music transfer / streaming is capped at 2.4 GHz real
throughput (tens of Mbps, congestion-sensitive). BT codec quality (LDAC/aptX) is a
userspace-stack question, not a chip blocker for A2DP.
---
## 9. USB
| Item | Value |
|---|---|
| Controller | **DWC2 OTG** (`13500000.otg_new`) - **dual-role** (host *or* device) |
| Current mode | device; gadget `serial_demo` exposing **ACM** only (VID 0x0525 / PID 0xa4a7) → this *is* our serial shell |
| USB-DAC mode | stock "UAC" work-mode reconfigures the gadget to **USB Audio Class** (device-as-DAC for a host PC) |
**Untapped:** DWC2 is OTG, so **USB host mode is physically possible** - mounting USB
storage, or driving an *external* USB DAC (device as a pure transport). Stock only ships
device-mode (serial + UAC). Host-mode would need role switch + the right gadget/host
config and likely a USB-C OTG adapter.
---
## 10. Misc
- **RTC:** `rtc0` present and correct - real hardware clock.
- **ADC:** SoC SAR ADC, 6 aux channels (`/dev/jz_adc_aux_0..5`) - analog reads (e.g.
jack/line detect, if wired).
- **Watchdog:** hardware `/dev/jz_watchdog`.
- **LED:** **none.** `/sys/class/leds` is empty and there is **no physical LED** on the
unit (confirmed visually). The `RGB_LEVEL`/`RGB_STATUS` fields in mq_player's config blob
are vestigial, inherited from the halley5 reference design / other FiiO products.
→ diskOS should plan **no LED features**.
- **Motion sensors:** none on I²C (no accel/gyro) - no tilt/gesture input despite the
round watch-like shape.
---
## 11. Stock-uses vs hardware-can-do (gap list)
| Capability | HW supports | Stock uses | diskOS opportunity |
|---|---|---|---|
| MSA SIMD | Yes (128-bit) | UI not built for it (unknown) | Rebuild LVGL/DSP `-mmsa` → faster render/effects |
| LCDC overlay planes | 4 (fb0-3) | fb0 only | HW-composited art/video layer (spinning cover, backdrops) |
| I²S rate | 768k/64b/8ch | ≤384k/DSD256 (DAC-limited) | none beyond DAC; already maxes the DAC |
| DSD native + DoP | Yes | Yes | parity - reuse driver ioctls |
| Quad balanced DACs | Yes | Yes | direct ioctl control for bit-perfect / HW volume |
| USB host (OTG) | Yes | No (device-only) | USB storage / external USB-DAC transport |
| UAC2 gadget | Yes | Yes (UAC mode) | expose/control USB-DAC from diskOS |
| USB-C PD | Yes (AW35615) | basic charge | PD-aware fast charge / power-role UI |
| Physical keys | Yes (x2000_key) | Yes | map HW buttons in diskOS |
| WiFi 5 GHz | **No** | - | hard ceiling: 2.4 GHz only |
| GPU / VPU / HW JPEG | **No** | - | hard ceiling: video is CPU-only (MSA-assisted at best) |
| Thermal / DVFS | **Not exposed** | - | no power/thermal tuning via standard sysfs |
| LED | **None** | vestigial config | none - drop from plans |
---
## 12. "Write our own mq_player / mq_ui?" - assessment
**mq_ui: already done.** diskOS *is* our own UI; it reuses stock `mq_player` purely as an
audio engine over mqueue IPC. No reason to change that split for UI work.
**mq_player: a full rewrite is high-effort but the local-playback core is feasible.**
What a from-scratch local player needs, and how hard each piece is:
| Piece | Feasibility | Notes |
|---|---|---|
| Decode | **Easy** | reuse on-device `libavcodec.so.58` (same as stock) |
| PCM out | **Easy** | tinyalsa/libasound to card 0; up to 768k/64b |
| DAC control (rate/DSD/filter/volume/mute) | **Medium** | open `/dev/cs43131*` and replay the kernel-driver **ioctls** - must RE the ioctl numbers + sequences from `mq_player.asm` (bounded but real work). This is the **critical enabler**. |
| Native DSD / DoP | **Medium** | once DAC ioctls are known, feed the right format |
| MCU glue (keys/charge/USB-detect/power) | **Medium** | stock player talks to the FiiO MCU; our player must too (MCU command surface mapped during RE) |
| Streaming receivers (AirPlay/DLNA/Roon/QPlay/BT-sink) | **Hard** | large independent stacks - **do not rewrite**; keep stock or graft open-source (e.g. shairport-sync) |
**Recommendation (hybrid, incremental):**
1. **Keep stock mq_player** as the engine for now - it already handles DAC/DSD/streaming/
MCU and diskOS drives it fine over IPC.
2. **RE the `cs43131` ioctl interface regardless** - it's the key that lets diskOS (or a
future thin player) control bit-perfect output, hardware volume, DSD, and filters
directly. Highest-value RE next step.
3. **Only build our own *local* player** if we need something stock won't expose - e.g.
software parametric EQ, ReplayGain, custom gapless/crossfade, or a DSP chain - using
ffmpeg + tinyalsa + the RE'd DAC ioctls. Leave streaming to stock.
The streaming receivers and MCU dependency are what make a *complete* replacement
expensive; the audiophile local-playback path is the tractable, high-value slice.
---
## Appendix: probe commands (reproducible)
- SoC/mem: `cat /proc/cpuinfo /proc/meminfo`, `uname -a`
- Audio: `cat /proc/asound/{cards,pcm}`, `aplay -l`, `aplay -D hw:0,0 --dump-hw-params /dev/zero`, `amixer -c0 controls`
- I²C map: `for d in /sys/bus/i2c/devices/*/name; do echo "$d: $(cat $d)"; done`
- Power: `cat /sys/class/power_supply/*/{type,capacity,voltage_now,status}`
- Storage: `cat /proc/partitions /proc/mtd`
- USB: `ls /sys/class/udc`, `cat /sys/class/udc/*/state`, `ls /sys/kernel/config/usb_gadget/*`
- Wireless: `dmesg | grep -iE 'dhd|bcm|chip'`, `hciconfig -a`, `ls /lib/firmware/{wifi_bcm,bt_bcm}`
- Display/input: `cat /sys/class/graphics/fb0/{name,virtual_size,bits_per_pixel}`, `ls /dev/fb*`, `cat /proc/bus/input/devices`
- Engines: `ls /dev | grep -iE 'ipu|vpu|jpeg|adc|watchdog'`
+61
View File
@@ -0,0 +1,61 @@
# diskOS privacy and network disclosure
This lists everything the installer and the diskOS UI (`mq_ui`) send over the network. The UI ships
as a binary-only component (source not yet published), so this is a good-faith disclosure based on the
code and observed behaviour, not a guarantee; it will be tightened when the UI source is published.
## The installer (this repo)
- **`./install.sh` uses `pip`** to upgrade `pip` itself and download two packages - `pyusb` and
`pycryptodome` - from **PyPI** into a local `.venv`. That `pip`/PyPI traffic is the only network
activity in setup. Point `pip` at your own mirror if you prefer, or pre-install the packages offline.
- **The installer app itself makes no network requests.** Building the image, decrypting/extracting
your firmware, saving the recovery image, and flashing over USB are all fully local. It does not
phone home and sends no telemetry.
## The diskOS UI (`mq_ui`) on the device
diskOS is a local music player. The online features below reach out **only when you use them**; each
request unavoidably reveals your device's public IP to the service it contacts.
| Feature | Endpoint | Protocol | What is sent |
|---|---|---|---|
| **Weather** | `wttr.in` | **plain HTTP** | A location string if you set one, else nothing - wttr.in then **auto-geolocates you by IP** (approximate). Over HTTP, so treat it as visible on your network. |
| **Lyrics** | `lrclib.net` | HTTPS | The current track's **title and artist**, to find matching lyrics. |
| **Scrobbling (Last.fm)** | `ws.audioscrobbler.com` | HTTPS | If enabled and connected: the tracks you play (artist/title/album/timestamp) are reported to **your** Last.fm account. |
| **Last.fm sign-in** | `www.last.fm/api/auth/` | HTTPS | Only a QR code containing the approval URL is shown; **your phone**, not the device, opens it. `www.last.fm/api/account/create` is shown as text so you know where to get an API key. |
### Last.fm credential setup happens over your LOCAL network in plaintext
To connect Last.fm, diskOS runs a **temporary web server on the device** at
`http://<device-wifi-ip>:8080/<random-token>/`, shows a QR for it, and your phone posts your Last.fm
**API key and shared secret** to it. Important properties:
- It is **plain HTTP on your Wi-Fi LAN** - your API key/secret cross your local network unencrypted.
Do this on a network you trust.
- The server is **transient** (runs only during setup), bound to the Wi-Fi interface, and gated by a
random URL token.
- Your Last.fm **API key, secret, and session key are then stored on the device** under `/usr/data`
(device config); **offline scrobbles are queued** in `/usr/data/lastfm.queue` until they can be sent.
Nothing Last.fm-related is sent anywhere except your device, your phone (during setup), and Last.fm.
> **Last.fm is BETA and unverified end-to-end** - see the README's Known Issues. The transport and
> signing are tested, but a full connect-and-scrobble round-trip to a live account has not been.
### The stock FiiO player still runs alongside diskOS
diskOS replaces only the UI; FiiO's original player process still runs underneath it. That stock
component - not diskOS - is responsible for any Bluetooth, firmware-update checks, and LAN media
endpoints (DLNA/AirPlay/Roon/QPlay-style discovery) the device may present on your local network. Those
behaviours are inherited from the stock firmware and are outside diskOS's code.
## What diskOS does NOT do
- No analytics, telemetry, or usage tracking.
- It does not upload your music library, your listening history (beyond Last.fm scrobbles if you turn
them on), or any personal files.
- If you never enable weather, lyrics, or Last.fm, diskOS itself makes no outbound requests.
## Reporting
Report anything that looks like unexpected data leaving the device via the process in
[`SECURITY.md`](../SECURITY.md).
+427
View File
@@ -0,0 +1,427 @@
# Snowsky Disc - mq_player / mq_ui Reverse-Engineering Catalogue
Teardown of the stock V2.09 firmware binaries to document everything the player
and UI are capable of, so diskOS (our LVGL UI) can drive every feature.
- Targets: stock `usr/bin/mq_player` (4126620 B) and `usr/bin/mq_ui` (4418300 B).
MIPS32 little-endian, **glibc dynamically linked**
(interp `/lib/ld-linux-mipsn8.so.1`; 28 DT_NEEDED incl libc.so.6/libsqlite3/FFmpeg - NOT
static musl; only *our* diskOS binary is static-musl).
- Disasm cache (regenerate with `mipsel-linux-gnu-objdump`):
disassembly, data, and string dumps of the two binaries.
- Verification: addresses below were spot-checked against the cache on 2026-06-25.
Items marked **(unverified)** have not yet been individually confirmed at the
instruction level.
---
## ⚑ CORRECTIONS - full verification pass (2026-07)
Handler-level RE of both binaries; corrections spot-checked against the binary and applied inline below.
- **Binaries are glibc dynamic, not static musl** (interp `/lib/ld-linux-mipsn8.so.1`, 28 DT_NEEDED). Affects any replacement-binary / preload work.
- **IPC frame = `TAG(4) + TOTAL_LEN(4hex) + VALUE1(4hex) + optional payload`** - LEN is *total*, not payload length; class-2 cmds add VALUE2. Builder `mq_ui 0x43f82c` (`%s%04X%04X%s`). Replies `%s%04X%04X%s` to `/ui`. Queue `/player` maxmsg=20 msgsize=8192.
- **`06b3` = BT CODEC SELECT** (0=SBC 1=AAC 2/3/4=LDAC; worker 0x40eaf4 → `set_out_dev_sample_array(2,44100,44100)` for SBC/AAC, 96000 for LDAC). **`06b4` = LDAC quality only** (mob/std/high via /usr/data/bt_pipe_recv). ← the two were swapped in our old notes.
- **✅ BT AUDIO OUTPUT NOW WORKS (2026-08-03, live-fixed).** The DAP CAN transmit to a BT speaker (a2dp-source) - it just wasn't exposed and the code is fragile. The crash we hit was NOT the 06b3 codec value and NOT unfinished code: it was **skipping the mandatory `0666000C0006` pre-stop** before `0666000C0002`. Full working route sequence + the `--sbc-quality=medium` (stereo, no stutter) fix → **COMMAND_MAP.md "BT AUDIO OUTPUT" section**. The earlier "SBC fix frame = 06b3000C0000" was wrong/incomplete: diskOS uses `06b3001D0000<MAC>` after the pre-stop + `06c1` init.
- **`06b1`/`06b2`** = BT sample-rate / bit-depth params (not list/query).
- **`0689`** = EQ preset *apply* (21-way engine 0x449544), not a DB-only/media-info op.
- **`0201`** = generic transport toggle (not Roon-specific). **`0657`/`0666`/`06b3` "close_player" = false positive** (shared teardown preamble). `0666`=route (2=BTSRC 4=SPDIF 6=DAC).
- **out_dev** enum has no BTSINK (that's an input/work-mode). 48k→44.1k resample is `libfiio_decoder` over FFmpeg `libswresample` - a stock path, so codec-feasible (CPU headroom still needs an on-device xrun benchmark).
- **IPC-hardening RISK:** stock parser trusts declared LEN and uses `strlen` over the real `mq_receive` byte count → diskOS must emit strictly-correct total lengths and never forward untrusted frames.
- Still UNVERIFIED / deep-RE TODO: exact `0642` receiver-mode values + AirPlay/DLNA/Roon/QPlay trigger sequences; `0715` runtime volume callback @0x822b14; full `SET_USB_MODE` wire encoding; `0722` OTA worker chain; CS43131 ioctl ABI; the remaining ~190 family-inferred tag meanings.
---
## 1. How mq_player is driven - the command dispatch
mq_player is a background command server. The UI never touches audio; it mails
text commands to a POSIX message queue **`/player`**, and the player mails status
frames back on **`/ui`**.
### Wire format
- Command frame: `TAG(4 ASCII) + LEN(4 ASCII hex) + DATA`.
- Response builder @ **0x488d64** uses format `%s%04X%04X%s`
(tag, then two 16-bit hex fields, then payload). **(verified: prologue @0x488d64)**
### Dispatch tables (verified structure)
Two arrays of 8-byte `{descriptor_ptr, handler_ptr}` entries:
- **Table A @ 0x7c9d30** - primary handlers. Entry 0 = `{0x64f6e0, 0x411790}`.
~131 entries. **(count unverified; structure verified)**
- **Table B @ 0x7ca150** - secondary/extended. Many entries have
`handler = 0x00000000` = **declared but unimplemented** (e.g. `{0x64fca8, NULL}`).
~76 entries. **(count unverified; NULL-handler structure verified)**
Note: 0x7b7870 / 0x7b7c90 (noted in older sessions) are **PLT stubs**, not the
real tables. ~194 tag-like ASCII strings exist in `.str` total; ~30 of the table
slots are NULL / reloc-only / unimplemented (NAS / qplay family). **(unverified)**
A command arrives → tag matched against table → handler thunk → real handler.
Most handlers are tiny getters/setters over an in-memory settings struct.
### Confirmed action commands (tag strings verified present in `.str`)
| Tag | Action |
|------|------------------------------------------|
| 0100 | play by list (list_type + index) |
| 0103 | seek |
| 0104 | favorite / unfavorite |
| 0201 | transport (play/pause/next/prev) |
| 0202 | request current state |
| 0622 | rescan SD / rebuild DB |
| 0657 | source/work-mode transition (NOT play-mode) |
| 0666 | set output route (2=BTSRC 4=SPDIF 6=local-DAC) |
| 0689 | select+APPLY EQ preset (21-way engine 0x449544; NOT DB-only) |
| 0715 | set volume |
(0100/0103/0104/0201/0202/0622/0657/0666/0689/0715 all confirmed as ASCII tag
strings in `mq_player.str`. Full 207-tag enumeration is in the raw table dump and
should be transcribed here in a follow-up pass.)
---
## 2. Audio pipeline
Decode → process → output.
### Decode
- **FFmpeg** stack for mp3/flac/wav/aac/aif/m4a/ape/ogg/wma. **(unverified)**
- **libfiio_decoder** for DSD / DFF / DSF / SACD-ISO; DTS. **(unverified)**
- libsndfile present. **(unverified)**
### DSD / DoP
- Modes: NATIVE / DOP / D2P. DoP carrier up to 768k. Roon `configure_*` files in
`usr/project/config/roon/` corroborate (configure_768_dop, _384_d2p, etc.).
**(config files verified on disk; mode enum unverified)**
### Output routing (`out_dev`, tag 0666)
LOCAL_ANALOG (CS43131 headphone DAC) / BTSRC / USB_HOST / SPDIF / I2S3.
(BTSINK is NOT an out_dev route - it is an input/work-mode; see §1 and the work-mode enum in §7.)
**(unverified)**
### Volume - set_volume @ 0x489558 **(verified: prologue @0x489558)**
- Applied by shelling out to an amixer control named **`ICODEC HPOUTL GAIN`**
(string verified @ 0x264dd4 in `.str`).
- Uses inotify to react to external volume changes. **(unverified)**
- On-board MCU over SPI also carries gain/filter/mute opcodes
(SET_EQ_PARAMETER 0x100B etc.). **(unverified)**
### Bluetooth
- bluealsa-based; source + sink; codecs sbc / aac / ldac. **(unverified)**
- **Stock BT stack = BLUEZ, decoded from `mq_player` strings** (NOT BSA - `bsa_server`/`bt_enable_bsa*.sh`
are dead code, wrong chip BCM4345C5, no caller; mq_player references bsa_server 0×). Full bring-up embedded
in mq_player: `brcm_patchram_plus --enable_lpm --enable_hci --no2bytes --tosleep 200000 --baudrate 3000000
--patchram /lib/firmware/bt_bcm/BCM4343A1_001.002.009.1026.1055.hcd /dev/ttyS0` (downloads the chip fw patch
over UART → creates working hci0; nothing does this at boot) → `/usr/project/bluetoothd --noplugin=sap
--plugin=a2dp,avrcp --mode=source` → `bluealsa -S --device=hci0 --profile=a2dp-source --ldac-abr
--ldac-quality=standard --codec=sbc --initial-volume=48` → `hciconfig hci0 up/piscan/class 0x200414` →
`bluetoothctl agent on/default-agent/pairable on`. Sink mode = no-LPM patchram + `--mode=sink -p hfp-ag
--codec=sbc/aac/ldac`. The missing patchram step is why a naive BT enable produces a
poor scan.
### Gapless
- `audio_track_update_play_gapless`. **(unverified)**
### ReplayGain
- Stored / read from DB. **(unverified)**
---
## 3. EQ - the apply path (the key unlock)
The EQ is a **software parametric biquad cascade inside mq_player**, NOT a
hardware DAC feature. **CORRECTION:** `0689` does NOT merely write
to SQLite - its handler (`0x4961bc`) invokes the **21-way preset engine `0x449544`**,
updates the rate caps and applies the DSP, then replies `a639`. Custom bands are set
separately via `0678` (`0x44a658`). Both are live apply paths, not DB-only.
### DSP engine (verified prologues exist)
- Coefficient calc @ **0x448144** - uses pow/sqrt/sincos to turn
{filterType, frequency, gain, qValue} into biquad coefficients.
- IIR cascade @ **0x447ed0** and @ **0x4483a4** - per-sample filter, 32-bit
saturation. **(verified: both are function prologues)**
### Storage - PEQ table (SQL strings verified in `.str`)
Columns: `STYLE_NAME, MASTER_GAIN (REAL), PARAMS_JSON (text), STYLE_PRESET (int)`.
- PARAMS_JSON = array of bands `{filterType, frequency, gain, qValue}` (up to 10)
+ a master gain.
- Confirmed SQL @ ~0x257cb8 region:
- `INSERT INTO PEQ (STYLE_NAME, MASTER_GAIN, PARAMS_JSON, STYLE_PRESET) VALUES ('%s', %.1f, '%s', %d)`
- `UPDATE PEQ SET STYLE_NAME = ?, MASTER_GAIN = %.1f, PARAMS_JSON = ? WHERE STYLE_PRESET = ?`
- `SELECT 1 FROM PEQ WHERE STYLE_PRESET = ? LIMIT 1`
### To apply a custom EQ from diskOS
1. Write/UPDATE the PEQ row (bands JSON + master gain) for a STYLE_PRESET.
2. Send **0689** to select that preset.
The player loads bands → computes coeffs @0x448144 → runs the cascade
@0x447ed0/0x4483a4 on every sample before output.
### ✅ WIRED + CONFIRMED in diskOS (2026-06-30)
Custom EQ is live: `eqcustom.c` (10-band UI, horizontal scroll) → `mdb_set_peq()` writes PEQ
slot 11 in the format below → `ui_apply_eq(11)` sends 0689 → **player applies, sound changes
on-device (user-verified).** `ui_apply_eq` clamp raised 0x0A→20 to reach user slots 11-20.
### CAPTURED PARAMS_JSON format (live, V2.09, 2026-06-30)
Saved a stock "User 1" custom EQ (+12 @ 32 Hz, −12 @ 16 kHz) and read it back. Ground truth:
- **10 fixed bands**: 32, 64, 125, 250, 500, 1000, 2000, 4000, 8000, 16000 Hz, each ±12.0 dB; plus a **master ±12 dB** = the `MASTER_GAIN` REAL column.
- PARAMS_JSON = JSON **array of 10 objects**, e.g. one band:
`{"filterType":0,"frequency":32,"position":0,"gain":"12.0","qValue":"0.7"}`
- `filterType` = 0 (peaking) - **int**; `frequency` Hz - **int**; `position` 0-9 band index - **int**.
- **`gain` and `qValue` are JSON STRINGS** (quoted: `"12.0"`, `"-12.0"`, `"0.7"`), NOT numbers. gain is one-decimal dB; default qValue `"0.7"`.
- **User slot → STYLE_PRESET**: User 1-10 = **11-20** (User 1 = 11). Built-in presets = 0-10 (off,jazz,rock,r&b,hip-hop,pop,dance,classical,retro,sibilance-atten-1,sibilance-atten-2). Rows 160-169 exist but are unused/placeholder (`PARAMS_JSON` = literal string `"(null)"`).
- Stock writes via `UPDATE PEQ SET ... PARAMS_JSON = ? WHERE STYLE_PRESET = ?` then selects with **0689000C<preset hex>** (User 1 = `0689000C000B`).
- Other stock audio settings seen in the same menu (candidates for diskOS, map to documented name-cmds): Gain H/L, BT codec, SPDIF on/off, DAC digital filter (Fast/Slow LL, Fast/Slow PC, NOS, Wideband FF), DRE on/off.
---
## 4. The `/ui` frames - player → UI
mq_ui opens the **`/ui`** mqueue (name built @0x41b388, recv thread @0x415584,
`mq_receive` wrapper @0x41b5c8). Each frame = `TAG(4) + %x extension + JSON "other"`
(parser @0x415674: `strncpy …,4` then `sscanf %x`). Dispatch is a
`strncmp(cmd,tag,4)` chain in `ui_ctrl_response` (@0x41bfd0-0x41c098). Recv log
`[UI RECV]: %s` @0x272960. **(IPC path + format instruction-verified)**
Player→UI frames use **`a`-prefixed** tags (replies/reports) + `06d*` (OTA). Tag
meaning is taken from the adjacent log string (string-inferred, high confidence).
| TAG | meaning | payload |
|------|---------|---------|
| a620 | version reply | version `%s` |
| a710 | max-volume reply | `maxVolume` |
| a715 | volume / UAC srate change | `currentVolume` |
| aa1b | UAC sample-rate change | rate; `usbAudio` |
| a704/a705 | wifi connect status | state; `wifi_ssid` |
| a706 | net status | `%d` |
| a615 | language config | `%d` |
| a609 | theme config | `%d` |
| aa27 | charge-protect | `charge_protect` |
| aa24 | sys config | `%d`; `sys_count` |
| a634 | memory-play | `memoryPlay`/`memoryType` |
| a639 | EQ type | preset + `filterType/frequency/gain/qValue` |
| a6b6 | BT paired devices | count + list |
| a6c5/a6c3/a6c2/a6c1/a6c4/a6c0 | BT disc/connect/open replies | state + address |
| aa1c | power-key event | `%d` |
| aa22 | TF-card (SD) insert/remove | event `%d` |
| aa0c/aa0f | screen status | `%X` |
| a60a | tip/toast popup | tip code |
| a644 | now-playing / UI state update | song JSON (below) |
| a622 | SD rescan / DB-rebuild status | scan state |
| 06d0/06d1/06d2 | OTA progress / success / file-count | `%d` |
Verified-present log strings: GET_VERSION_REPLY @0x27255c, GET_WIFI_CONNECT_STATUS
@0x272658, UAC_SRATE_CHANGE @0x27252c.
**Now-playing JSON payload** (fields verified in `.str`): `song_name`, `song_artist_name`
(@0x271b90), `song_album_name`, `song_style_name`, `song_track`, `song_channel`,
`song_duration_time` (@0x271b34), `duration`, `songposition` (@0x271c2c),
`song_sample_rate`, `song_encoding_rate`, `song_bit_rate`, `song_mimetype`,
`song_file_path`, `is_sacd/is_cue/is_dsd`, `love` (favorite), `state` (play state),
`playerflag` (@0x271c08), `curlistlength`, `pos_id`, `playing_num`,
`work_mode` (@0x271b… 0x272b34), `battery` (@0x272c58). Album art → width/height/
quality/rgb → `/usr/data/fiio/cover.png`.
→ For diskOS status indicators (battery/BT/wifi) we read tags a704/a706 (wifi/net),
the BT a6c* family, and `battery` inside a644. **This is the data we were missing.**
### mq_ui feature surface (subsystems)
IPC core (`/ui` in; `/player`,`/bt_control` out) · frame dispatch (cJSON) · local
browse/play (all-songs/album/artist/style/favorite/custom, `db_song_ctrl.c`) ·
now-playing (`class_play_screen.c`, album art `jpg_to_png.c`) · Roon endpoint ·
home/menus (app/system/audio/others/popup `.json`) · EQ (`equalizer.json`) ·
Bluetooth (`bt.json`) · WiFi/NAS (`wpa_supplicant`, `hostapd`, `wl rssi`) ·
system/version/OTA (`ota_update.c`, `set_local_time.c`) · FiiO Link (UDP
224.0.0.255 discovery + TCP control, device id "SNOWSKY DISC") · bundled zlog.
---
## 5. Config + database schema
SQLite 3.23.1, opened via `sqlite3_open_v2`. DB files (paths verified in `.str`):
| File | Holds |
|------|-------|
| `/usr/data/fiio/db/sysconfig.db` | SYSCONFIG (settings, single row ID=1), CUSTOM_THEME, NAS_CONFIG |
| `/usr/data/fiio/db/song.db` | SONG, MY_LOVE, MEMORY_PLAY, PLAY_LIST, LIST_SONG_0/1/2, CUSTOM_PLAYLIST, PLAYLIST_INFO, PEQ |
| `/usr/data/fiio/db/dic.db` | HAN_PINYIN (CODE INTEGER, PINYIN char(1)) - CJK pinyin sort (on-disk verified) |
| `/usr/data/fiio/db/theme.db` | theme assets |
| `/usr/data/fiio/db/ebook.db` | e-book |
| `/usr/data/bluetooth.db` | bt_devices |
Only `dic.db` ships in the rootfs; the rest are created at first boot under
`/usr/data/fiio/db/`. db→file binding is from co-located source names + init block
(high confidence for SONG-family→song.db, SYSCONFIG/theme/NAS→sysconfig.db).
### SONG (song.db) - literal CREATE for MY_LOVE verified verbatim; SONG = same + IS_LOVE
ID(PK) · PATH · NAME · TITLE · ALBUM · ARTIST · GENRE · DISC · TRACK · IS_CUE ·
IS_ISO · IS_DSD · OFFSET(BIGINT) · DURATION(BIGINT) · NAME_CODE · TITLE_CODE ·
ALBUM_CODE · ARTIST_CODE · GENRE_CODE(pinyin sort keys) · ADD_TIME(INT8) ·
SAMPLE_RATE · BIT_PER_SAMPLE · CHANNELS · BIT_RATE · SONG_MIMETYPE ·
SONG_PRODUCTION_YEAR · IS_SELECT · ALBUM_ARTIST · ALBUM_ARTIST_CODE ·
**IS_LOVE** (SONG only, added by upgrade ALTER - favorites flag).
MY_LOVE = same minus IS_LOVE, `UNIQUE(PATH,TRACK)`. **(CREATE verified @mq_ui.str:9793)**
### CUSTOM_PLAYLIST (song.db) - literal CREATE verified @mq_ui.str:9790
MY_LOVE columns + `PLAYLIST_ID` (after ID), `FOREIGN KEY(PLAYLIST_ID) REFERENCES
PLAYLIST_INFO(ID) ON DELETE CASCADE`, `UNIQUE(PLAYLIST_ID,PATH,TRACK)`.
### PLAYLIST_INFO (song.db) - parent of CUSTOM_PLAYLIST. ID(PK) firm; name/count inferred (LOW confidence).
### PLAY_LIST (song.db) - queue registry: ID(PK) · LIST_ID · LIST_NAME.
### LIST_SONG_0/1/2 (song.db) - active play queues, built by `INSERT INTO LIST_SONG_%d … SELECT … FROM SONG` (verified). Cols: ID · LIST_ID · POS_ID(=MUSIC_ID join key) · PATH · NAME · TITLE · ALBUM · ARTIST · GENRE · DISC · TRACK · IS_CUE · IS_ISO · OFFSET · DURATION · ADD_TIME · IS_SELECT · SONG_TYPE · ALBUM_ARTIST.
### MEMORY_PLAY (song.db) - resume state, single row. ID(=1) · MUSIC_ID · IS_PLAYING · POSITION · IS_CUE · IS_ISO · TRACK. **(UPDATE verified @mq_player.str:13412)**
### PEQ (song.db) - see §3. ID · STYLE_NAME · MASTER_GAIN(REAL) · PARAMS_JSON · STYLE_PRESET.
### CUSTOM_THEME (sysconfig.db) - ID · POS_ID · NAME · PATH · ALIAS · TYPE · IS_SYSTEM · ATTR · ALPHA · LOCK_TIME/DATE/BATTERY/ID3/MEM_TYPE · FRONT_COLOR.
### NAS_CONFIG (sysconfig.db) - ID · NAS_NAME · NAS_IP · USER · (password) · TYPE · AUTO_LOGIN.
### bt_devices (bluetooth.db) - ID · NAME · ADDR(MAC key) · CODEC · SAMPLING · VOLUME.
### SYSCONFIG (sysconfig.db) - single row, all INT, `UPDATE SYSCONFIG set %s = %d where ID = 1` (verified @0x25a910)
Column names verified from descriptor @mq_player.str:13091+. Runtime pak dump
(verified @0x25e7a4): `DSD_MODE,OUT_DEV,VOLUME,WORK_MODE,LIGHT_LEVEL,LIGTH_ON_TIME
(sic),RGB_LEVEL,MUTE,VOL_MODE,RGB_STATUS,MEM_PLAY`. Full key set (names verified;
**enum value mappings NOT proven** - inferred from name + cross-ref to command tags):
DSD_MODE · OUT_DEV/DEVICE_OUTPUT(→0666) · VOLUME · WORK_MODE · LIGHT_LEVEL ·
LIGTH_ON_TIME(backlight timeout, sic) · RGB_LEVEL · MUTE · VOL_MODE · RGB_STATUS ·
RGB_COLOUR · TRIGGER_IN · SYS_THEME · LANGUAGE · USB_MODE · NETWORK_MODE ·
EQ_TYPE(→0689, =PEQ.STYLE_PRESET) · MAX_VOL · BALANCE_VOL · POWER_SAVE ·
FILTER_TYPE(DAC digital filter) · PLAY_MODE(→0102) · MEMORY_PLAY(resume) ·
FOLDER_JUMP · PLAY_GAP(gapless) · INPUT_MODE · VOL_KNOB_MODE · OTA_CFG · BATTERY ·
BT_CODEC · SCREEN_ROT · PO_PRE_VOL/PO_VOL/PRE_VOL · THEME_MODE · CHARGE_PROTECT ·
LOCK_THEME · TREBLE · BASS · WIFI_STATUS · BT_STATUS · LO_DISABLE · OS_MODE ·
DSD_DECODE · SPDIF · AUTO_TIME · DRE_STATUS · LOCAL_IMG_ANIM · IMG_ANIM_BRIGHTNESS ·
ARM_VERSION · MCU_OTA_FAILED_TIME · KEY_SINGLE/DOUBLE/LONG_CLICK_SLE(gesture→action) ·
ARTIST_CLASS_TYPE · AUDIO_VOLUME_SET.
Config is committed to flash on write (`now try to save config to flash` @0x25a…).
---
## 7. Network streaming + USB modes + COMPLETENESS
**Major gap found:** the earlier sections missed the network-streaming receivers and several subsystems. The device is far more capable than §1-6 implied.
### Work-mode / OUT_DEV enum (the master "audio source" list) - names VERIFIED
mq_player has ONE work-mode enum (pointer-array @ ~0x7bb0a0 data; names in `.str` @0x25f9e0+). Switching mode is **name-driven**: a supervisor `@0x444604` does `strcmp(name,"AIRPLAY"/"DLNA"/"ROON"/...)` and starts/stops that receiver. **Names verified present; integer indices unverified:**
`0 NO_DEFINED · 1 I2S3_OUT · 2 USB_HOST_NULL · 3 NO_WORK_MODE · 4 LOCALPLAYER · 5 BTSINK · 6 ANALOG · 7 UAC(USB-DAC) · 8 DLNA · 9 AIRPLAY · 10 ROON · 11 SPDIF_OPT · 12 SPDIF_RX · 13 DMR · 14 DMC · 15 DMS · 16 MIX · 17 I2S_IN · 18 STREAM_AUDIO` (+ QPLAY). sysconfig keys NETWORK_MODE (cfg+0x5c) and OUT_DEV both feed this.
### AirPlay receiver - BUILT IN (was completely missed)
mq_player embeds a **full shairport-sync fork**: `fiio_airplay.c` + `src/shairport.c, rtsp.c, rtp.c, dacp.c, metadata.c, mdns_avahi.c, player.c` + `libshairplay.so`. Advertises **`_raop._tcp`/`_airplay._tcp`** as **"SNOWSKY DISC"**. Config: `/usr/project/config/airplay2/x2000_airplay2.conf` (Shairport-Sync style, AirPlay 2). Flow: supervisor sees mode "AIRPLAY" → sets `airplay_play=1` (@0x7efbe4) → `start_airplay@0x436008` → pthread `airplay_func@0x435fc0` → shairport loop. Needs **wlan0 up** (`start_switch_network_mode_thread@0x46e634` monitors `/sys/class/net/wlan0/operstate`=="up", then emits `/ui` tag **a706** = GET_NET_STATUS_REPLY - a706 is STATUS, NOT the trigger). Has `airplay_artwork_thread`, DACP remote. Audio → ALSA `snd_pcm_writei` to the DAC after out_dev switch. **TRIGGER COMMAND TAG: NOT yet pinned** (a `06xx` work-mode-switch carrying AIRPLAY=9, sent via `ui_send_cmd@0x43f82c` → mqueue `/player` idx 3, frame `TAG(4)+ext1(4hex)+len(4hex)+data`). Player also has a name-string command dispatch @0x482328 (e.g. `SET_USB_MODE`). **Next step to enable AirPlay from diskOS = read the mq_ui output/work-mode menu handler (callers of 0x43f82c) to capture the literal tag+payload for AIRPLAY/UAC/DLNA/ROON.**
### Also built-in network receivers (missed):
- **DLNA/UPnP renderer** - `dlna_player.c`, UPnP RenderingControl/AVTransport SCPD. (mode DLNA=8)
- **Roon Ready endpoint** - `roon_player.c` + `libroon.so` RAAT (`roon_transport_*`, volume/seek/shuffle). (mode ROON=10) UI screen `ui_roon_play.c`.
- **QPlay** (Tencent/QQ Music) receiver - `mq_player_server_qplay.c`, MD5(Seed+PSK) auth, SetNetwork/SetLyric.
- **BT SINK** (phone→player A2DP in) - `bt_sink_server.c/bt_sink_control.c` + AVRCP. (mode BTSINK=5)
### USB modes (partially missed)
USB_MODE sysconfig + `usb_mode_change_handler@0x48eb80` (named cmd `SET_USB_MODE`@dispatch 0x482328). Gadgets via configfs: **`uac_demo`** (USB-DAC, functions uac1.a/uac2.a, /dev/usb_dac, UAC_SRATE→/ui tag aa1b) = work-mode UAC(7); **`storage_demo`** (card-reader, mass_storage.0, lun.0/file=/dev/mmcblk0). `set_usb_host`@0x24da24. **USB_MODE integer values (charge/DAC/reader/host) NOT yet mapped.**
### CORRECTIONS to earlier sections
- **NAS is FULLY IMPLEMENTED** (`nas_control.c`: `mount -t cifs vers=3.0`, NFS, `smbclient -L`; NAS_CONFIG live) - §1's "NAS/qplay = NULL/unimplemented" was WRONG.
- **Tag counts:** ~**221** distinct `/player` `0xxx` command tags + ~**102** `axxx` reply tags (mq_ui emits ~161 cmds, handles ~102 replies). §1/§4 documented ~10 + ~30 → **~95% of the command surface is still undocumented** (entire a4xx reply family untouched).
- Other missed subsystems: **lyrics** (`lrc_paser.c`, `/usr/data/fiio/encoder.lrc`!), generic stream/I2S_IN/capture (`stream_audio.c`,`player_capture.c`), animated gif screensaver (LOCAL_IMG_ANIM), serial-number (`sn_nb.c`), image loaders (bmp/jpeg/png/yabmp), SACD/DST internals, MCU OTA (`ENTER_MCU_UPDATE_MODE`), full SPI/MCU handler family.
## 8. FULL command map - inventory complete, meanings mixed-confidence
**V2.09 dispatch tables** (entry = `{tag_str_ptr, handler_thunk_ptr}` 8B; thunks tail-jump via GOT to real handler):
- **Table A @0x7c9d30 = 131 entries** (terminator @0x7ca148). Tags 06xx/07xx/08xx/0a51.
- **Table B @0x7ca150 = 75 entries** (terminator @0x7ca3a8). Tags 00xx/01xx/02xx/04xx/05xx. ~36 in-table NULL (declared-unimplemented), ~11 thunk-but-GOT-null, ~28 live.
- **MCU/SPI name-commands** via hw_ctrl.c @0x48d0b8 + sysconfig-key dispatch @0x488000 (NOT 0x482328 = that's the tag↔enum resolver).
**⚠️ RELIABILITY:** tag list = reliable (mechanical table walk). Per-tag MEANINGS: ~36 string-VERIFIED, ~80 INFERRED-from-family, ~15 UNKNOWN(runtime-registered GOT=0). **Some conflict with the 1.95-era LIVE-tested set** (1.95 tables were @0x7b7870/0x7b7c90; V2.09 layout differs). **RESOLVED:** the `0657`/`0666`/`06b3` "close_player" reading was a false positive - all three call a shared teardown preamble at the start of a disruptive mode change; that teardown is NOT their meaning. `0657`=source/work-mode transition, `0666`=output route (2/4/6), `06b3`=BT codec select. **Treat remaining INFERRED meanings as needing verification; trust live tests + resolved-handler traces over family inference.**
**String-VERIFIED V2.09 commands (Table A):** 0802=song count, 0620=get WIFI_MAC(/usr/data/fiio/nb.txt), 0704=wifi scan list, 0705=wifi connect(psid/passwd), 0800=write wpa_supplicant.conf, 0701=wifi init, 0700=close network card, 0720/0722=OTA(wget ota_patch), 0639/0689/0690/0634/0641=media-info query→a639 reply, 0675/0630=EQ/PEQ get(gain/filterType/frequency), **0678=set PEQ band(filterType/frequency/gain/qValue)**, 0621=DROP DB tables, 0624=mount/storage, 0815=set MEMORY_PLAY position, 0820/0821/0822=key single/double/long action, 0647=gapless, 0648=artist_class_type, **06b1=BT sample-rate param(0x40d4d8), 06b2=BT bit-depth param(0x40d66c), 06b3=BT CODEC SELECT(0=SBC 1=AAC 2/3/4=LDAC; 0x40eaf4; SBC frame `06b3000C0000` pins 44100), 06b4=LDAC QUALITY only(0x40dbe8; mob/std/high)**, 06b7=BT paired, 06c0=BT trust/power, 06c1=BT alias, 06c4=BT disconnect/remove. (0657/0666/06b3 close_player = RESOLVED false positive, see above.)
**Table B verified:** **0100=main PLAY** (jumptable @0x650e2c by list_type), 0201=transport play/pause toggle (generic, →0x419ff4; NOT Roon-specific), 0112=playlist add song, 0115=add to custom list, 0113=love-list delete, 0114=custom-list delete, 0117=playlist reorder(src/dst), 0408=file/folder browse, 0413=album query, 0414=style/genre query, 02xx=NAS scan/browse(mq_player_server_nas.c, many GOT-null/unimplemented).
**MCU/SPI name-commands (hw_ctrl.c, SPI to MCU):** GET/SET_DEVICE_MAX_VOL, SET_DEVICE_VOL, GET/SET_INPUT_MODE, SET_OUTPUT_MODE, SET_GAIN, GET/SET_DAC_FILTER, **SET_USB_MODE**, GET/SET_EQ_PRE, GET/SET_EQ_PARAMETER, SET_EQ_RESET, SAVE_EQ, SET_AUDIO_FORMAT, SET_FACTORY, **ENTER_MCU_UPDATE_MODE**, SET_MCU_POWER, SET_MUTE, SET_POWER_DOWN_TO_MCU (shutdown path, 63 call sites), GET/SET_ZERO_DATA_DETECT_TIME, BT_REPORT_RATE/STATE/CODEC_TO_MCU. sysconfig-key setters: RGB_COLOUR/TRIGGER_IN/SYS_THEME/LANGUAGE/USB_MODE/NETWORK_MODE/EQ_TYPE/MAX_VOL/BALANCE_VOL/POWER_SAVE/FILTER_TYPE/PLAY_MODE/FOLDER_JUMP/PLAY_GAP/INPUT_MODE/VOL_KNOB_MODE/OTA_CFG/PO_PRE_VOL/PO_VOL/PRE_VOL/TREBLE/BASS/LO_DISABLE/OS_MODE/DSD_DECODE.
## 6. TODO (next passes)
- [x] ~~Live-verify 0657/0666~~ RESOLVED (handler-trace): 0657=source/work-mode transition, 0666=output route(2/4/6). "close_player" was a shared teardown preamble.
- [ ] **Pin the AirPlay trigger tag** (mq_ui work-mode menu → callers of ui_send_cmd@0x43f82c) - the one fact needed to enable AirPlay from diskOS.
- [x] **0622 is NOT a working rescan on V2.09:** diskOS "Rescan Library" sends 0622 → runs a long scan
(~13min, scan_songs_thread) but writes 0 rows to song.db (mtime unchanged). Clearing SONG + reboot also scanned but
wrote nothing. So song.db must be hand-built (laptop `tools/build_db.py` from sync_manifest.json → SONG +
PLAYLIST_INFO + CUSTOM_PLAYLIST; diskOS lib sorts by TEXT so *_CODE only affects play-queue order). The real scan
trigger (comm_scan_songs_thread) is still un-pinned. song.db schema is in this catalogue's table notes / dump from
song.db.bak. Stock leaves DURATION/SAMPLE_RATE/BIT_RATE/CHANNELS=0 and ALBUM=TITLE for tagless rips - match that.
- [x] **USB_MODE card-reader mode = VALUE 2 - LIVE-VERIFIED WORKING (transferred 32GB this way).** This is the clean
stock MSC path for file transfer, and it SIDESTEPS the dangerous 0666 entirely. Details:
- `usb_mode_change_handler` @ **0x48eb??** (log str "usb_mode_change_handler = %d" @vaddr 0x670358, ref'd
by `addiu v1,v1,856` @0x48eb84). Reads/writes current usb_mode global @ **0x822d20**. Branches on the
target mode value (s0): observed cases 2, 5, 6.
- On **usb_mode==2** (`bne s0,2` fall-through @0x48ebc4) it accesses
**`/sys/kernel/config/usb_gadget/storage_demo`** (lui 0x66 + 13620 = vaddr 0x663534) → builds a
`mass_storage.0` function, **lun.0/file = `/dev/mmcblk0`** (whole SD), toggles cdrom/nofua/removable/ro,
binds the UDC. (All configfs paths string-verified @ file 0x263534-0x263d8f.)
- **CLEAN handoff CONFIRMED:** before/while exporting it UNMOUNTS the SD - `unmount_udisk` @0x668ed4 (called
~7× around 0x470134-0x470388) runs `umount %s` with 5 retries + `umount -lf %s 2>/dev/null` lazy-force
fallback on `/tmp/sdcard` (strs @0x268be8/0x266e40/0x268e40). So it properly releases mq_player's SD hold
(the EBUSY blocker) - no corruption, unlike a raw composite-gadget export.
- Trigger: **`SET_USB_MODE`** name-command (str @vaddr 0x66fe40; dispatch refs @0x48232c/0x4863ec/0x48d154;
builders @0x408044/0x40fa94) and/or the `USB_MODE` sysconfig field. EXACT payload/value-encoding for
SET_USB_MODE still to pin (one more trace), but the value is **2**.
- ⚠ CAVEAT (untested): a UDC binds ONE gadget at a time, so binding `storage_demo` almost certainly UNBINDS
our `serial_demo` ACM → **the serial shell will drop while in reader mode**; exiting reader mode (mode
switch / replug) should restore it. TEST LIVE WITH USER PRESENT (power-cycle fallback). This is still far
safer than 0666 (no player crash / MCU-reboot path).
- ⇒ This unblocks **music-transfer-over-USB** via the stock mechanism: set USB_MODE=2 → laptop sees the SD as
a USB drive → copy 32GB at USB speed + fsck → exit reader mode → in-device rescan. Replaces the unsafe
wifi-push (watchdog reboots) and the blocked raw-MSC attempt.
- [ ] Transcribe the full 221-tag command table + 102 a-frame replies.
- [ ] Transcribe the full 207-tag command table (A+B) with handler addresses.
- [ ] Verify audio/decoder/BT/DSD claims (§2) at instruction level (currently unverified).
- [ ] Resolve SYSCONFIG enum value→option integer mappings.
- [ ] Pin PLAYLIST_INFO's full column list (currently only ID firm).
- [ ] diskOS wiring: status indicators from a644/a704/a706/a6c* + custom-EQ via PEQ write + 0689.
## 5b. SYSCONFIG - the master settings table (decoded 2026-06-30)
`/usr/data/fiio/db/sysconfig.db` → table **SYSCONFIG** (single row), one INT column per setting.
This is where every audio/system setting persists (the config-named commands write here).
Columns incl: DSD_MODE, OUT_DEV, VOLUME, WORK_MODE, LIGHT_LEVEL(brightness), LIGTH_ON_TIME,
MUTE, VOL_MODE, USB_MODE, NETWORK_MODE, EQ_TYPE(=0689 preset), MAX_VOL, BALANCE_VOL(channel
balance), POWER_SAVE, FILTER_TYPE(DAC filter), PLAY_MODE(=0102), MEMORY_PLAY, FOLDER_JUMP,
PLAY_GAP, INPUT_MODE, VOL_KNOB_MODE, BT_CODEC, SCREEN_ROT, PO_PRE_VOL/PO_VOL/PRE_VOL,
THEME_MODE, CHARGE_PROTECT, LOCK_THEME, TREBLE, BASS, WIFI_STATUS, BT_STATUS, LO_DISABLE,
OS_MODE, DSD_DECODE, SPDIF, AUTO_TIME, DRE_STATUS, DEVICE_OUTPUT, KEY_SINGLE/DOUBLE/LONG_CLICK_SLE,
ARTIST_CLASS_TYPE, AUDIO_VOLUME_SET.
Live sample (V2.09): FILTER_TYPE=1, DRE_STATUS=1, BALANCE_VOL=0, SPDIF=0, MAX_VOL=120,
BT_CODEC=3, MEMORY_PLAY=0, FOLDER_JUMP=0, PLAY_GAP=0, SCREEN_ROT=0, CHARGE_PROTECT=0,
ARTIST_CLASS_TYPE=0, TREBLE=0, BASS=0, OUT_DEV=6, OS_MODE=0, LO_DISABLE=0, DSD_MODE=1,
INPUT_MODE=1, VOL_MODE=1. (No explicit GAIN column - likely VOL_MODE or encoded in OUT_DEV;
confirm by toggling.) Filter enum (others.json 70-75): 0=FAST_LL,1=SLOW_LL,2=SLOW_PC,3=FAST_PC,
4=NON_OS,5=Wideband_FF. To wire a setting in diskOS: write its SYSCONFIG column + send its apply
command (verified: gapless 0647, BT codec 06b3 [0=SBC…4=LDAC-high], artist 0648, memory 0815, keys 0820-22; Gain/
Filter/DRE/Balance apply-cmds TBD via strace-correlate of stock mq_ui - strace on mq_ui is SAFE,
only strace-on-mq_player triggers the MCU reboot).
## 5c. Audio/DAC apply-commands - DECODED LIVE (2026-06-30, strace of stock mq_ui)
Captured by strace `mq_timedsend` on stock mq_ui while toggling each setting (SAFE - strace
on mq_ui, never mq_player). Frame format `<tag>000C<value 4hex>`. Note: SYSCONFIG column
writes are DEFERRED (didn't update live), so these were correlated by the FRAME, not the DB.
Background-noise tags to ignore: 0807 (recurring 0/1 status), 0704 (wifi scan).
- **DRE** = `0812` - `0812000C0000` = ON, `0812000C0001` = OFF (startup sent 0 when DRE on).
- **Gain** = `0645` - `0645000C0000`/`0001` (Low/High; startup sent 0).
- **Channel balance** = `0713` - `0713000C01<level>`; center = `0101`, nudging streamed 0105..010C
(one frame per step; 0x01 hi-byte = channel/side, lo-byte = level).
- **DAC Filter** = `0653` - enum = menu order (clean sweep): 0=FAST_LL, 1=SLOW_LL, 2=SLOW_PC, 3=FAST_PC, 4=NON_OS, 5=Wideband_FF.
- **SPDIF** = via output-route `0666` - SPDIF on = `0666000C0004`, analog = `0666000C0006`
(0666 = OUT_DEV/output route: LOCAL_ANALOG=6, SPDIF=4; mutually exclusive with headphone).
- **BT codec** = `06b3` (**CORRECTED**: mq_ui codec menu 0x464e90 sends 06b3, not 06b4):
codec-settings menu sends payload-less `06b3000C0000`=SBC `…0001`=AAC `…0002/3/4`=LDAC mob/std/high.
**But the ROUTE-to-speaker frame (live-captured 2026-08-03) is `06b3<len>000X<MAC>`** (X=codec, MAC payload
kept for stock frame-shape; worker ignores it). diskOS route uses `06b3001D0000<MAC>` (SBC). `06b4` is
LDAC-quality only. **Full working BT-transmit sequence → COMMAND_MAP.md "BT AUDIO OUTPUT" section.**
- Also re-confirmed: `0666`=output route, `0642`=network mode (from startup sync).
## 5d. More settings - DECODED LIVE 2026-06-30 (strace stock mq_ui, clean batch)
- **Channel balance** = `0713` - `0713000C<HHLL>`: center=`0000`; one side `00NN` (NN=step), other side `01NN`. (Same tag the audio-cluster capture saw.) Mixer-style, likely safe.
- **Gapless** = `0647` - `0647000C0001` on / `0000` off. (matches COMMAND_MAP 0647=set gapless)
- **Artist list grouping** = `0648` - `0648000C0000` Artist / `0001` Album-Artist. (ARTIST_CLASS_TYPE)
- **Memory playback (resume)** = `0684` - `0684000C00<0|1|2>` = Off / Position / Song. (0684 was "media getter" in COMMAND_MAP - now confirmed the MEMORY_PLAY setter)
- **Max volume** = `0711` - `0711000C00<NN>` where NN(hex)=cap, 0..0x78(120).
NOTE: only SPDIF (0666 route) wedges on a raw send; these are config/mixer commands, expected safe - but per the wedge lesson, apply on live user change only, don't blind-send at boot.
## 5e. Sibilance EQ presets wired (2026-07-01, code-only, staged not-yet-deployed)
Stock has 11 EQ presets (equalizer.json 0-10); diskOS had 9. Added preset 9="Sibilance 1",
10="Sibilance 2" to OPT_EQ (settings.c) + T_EQ (npmenus.c), nopts 9->11, clamps q>8->q>10.
Uses the existing 0689 path (ui_apply_eq, clamp already 0..20) so 0689000C0009/000A select them.
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env python3
"""Assemble the USB stage-1 from the GPL-built SPL + the W63AH6NKB DDR parameter block.
stage1 = BDIF record + DDR record (35 W63AH6NKB reg words) + zero-pad to 0x800 + u-boot-spl.bin
The mask ROM loads this at 0xb2401000 and executes the SPL at 0xb2401800; the SPL reads the
parameter records at 0xb2401000. Reproducible: same inputs -> identical output.
Usage: assemble_stage1.py <u-boot-spl.bin> <ginfo_w63ah6nkb.bin> <out disc_spl_lpddr3.bin>
"""
import struct, sys, hashlib
def main(spl_path, ginfo_path, out_path):
g = open(ginfo_path, 'rb').read()
# BDIF (board-info) record verbatim: [magic][size=184][184B payload] = 0xc0 bytes
bdif = g[0x000:0x0c0]
if struct.unpack_from('<I', bdif, 0)[0] != 0x42444946:
raise SystemExit("BDIF magic missing in ginfo")
# DDR record payload = the 35 register words (old ABI: no name[32] header), i.e. vendor
# DDR payload bytes [+0x2c .. +0xb8] which map 1:1 onto struct ddr_registers (with ddr_mr11).
ddr_payload = g[0xc8 + 0x2c : 0xc8 + 0x2c + 35 * 4]
if len(ddr_payload) != 140:
raise SystemExit("unexpected DDR payload length")
ddr_magic = (ord('D') << 24) | (ord('D') << 16) | (ord('R') << 8) | 0
ginfo = bdif + struct.pack('<II', ddr_magic, len(ddr_payload)) + ddr_payload + struct.pack('<I', 0)
if len(ginfo) > 0x7c0:
raise SystemExit("param block collides with the 0x7c0 diagnostic scratch")
spl = open(spl_path, 'rb').read()
buf = bytearray(ginfo) + b'\x00' * (0x800 - len(ginfo)) + spl
if len(buf) > 0x3000:
raise SystemExit("stage-1 exceeds the ~0x3000 TCSM window: %d bytes" % len(buf))
open(out_path, 'wb').write(buf)
print("wrote %s: %d bytes (0x%X), TCSM headroom %d, sha256=%s"
% (out_path, len(buf), len(buf), 0x3000 - len(buf), hashlib.sha256(buf).hexdigest()))
if __name__ == '__main__':
if len(sys.argv) != 4:
raise SystemExit(__doc__)
main(*sys.argv[1:])
Binary file not shown.
Binary file not shown.
+353
View File
@@ -0,0 +1,353 @@
/* my_write.c - SFC SPI-NAND WRITE primitive self-test for GD5F2GM7 (X2000 Disc).
* Built on the PROVEN my_read.c framework (same SFC 0x7c cmd-index + CDT + clock/pins).
* v1: SINGLE-BLOCK round-trip self-test on the INACTIVE ro2 slot - STRICTLY contained:
* erase 1 block -> read back (expect 0xFF) -> program 4 pages w/ pattern -> read back -> compare.
* Reports everything in the dbg block @0xa0a00000. No host data needed (pattern generated on-device).
* Active stock slot (ro4) is never touched; this proves the primitive before any real flash. */
typedef unsigned int u32; typedef unsigned char u8;
#define SFC_BASE 0xb3440000u
#define CPM_BASE 0xb0000000u
#define CPM_CLKGR 0x20u
#define CPM_SSICDR 0x74u
#define CPM_CPMPCR 0x14u
#define SFC_GLB 0x0000
#define SFC_DEV_CONF 0x0004
#define SFC_DEV_STA_EXP 0x0008
#define SFC_DEV_STA_MSK 0x0010
#define SFC_TRAN_CONF0 0x0014
#define SFC_TRAN_LEN 0x002c
#define SFC_DEV_ADDR0 0x0030
#define SFC_DEV_ADDR_PLUS0 0x0048
#define SFC_MEM_ADDR 0x0060
#define SFC_TRIG 0x0064
#define SFC_SR 0x0068
#define SFC_SCR 0x006c
#define SFC_INTC 0x0070
#define SFC_CGE 0x0078
#define SFC_CMD_IDX 0x007c
#define SFC_ARG0 0x0080
#define SFC_ARG1 0x0084
#define SFC_ARG2 0x0088
#define SFC_ARG3 0x008c
#define SFC_UNK0 0x009c
#define SFC_RM_DR 0x1000
#define GLB_TRAN_DIR_OFFSET 13
#define GLB_THRESHOLD_OFFSET 7
#define GLB_THRESHOLD_MSK (0x3f<<7)
#define GLB_PHASE_NUM_OFFSET 3
#define GLB_PHASE_NUM_MSK (0x7<<3)
#define THRESHOLD 32
#define END (1<<4)
#define TRAN_REQ (1<<3)
#define RECE_REQ (1<<2)
#define CLR_END (1<<4)
#define CLR_TREQ (1<<3)
#define CLR_RREQ (1<<2)
#define TRIG_START (1<<0)
#define TRIG_STOP (1<<1)
#define TRIG_FLUSH (1<<2)
#define CMD_RDID 0x9f
#define CMD_PARD 0x13
#define CMD_FRCH 0x0b
#define CMD_GET_FEATURE 0x0f
#define CMD_SET_FEATURE 0x1f
#define CMD_RESET 0xff
#define CMD_WREN 0x06
#define CMD_PLOAD 0x02
#define CMD_PEXEC 0x10
#define CMD_BERASE 0xd8
#define ADDR_STATUS 0xc0
#define ADDR_PROTECT 0xa0
#define ADDR_FEATURE 0xb0
#define ADDRLEN 2u
#define GUARD 800000u
#define ST_OIP 0x01
#define ST_EFAIL 0x04
#define ST_PFAIL 0x08
static inline void w32(u32 a,u32 v){*(volatile u32*)a=v;}
static inline u32 r32(u32 a){return *(volatile u32*)a;}
#define sfc_writel(v,o) w32(SFC_BASE+(o),(u32)(v))
#define sfc_readl(o) r32(SFC_BASE+(o))
#define GPIO_PORTE 0xb0010400u
#define SFC_PINS 0x003f0000u
static void mux_sfc_pins(void){
w32(GPIO_PORTE+0x18,SFC_PINS); w32(GPIO_PORTE+0x28,SFC_PINS);
w32(GPIO_PORTE+0x38,SFC_PINS); w32(GPIO_PORTE+0x48,SFC_PINS);
}
static u32 g_id,g_len,g_arg0,g_arg1,g_arg2,g_arg3;
static void send_raw(int dir){
u32 v;
sfc_writel(TRIG_STOP,SFC_TRIG);
v=sfc_readl(SFC_CMD_IDX); v=(v&~0x3fu)|(g_id&0x3fu); sfc_writel(v,SFC_CMD_IDX);
sfc_writel(g_arg0,SFC_ARG0); sfc_writel(g_arg1,SFC_ARG1);
sfc_writel(g_arg2,SFC_ARG2); sfc_writel(g_arg3,SFC_ARG3);
v=sfc_readl(SFC_CMD_IDX)&0x7fffffffu; if(g_len)v|=0x80000000u; sfc_writel(v,SFC_CMD_IDX);
if(g_len){ v=sfc_readl(SFC_CMD_IDX)&~0x40000000u; v|=((u32)dir&1u)<<30; sfc_writel(v,SFC_CMD_IDX); }
{u32 g=sfc_readl(SFC_GLB); g&=~((1u<<GLB_TRAN_DIR_OFFSET)|GLB_PHASE_NUM_MSK|GLB_THRESHOLD_MSK|(1u<<6)|3u);
g|=(THRESHOLD<<GLB_THRESHOLD_OFFSET)|(1u<<GLB_PHASE_NUM_OFFSET)|2u|0x4000u|(((u32)dir)<<GLB_TRAN_DIR_OFFSET);
sfc_writel(g,SFC_GLB);}
sfc_writel(g_len,SFC_TRAN_LEN); sfc_writel(0,SFC_MEM_ADDR);
sfc_writel(TRIG_FLUSH,SFC_TRIG); sfc_writel(TRIG_START,SFC_TRIG);
}
static void cmd(u32 c,u32 len,u32 addr,u32 aw,u32 dmy,u32 den,int dir){
(void)dmy;(void)den;
g_arg0=g_arg1=g_arg2=g_arg3=0;
if(c==0x9f) g_id=aw?2:1; /* FIX: RDID = CDT idx 1/2 (was 2/3) */
else if(c==0xff) g_id=0;
else if(c==0x0f){ g_id=4; g_arg2=addr; }
else if(c==0x1f){ g_id=3; g_arg2=addr; } /* FIX: SET_FEATURE = CDT idx 3, was 5 (=PAGE_READ!) -> unlock never landed */
else if(c==0x13){ g_id=5; g_arg1=addr; g_arg2=ADDR_STATUS; }
else if(c==0x0b){ g_id=7; g_arg0=addr; }
else if(c==0x06){ g_id=8; } /* WRITE_ENABLE: cmd-only */
else if(c==0x02){ g_id=9; g_arg0=addr; } /* PROGRAM_LOAD: COL addr, data-out */
else if(c==0x10){ g_id=10; g_arg1=addr; } /* PROGRAM_EXECUTE: ROW addr (same path as PAGE_READ row) */
else if(c==0xd8){ g_id=11; g_arg1=addr; } /* BLOCK_ERASE: ROW addr */
else g_id=0x3f;
g_len=len; send_raw(dir);
}
static int clr_end(void){u32 g=0; while(!(sfc_readl(SFC_SR)&END)){if(++g>GUARD)return -1;} sfc_writel(CLR_END,SFC_SCR); return 0;}
static int rd(u32*d,u32 length){
u32 done=0,fn,sr,len=(length+3)/4,g=0; int i;
while(done<len){ if(++g>GUARD)return -1; sr=sfc_readl(SFC_SR);
if(sr&RECE_REQ){ sfc_writel(CLR_RREQ,SFC_SCR); fn=((len-done)>THRESHOLD)?THRESHOLD:(len-done);
for(i=0;i<(int)fn;i++){*d++=sfc_readl(SFC_RM_DR);done++;} g=0;} }
return clr_end();
}
static int wr(u32*d){u32 g=0; while(!(sfc_readl(SFC_SR)&TRAN_REQ)){if(++g>GUARD)return -1;} sfc_writel(CLR_TREQ,SFC_SCR); sfc_writel(*d,SFC_RM_DR); return clr_end();}
static int wr_bulk(u32*s,u32 length){ /* transmit `length` bytes (PROGRAM_LOAD data phase) */
u32 done=0,fn,sr,len=(length+3)/4,g=0; int i;
while(done<len){ if(++g>GUARD)return -1; sr=sfc_readl(SFC_SR);
if(sr&TRAN_REQ){ sfc_writel(CLR_TREQ,SFC_SCR); fn=((len-done)>THRESHOLD)?THRESHOLD:(len-done);
for(i=0;i<(int)fn;i++){sfc_writel(*s++,SFC_RM_DR);done++;} g=0;} }
return clr_end();
}
static u32 g_mpll,g_cdr,g_src;
static void set_clock(void){
u32 reg=CPM_BASE+CPM_SSICDR, v=r32(reg);
u32 src=(v>>30)&3;
u32 pcr=r32(CPM_BASE+(src?CPM_CPMPCR:0x10));
u32 m=((pcr>>20)&0xfff)+1, n=((pcr>>14)&0x3f)+1, od=1u<<((pcr>>11)&7u);
u32 pll=(24u*m*2u)/n/od, cdr=((pll+49u)/50u-1u)&0xff;
g_mpll=pll; g_cdr=cdr; g_src=src;
w32(CPM_BASE+CPM_CLKGR, r32(CPM_BASE+CPM_CLKGR)&~(1u<<2));
v&=~(0xffu|(3u<<27)); v|=(1u<<29)|cdr;
w32(reg,v);
{u32 g=0; while((r32(reg)&(1u<<28))){if(++g>GUARD)break;}}
}
static void sfc_reset_regs(void){
int n; u32 v;
for(n=0;n<6;n++){sfc_writel(0,SFC_TRAN_CONF0+n*4);sfc_writel(0,SFC_UNK0+n*4);sfc_writel(0,SFC_DEV_ADDR0+n*4);sfc_writel(0,SFC_DEV_ADDR_PLUS0+n*4);}
sfc_writel(0,SFC_DEV_CONF);sfc_writel(0,SFC_DEV_STA_EXP);sfc_writel(0,SFC_DEV_STA_MSK);
sfc_writel(0,SFC_TRAN_LEN);sfc_writel(0,SFC_MEM_ADDR);sfc_writel(0,SFC_TRIG);
sfc_writel(0,SFC_SCR);sfc_writel(0,SFC_INTC);sfc_writel(0,SFC_CGE);sfc_writel(0,SFC_RM_DR);
v=sfc_readl(SFC_GLB); v=(v&~3u)|2u; sfc_writel(v,SFC_GLB);
sfc_writel(TRIG_STOP,SFC_TRIG);
sfc_writel(0x1f,SFC_SCR); sfc_writel(0x1f,SFC_INTC);
sfc_writel((1<<1)|(1<<0)|(1<<2)|(2<<5),SFC_DEV_CONF);
v=sfc_readl(SFC_GLB); v&=~(GLB_THRESHOLD_MSK|(1u<<6)|3u);
v|=(THRESHOLD<<GLB_THRESHOLD_OFFSET)|2u|0x4000u; sfc_writel(v,SFC_GLB);
}
#define SFC_CDT 0x0800
#define CDT_XFER(aw,dmy,den,cmd) (((u32)(aw)<<26)|(1u<<24)|((u32)(dmy)<<17)|((u32)(den)<<16)|((cmd)&0xffffu))
#define CDT_LINK(link,addrkind,tm) (((u32)(link)<<31)|((u32)(tm)<<4)|((addrkind)&0xfu))
static void cdt_write(u32 idx,u32 w0,u32 w1,u32 w2,u32 w3){
u32 b=SFC_BASE+SFC_CDT+idx*16u; w32(b,w0); w32(b+4,w1); w32(b+8,w2); w32(b+12,w3);
}
static void cdt_init(void){
cdt_write(0, CDT_LINK(0,0,0), CDT_XFER(0,0,0,0xff), 0,0); /* RESET */
cdt_write(1, CDT_LINK(0,0,0), CDT_XFER(0,0,1,0x9f), 0,0); /* RDID aw0 */
cdt_write(2, CDT_LINK(0,1,0), CDT_XFER(1,0,1,0x9f), 0,0); /* RDID aw1 */
cdt_write(3, CDT_LINK(0,2,0), CDT_XFER(1,0,1,0x1f), 0,0); /* SET_FEATURE */
cdt_write(4, CDT_LINK(0,2,0), CDT_XFER(1,0,1,0x0f), 0,0); /* GET_FEATURE */
cdt_write(5, CDT_LINK(1,1,0), CDT_XFER(3,0,0,0x13), 0,0); /* PAGE_READ linked->6 */
cdt_write(6, CDT_LINK(0,2,0), (1u<<25)|CDT_XFER(1,0,1,0x0f), 0,1); /* hw OIP poll */
cdt_write(7, CDT_LINK(0,0,0), CDT_XFER(2,8,1,0x0b), 0,0); /* READ_CACHE */
cdt_write(8, CDT_LINK(0,0,0), CDT_XFER(0,0,0,0x06), 0,0); /* WRITE_ENABLE: cmd-only */
cdt_write(9, CDT_LINK(0,2,0), CDT_XFER(2,0,1,0x02), 0,0); /* PROGRAM_LOAD: COL(2B), data-out, dir set at run */
cdt_write(10,CDT_LINK(0,1,0), CDT_XFER(3,0,0,0x10), 0,0); /* PROGRAM_EXECUTE: ROW(3B) */
cdt_write(11,CDT_LINK(0,1,0), CDT_XFER(3,0,0,0xd8), 0,0); /* BLOCK_ERASE: ROW(3B) */
}
static int nand_reset(void){u32 st,g=0;
cmd(CMD_RESET,0,0,0,0,0,0); if(clr_end())return -1;
do{if(++g>GUARD)return -2; cmd(CMD_GET_FEATURE,1,ADDR_STATUS,1,0,1,0); if(rd(&st,1))return -3;}while(st&ST_OIP);
return 0;}
static int set_features(void){u32 x; /* unlock block-protect + enable on-die ECC */
cmd(CMD_SET_FEATURE,1,ADDR_PROTECT,1,0,1,1); x=0; if(wr(&x))return -1; /* PROTECT(0xA0)=0 */
cmd(CMD_SET_FEATURE,1,ADDR_FEATURE,1,0,1,1); x=(1<<4); return wr(&x);} /* FEATURE(0xB0): ECC_EN */
static int wait_ready(u32*stout){u32 st,g=0;
do{if(++g>GUARD)return -1; cmd(CMD_GET_FEATURE,1,ADDR_STATUS,1,0,1,0); if(rd(&st,1))return -2;}while(st&ST_OIP);
if(stout)*stout=st; return 0;}
static int read_page(u32 page,u32 col,u8*dst,u32 len){
cmd(CMD_PARD,0,page,3,0,0,0); if(clr_end())return -2;
cmd(CMD_FRCH,len,col,ADDRLEN,8,1,0); return rd((u32*)dst,len);}
static int block_erase(u32 page){u32 st; int r;
cmd(CMD_WREN,0,0,0,0,0,0); if(clr_end())return -10;
cmd(CMD_BERASE,0,page,3,0,0,0); if(clr_end())return -11;
r=wait_ready(&st); if(r)return -12;
if(st&ST_EFAIL)return -13;
return 0;}
static int program_page(u32 page,u8*src){u32 st; int r;
cmd(CMD_WREN,0,0,0,0,0,0); if(clr_end())return -20;
cmd(CMD_PLOAD,2048,0,2,0,1,1); if(wr_bulk((u32*)src,2048))return -21; /* load cache @col0 */
cmd(CMD_PEXEC,0,page,3,0,0,0); if(clr_end())return -22; /* commit row */
r=wait_ready(&st); if(r)return -23;
if(st&ST_PFAIL)return -24;
return 0;}
/* LEAN writer (my_write2): programs NPAGES from host-loaded DRAM @SRC into NAND
* starting at START_PAGE, erasing the covered blocks first. Reads back page 0 and
* compares to SRC for one-run feedback. This is the REAL write path (data from DRAM),
* not a self-generated pattern - host loads SRC, runs this, verifies via dbg + reader. */
/* my_write3 - MULTI-BLOCK writer for the real rootfs flash.
* Programs NLOGBLOCKS logical 128KB blocks from host-loaded DRAM @SRC into physical
* blocks starting at START_BLOCK, SKIPPING the factory bad block SKIP_BLOCK (left untouched
* so its OOB bad-marker survives). This reconstructs the mtdblock_bbt logical->physical mapping. */
#ifndef START_BLOCK
#define START_BLOCK 80u /* rootfs @0xA00000 / 0x20000 */
#endif
#ifndef NLOGBLOCKS
#define NLOGBLOCKS 580u /* diskos_*_v228.bin = 76021760 B / 128KB = 580 blocks (override via -D) */
#endif
#ifndef SKIP_BLOCK
#define SKIP_BLOCK 383u /* verified factory bad block in the rootfs region (dump ground truth) */
#endif
#define PAGE_SZ 2048u
#define SRC 0xa1000000u /* host-loaded squashfs (padded to NLOGBLOCKS*128KB), via usbboot --download */
/* my_write5 - PORTABLE robust bad-block-aware writer (my_write4 + an in-writer OOB scan).
* Unlike my_write4 (which hardcoded SKIP_BLOCK=383, this unit's bad block), my_write5 first
* SCANS each physical block's OOB bad-marker to learn THIS unit's factory-bad blocks, then
* skips exactly those - so it maps logical->physical correctly on any device. For every good
* physical block it does
* erase -> program 64 pages -> READBACK-VERIFY all 64 pages, retrying the WHOLE block (with a
* NAND reset + re-unlock between attempts) up to MAXTRIES. This recovers transient SFC/timeout
* failures like the ones that killed the previous flash on blocks 80/81 (which are NOT OOB
* bad and were written fine by the V2.09 flash). FAILS CLOSED: if a block cannot be written+
* verified after MAXTRIES, it stops immediately and reports - it never silently mis-maps. */
#define MAXTRIES 6u
#define PART_END (START_BLOCK + NLOGBLOCKS + 64u) /* generous physical ceiling (guards runaway) */
#define MAXBAD 64u /* = PART_END-START_BLOCK-NLOGBLOCKS: max bad blocks the image can absorb */
/* linear membership test over the scanned bad-block list (nbad is tiny in practice) */
static int is_bad(u32 pb, const u32 *bl, u32 n){ u32 i; for(i=0;i<n;i++){ if(bl[i]==pb) return 1; } return 0; }
/* Read a block's OOB bad-marker byte (page0 spare byte0) once, retrying transient SFC read
* failures with a NAND reset. 0=ok (*mk set), -1=could not read. On this GD5F2GM7 the marker
* reads RAW regardless of the on-die ECC setting (proven by bbscan), so no ECC mgmt is needed. */
static int oob_read1(u32 pb, u8 *mk){
u32 t, m;
for(t=0;t<MAXTRIES;t++){
if(t>0 && nand_reset()!=0) continue;
m=0xFFFFFFFFu;
if(read_page(pb*64u, PAGE_SZ, (u8*)&m, 4u)==0){ *mk=(u8)(m & 0xFFu); return 0; }
}
return -1;
}
/* Bad-block verdict from the OOB marker, FAIL-CLOSED: 0=good, 1=bad, -1=undeterminable.
* EVERY verdict - good AND bad - is confirmed by two independent reads that must agree, so a
* single successful-but-corrupted read can't produce a false-good (missed bad block) OR a
* false-bad (skipped good block); either would mis-map against the kernel's BBT. An unreadable
* or self-inconsistent marker returns -1 and the caller aborts. */
static int oob_verdict(u32 pb){
u8 a, b;
if(oob_read1(pb, &a)!=0) return -1;
if(oob_read1(pb, &b)!=0) return -1;
if(a!=b) return -1;
return (a==0xFFu) ? 0 : 1;
}
/* Erase + program 64 pages + verify-readback a single physical block from src. 0=ok, else rc<0. */
static int write_block_verify(u32 pb, const u8 *src, u32 *tries_out){
u32 t, k, i;
int er, pr;
u8 rb[2048] __attribute__((aligned(4)));
u32 page = pb*64u;
for(t=0;t<MAXTRIES;t++){
/* On a retry, fully re-init the NAND/SFC state and REQUIRE it to succeed before
* touching the block again - never program without confirmed unlock + ECC. */
if(t>0){
if(nand_reset()!=0) continue;
if(set_features()!=0) continue;
}
er = block_erase(page);
if(er) continue; /* erase fail -> retry (re-inits) */
pr = 0;
for(k=0;k<64u;k++){ pr = program_page(page+k, (u8*)(src + k*PAGE_SZ)); if(pr) break; }
if(pr) continue; /* program fail -> retry */
/* verify every page against the source; a READ failure fails the attempt (stale rb
* must never be allowed to compare-equal and pass). */
pr = 0;
for(k=0;k<64u && !pr;k++){
if(read_page(page+k, 0, rb, PAGE_SZ)!=0){ pr = 1; break; } /* read error -> retry */
for(i=0;i<PAGE_SZ;i++){ if(rb[i] != src[k*PAGE_SZ+i]){ pr = 1; break; } }
}
if(!pr){ *tries_out = t+1u; return 0; } /* verified good */
}
*tries_out = MAXTRIES;
return -1; /* persistent failure -> fail closed */
}
__attribute__((section(".text.entry"))) void my_write(void){
volatile u32 *dbg=(volatile u32*)0xa0a00000u;
u32 lb=0, pb=START_BLOCK, skipped=0, retried=0, maxtries=0, feat=0, tries;
u32 nbad=0, badlist[MAXBAD], b;
int rr;
for(lb=0; lb<256u; lb++) dbg[lb]=0; /* clear the whole 1KB dbg region */
lb=0;
dbg[0]=0x4004E005u; /* magic: my_write5 (portable) ran */
mux_sfc_pins(); set_clock(); sfc_reset_regs(); cdt_init();
dbg[3]=(u32)nand_reset();
dbg[4]=(u32)set_features();
cmd(CMD_GET_FEATURE,1,ADDR_FEATURE,1,0,1,0); rd(&feat,1); dbg[15]=feat;
dbg[5]=START_BLOCK; dbg[6]=NLOGBLOCKS;
/* ABORT if the NAND/ECC state didn't come up - never write blind. */
if(dbg[3]!=0 || dbg[4]!=0 || (feat & 0x10u)==0){
dbg[16]=0xDEAD0001u; /* init-fail abort code */
dbg[9]=0x55555555u; return;
}
/* ---- PORTABLE SCAN PASS ------------------------------------------------------------
* Learn THIS unit's factory-bad blocks from their OOB bad-marker (byte0 of page0 spare
* != 0xFF, read with on-die ECC disabled) - the SAME criterion the kernel's mtdblock_bbt
* uses to build the logical->physical map. Replaces the hardcoded SKIP_BLOCK so the mapping
* is correct on ANY device. The identical read is proven by bbscan (it found block 383). */
/* Try to disable on-die ECC so the spare returns raw; record the readback (informational).
* On this NAND ECC may stay enabled (readback still 0x10) yet the marker byte still reads
* RAW - so ECC state is NOT a correctness gate; each marker read is validated per-block. */
cmd(CMD_SET_FEATURE,1,ADDR_FEATURE,1,0,1,1); { u32 z=0; wr(&z); }
cmd(CMD_GET_FEATURE,1,ADDR_FEATURE,1,0,1,0); rd(&feat,1); dbg[22]=feat;
for(b=START_BLOCK; b<PART_END; b++){
int v = oob_verdict(b);
if(v < 0){ dbg[16]=0xDEAD0006u; dbg[17]=b; /* marker unreadable/ambiguous -> fail closed */
dbg[9]=0x55555555u; return; }
if(v == 1){ if(nbad < MAXBAD){ badlist[nbad]=b; dbg[40u+nbad]=b; } /* list -> dbg[40..40+MAXBAD) */
nbad++; }
}
dbg[20]=nbad;
/* More bad blocks than the image can absorb -> dead NAND or a mis-scan. Fail closed. */
if(nbad > MAXBAD){ dbg[16]=0xDEAD0004u; dbg[9]=0x55555555u; return; }
/* Re-enable on-die ECC + re-assert block-unlock for the program/verify pass; REQUIRE it. */
rr = set_features();
cmd(CMD_GET_FEATURE,1,ADDR_FEATURE,1,0,1,0); rd(&feat,1); dbg[21]=feat;
if(rr!=0 || (feat & 0x10u)==0){ dbg[16]=0xDEAD0005u; dbg[9]=0x55555555u; return; }
/* ------------------------------------------------------------------------------------ */
while(lb<NLOGBLOCKS){
if(is_bad(pb, badlist, nbad)){ skipped++; pb++; continue; } /* scanned factory-bad block */
if(pb>=PART_END){ dbg[16]=0xDEAD0002u; dbg[17]=pb; dbg[18]=lb;
dbg[9]=0x55555555u; return; } /* out of physical space -> abort */
tries=0;
rr = write_block_verify(pb, (const u8*)(SRC + (u32)lb*64u*PAGE_SZ), &tries);
if(rr){ /* FAIL CLOSED */
dbg[16]=0xDEAD0003u; /* persistent block-write failure */
dbg[17]=pb; dbg[18]=lb; dbg[19]=tries;
dbg[9]=0x55555555u; return; /* stop - do NOT continue mis-mapped */
}
if(tries>1u){ retried++; if(tries>maxtries) maxtries=tries; }
lb++; pb++;
dbg[1]=lb; /* progress */
dbg[11]=pb;
}
dbg[7]=0; /* 0 = all blocks written+verified */
dbg[8]=0;
dbg[10]=skipped; /* bad blocks skipped within the written span (<= dbg[20]=nbad) */
dbg[11]=pb; /* last physical block +1 */
dbg[12]=*(volatile u32*)SRC; /* first source word */
dbg[13]=r32(CPM_BASE+CPM_SSICDR);
dbg[16]=0x600DF10Cu; /* SUCCESS sentinel */
dbg[17]=retried; /* # blocks that needed a retry */
dbg[18]=maxtries; /* worst-case retry count */
dbg[9]=0x55555555u; /* DONE - written LAST */
}
BIN
View File
Binary file not shown.
Executable
+96
View File
@@ -0,0 +1,96 @@
#!/bin/sh
# diskOS installer - one-time setup.
#
# Creates a local Python virtual environment (.venv) next to this script and installs the two
# pip dependencies (pyusb, pycryptodome) into it. After this you run the tool with ./diskos-installer.
#
# What this does NOT install (they come from your system, not from us):
# - Python 3 itself (install via your OS package manager if missing)
# - Tk/tkinter (only needed for the GRAPHICAL installer; CLI works without it)
# - libusb-1.0 (needed to talk to the device in mask-ROM mode)
# The script checks for these and tells you exactly what to install if any are missing.
set -eu
HERE=$(CDPATH= cd "$(dirname "$0")" && pwd)
cd "$HERE"
# Do NOT run this as root. The installer keeps per-user state and a saved recovery image under your
# home directory; running setup as root would create them root-owned and in the wrong place.
if [ "$(id -u)" = "0" ]; then
echo "error: don't run install.sh as root (no sudo). Run it as your normal user;" >&2
echo " only the one-time udev rule needs root (see README, 'USB permissions')." >&2
exit 1
fi
# Scratch file for capturing venv-creation errors: created private + removed on exit, never a
# fixed /tmp path (a predictable name in a world-writable dir invites a symlink attack).
ERRTMP=$(mktemp "${TMPDIR:-/tmp}/diskos_venv.XXXXXX") || { echo "error: mktemp failed" >&2; exit 1; }
trap 'rm -f "$ERRTMP"' EXIT INT TERM
# ---- locate a usable Python 3 -------------------------------------------------
PY=""
for c in python3 python; do
if command -v "$c" >/dev/null 2>&1; then
if "$c" -c 'import sys; sys.exit(0 if sys.version_info[:2] >= (3, 8) else 1)' 2>/dev/null; then
PY=$(command -v "$c"); break
fi
fi
done
if [ -z "$PY" ]; then
echo "error: Python 3.8+ not found." >&2
echo " Debian/Ubuntu: sudo apt install python3 python3-venv" >&2
echo " Fedora: sudo dnf install python3" >&2
echo " macOS: brew install python3 (or install from python.org)" >&2
exit 1
fi
echo "==> using $("$PY" --version 2>&1) at $PY"
# ---- create the venv ----------------------------------------------------------
if [ ! -x "$HERE/.venv/bin/python" ] && [ ! -x "$HERE/.venv/Scripts/python.exe" ]; then
echo "==> creating virtual environment in .venv/"
if ! "$PY" -m venv "$HERE/.venv" 2>"$ERRTMP"; then
echo "error: could not create the virtual environment:" >&2
sed 's/^/ /' "$ERRTMP" >&2 2>/dev/null || true
echo " Debian/Ubuntu often needs: sudo apt install python3-venv" >&2
exit 1
fi
else
echo "==> reusing existing .venv/"
fi
VENV_PY="$HERE/.venv/bin/python"
[ -x "$VENV_PY" ] || VENV_PY="$HERE/.venv/Scripts/python.exe" # windows layout
# ---- install pinned dependencies ---------------------------------------------
echo "==> installing dependencies (pyusb, pycryptodome)"
"$VENV_PY" -m pip install --upgrade pip >/dev/null 2>&1 || true
"$VENV_PY" -m pip install -r "$HERE/requirements.txt"
# ---- capability checks (warn, do not fail) -----------------------------------
echo "==> checking optional system components"
# Tk (GUI only). A venv inherits the base interpreter's tkinter, so this reflects the system Python.
if "$VENV_PY" -c 'import tkinter' 2>/dev/null; then
echo " ok: tkinter present - the graphical installer will work"
else
echo " note: tkinter NOT found - the GRAPHICAL installer will not run (the CLI still works)."
echo " To enable the GUI, install your system's Tk package, then re-run this script:"
echo " Debian/Ubuntu: sudo apt install python3-tk"
echo " Fedora: sudo dnf install python3-tkinter"
echo " macOS: brew install python-tk (or use python.org's Python, which bundles Tk)"
fi
# libusb-1.0 backend for pyusb (needed to see the device in mask-ROM mode).
if "$VENV_PY" -c 'import ctypes.util,sys; sys.exit(0 if ctypes.util.find_library("usb-1.0") else 1)' 2>/dev/null; then
echo " ok: libusb-1.0 present - device detection will work"
else
echo " note: libusb-1.0 NOT found - the tool cannot detect the device until you install it:"
echo " Debian/Ubuntu: sudo apt install libusb-1.0-0"
echo " Fedora: sudo dnf install libusbx"
echo " macOS: brew install libusb"
fi
echo
echo "Setup complete. Run the installer with:"
echo " ./diskos-installer doctor # check host + tools + device"
echo " ./diskos-installer gui # graphical installer (needs tkinter)"
echo " ./diskos-installer --help # all commands"
+27
View File
@@ -0,0 +1,27 @@
Copyright 2009–2017 Wander Lairson Costa
Copyright 2009–2021 PyUSB contributors
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. 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.
3. Neither the name of the copyright holder 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.
+396
View File
@@ -0,0 +1,396 @@
Attribution 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution 4.0 International Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution 4.0 International Public License ("Public License"). To the
extent this Public License may be interpreted as a contract, You are
granted the Licensed Rights in consideration of Your acceptance of
these terms and conditions, and the Licensor grants You such rights in
consideration of benefits the Licensor receives from making the
Licensed Material available under these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
d. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
e. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
f. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
g. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
h. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
i. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
j. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
k. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
4. If You Share Adapted Material You produce, the Adapter's
License You apply must not prevent recipients of the Adapted
Material from complying with this Public License.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material; and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.
+339
View File
@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
+502
View File
@@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
+17
View File
@@ -0,0 +1,17 @@
TJpgDec - Tiny JPEG Decompressor - license (verbatim from the source header shipped in LVGL)
/*----------------------------------------------------------------------------/
/ TJpgDec - Tiny JPEG Decompressor R0.03 (C)ChaN, 2021
/-----------------------------------------------------------------------------/
/ The TJpgDec is a generic JPEG decompressor module for tiny embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following terms.
/
/ Copyright (C) 2021, ChaN, all right reserved.
/
/ * The TJpgDec module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/-----------------------------------------------------------------------------*/
+114
View File
@@ -0,0 +1,114 @@
Dropbear contains a number of components from different sources, hence there
are a few licenses and authors involved. All licenses are fairly
non-restrictive.
The majority of code is written by Matt Johnston, under the license below.
Portions of the client-mode work are (c) 2004 Mihnea Stoenescu, under the
same license:
Copyright (c) 2002-2020 Matt Johnston
Portions copyright (c) 2004 Mihnea Stoenescu
All rights reserved.
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.
=====
LibTomCrypt and LibTomMath are written by Tom St Denis and others, see
libtomcrypt/LICENSE and libtommath/LICENSE.
=====
sshpty.c is taken from OpenSSH 3.5p1,
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
"As far as I am concerned, the code I have written for this software
can be used freely for any purpose. Any derived versions of this
software must be clearly marked as such, and if the derived work is
incompatible with the protocol description in the RFC file, it must be
called by a name other than "ssh" or "Secure Shell". "
=====
loginrec.c
loginrec.h
atomicio.h
atomicio.c
and strlcat() (included in util.c) are from OpenSSH 3.6.1p2, and are licensed
under the 2 point BSD license.
loginrec is written primarily by Andre Lucas, atomicio.c by Theo de Raadt.
strlcat() is (c) Todd C. Miller
=====
Import code in keyimport.c is modified from PuTTY's import.c, licensed as
follows:
PuTTY is copyright 1997-2003 Simon Tatham.
Portions copyright Robert de Bath, Joris van Rantwijk, Delian
Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
Justin Bradford, and CORE SDI S.A.
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 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.
=====
curve25519.c:
Modified TweetNaCl version 20140427, a self-contained public-domain C library.
https://tweetnacl.cr.yp.to/
Contributors (alphabetical order)
Daniel J. Bernstein, University of Illinois at Chicago and Technische
Universiteit Eindhoven
Bernard van Gastel, Radboud Universiteit Nijmegen
Wesley Janssen, Radboud Universiteit Nijmegen
Tanja Lange, Technische Universiteit Eindhoven
Peter Schwabe, Radboud Universiteit Nijmegen
Sjaak Smetsers, Radboud Universiteit Nijmegen
Acknowledgments
This work was supported by the U.S. National Science Foundation under grant
1018836. "Any opinions, findings, and conclusions or recommendations expressed
in this material are those of the author(s) and do not necessarily reflect the
views of the National Science Foundation."
This work was supported by the Netherlands Organisation for Scientific
Research (NWO) under grant 639.073.005 and Veni 2013 project 13114.
+17
View File
@@ -0,0 +1,17 @@
MIT License
Copyright (c) 2010 Serge Zaitsev
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.
+8
View File
@@ -0,0 +1,8 @@
MIT licence
Copyright (c) 2021 LVGL Kft
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.
+34
View File
@@ -0,0 +1,34 @@
musl libc - license
====================
The diskOS UI binary (`payload/mq_ui`) is statically linked against musl libc.
musl as a whole is licensed under the following standard MIT license:
----------------------------------------------------------------------
Copyright © 2005-2020 Rich Felker, et al.
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.
----------------------------------------------------------------------
The musl COPYRIGHT file additionally credits ~80 individual authors and notes
that certain files are, or were, licensed under compatible permissive terms
(BSD, ISC, public domain). The complete, authoritative COPYRIGHT file (including
the full author list and per-file notes) is distributed with musl and available
at: https://git.musl-libc.org/cgit/musl/plain/COPYRIGHT
+22
View File
@@ -0,0 +1,22 @@
QR Code generator library - license (verbatim from the source header shipped in LVGL)
QR Code generator library (C)
Copyright (c) Project Nayuki. (MIT License)
https://www.nayuki.io/page/qr-code-generator-library
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.
+15
View File
@@ -0,0 +1,15 @@
Font Awesome Free glyphs are embedded in the diskOS UI binary (payload/mq_ui) via LVGL's built-in
symbol font (LV_SYMBOL_*). Font Awesome Free licensing:
- Fonts: SIL OFL 1.1
- Icons: CC BY 4.0
- Code: MIT
The verbatim texts are shipped in this directory:
- OFL-1.1-FontAwesome.txt = Font Awesome's own LICENSE.txt (Copyright (c) Fonticons, Inc.),
which contains the full SIL OFL 1.1 text (with the "Font Awesome"
reserved font name) plus the MIT code license and the CC BY reference.
- CC-BY-4.0.txt = the full Creative Commons Attribution 4.0 International legal code.
Canonical sources:
- https://github.com/FortAwesome/Font-Awesome (LICENSE.txt)
- https://creativecommons.org/licenses/by/4.0/legalcode.txt
+165
View File
@@ -0,0 +1,165 @@
Fonticons, Inc. (https://fontawesome.com)
--------------------------------------------------------------------------------
Font Awesome Free License
Font Awesome Free is free, open source, and GPL friendly. You can use it for
commercial projects, open source projects, or really almost whatever you want.
Full Font Awesome Free license: https://fontawesome.com/license/free.
--------------------------------------------------------------------------------
# Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/)
The Font Awesome Free download is licensed under a Creative Commons
Attribution 4.0 International License and applies to all icons packaged
as SVG and JS file types.
--------------------------------------------------------------------------------
# Fonts: SIL OFL 1.1 License
In the Font Awesome Free download, the SIL OFL license applies to all icons
packaged as web and desktop font files.
Copyright (c) 2024 Fonticons, Inc. (https://fontawesome.com)
with Reserved Font Name: "Font Awesome".
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
SIL OPEN FONT LICENSE
Version 1.1 - 26 February 2007
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting — in part or in whole — any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
--------------------------------------------------------------------------------
# Code: MIT License (https://opensource.org/licenses/MIT)
In the Font Awesome Free download, the MIT license applies to all non-font and
non-icon files.
Copyright 2024 Fonticons, Inc.
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.
--------------------------------------------------------------------------------
# Attribution
Attribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font
Awesome Free files already contain embedded comments with sufficient
attribution, so you shouldn't need to do anything additional when using these
files normally.
We've kept attribution comments terse, so we ask that you do not actively work
to remove them from files, especially code. They're a great way for folks to
learn about Font Awesome.
--------------------------------------------------------------------------------
# Brand Icons
All brand icons are trademarks of their respective owners. The use of these
trademarks does not indicate endorsement of the trademark holder by Font
Awesome, nor vice versa. **Please do not use brand logos for any purpose except
to represent the company, product, or service to which they refer.**
+92
View File
@@ -0,0 +1,92 @@
Copyright 2011 The Montserrat Project Authors (https://github.com/JulietaUla/Montserrat), with Reserved Font Name 'Montserrat'.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
+93
View File
@@ -0,0 +1,93 @@
Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'.
Source Han Sans is a trademark of Adobe in the United States and/or other countries.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
+279
View File
@@ -0,0 +1,279 @@
A. HISTORY OF THE SOFTWARE
==========================
Python was created in the early 1990s by Guido van Rossum at Stichting
Mathematisch Centrum (CWI, see https://www.cwi.nl) in the Netherlands
as a successor of a language called ABC. Guido remains Python's
principal author, although it includes many contributions from others.
In 1995, Guido continued his work on Python at the Corporation for
National Research Initiatives (CNRI, see https://www.cnri.reston.va.us)
in Reston, Virginia where he released several versions of the
software.
In May 2000, Guido and the Python core development team moved to
BeOpen.com to form the BeOpen PythonLabs team. In October of the same
year, the PythonLabs team moved to Digital Creations, which became
Zope Corporation. In 2001, the Python Software Foundation (PSF, see
https://www.python.org/psf/) was formed, a non-profit organization
created specifically to own Python-related Intellectual Property.
Zope Corporation was a sponsoring member of the PSF.
All Python releases are Open Source (see https://opensource.org for
the Open Source Definition). Historically, most, but not all, Python
releases have also been GPL-compatible; the table below summarizes
the various releases.
Release Derived Year Owner GPL-
from compatible? (1)
0.9.0 thru 1.2 1991-1995 CWI yes
1.3 thru 1.5.2 1.2 1995-1999 CNRI yes
1.6 1.5.2 2000 CNRI no
2.0 1.6 2000 BeOpen.com no
1.6.1 1.6 2001 CNRI yes (2)
2.1 2.0+1.6.1 2001 PSF no
2.0.1 2.0+1.6.1 2001 PSF yes
2.1.1 2.1+2.0.1 2001 PSF yes
2.1.2 2.1.1 2002 PSF yes
2.1.3 2.1.2 2002 PSF yes
2.2 and above 2.1.1 2001-now PSF yes
Footnotes:
(1) GPL-compatible doesn't mean that we're distributing Python under
the GPL. All Python licenses, unlike the GPL, let you distribute
a modified version without making your changes open source. The
GPL-compatible licenses make it possible to combine Python with
other software that is released under the GPL; the others don't.
(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
because its license has a choice of law clause. According to
CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
is "not incompatible" with the GPL.
Thanks to the many outside volunteers who have worked under Guido's
direction to make these releases possible.
B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
===============================================================
Python software and documentation are licensed under the
Python Software Foundation License Version 2.
Starting with Python 3.8.6, examples, recipes, and other code in
the documentation are dual licensed under the PSF License Version 2
and the Zero-Clause BSD license.
Some software incorporated into Python is under different licenses.
The licenses are listed with code falling under that license.
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
--------------------------------------------
1. This LICENSE AGREEMENT is between the Python Software Foundation
("PSF"), and the Individual or Organization ("Licensee") accessing and
otherwise using this software ("Python") in source or binary form and
its associated documentation.
2. Subject to the terms and conditions of this License Agreement, PSF hereby
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python alone or in any derivative version,
provided, however, that PSF's License Agreement and PSF's notice of copyright,
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Python Software Foundation;
All Rights Reserved" are retained in Python alone or in any derivative version
prepared by Licensee.
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python.
4. PSF is making Python available to Licensee on an "AS IS"
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
7. Nothing in this License Agreement shall be deemed to create any
relationship of agency, partnership, or joint venture between PSF and
Licensee. This License Agreement does not grant permission to use PSF
trademarks or trade name in a trademark sense to endorse or promote
products or services of Licensee, or any third party.
8. By copying, installing or otherwise using Python, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
-------------------------------------------
BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
Individual or Organization ("Licensee") accessing and otherwise using
this software in source or binary form and its associated
documentation ("the Software").
2. Subject to the terms and conditions of this BeOpen Python License
Agreement, BeOpen hereby grants Licensee a non-exclusive,
royalty-free, world-wide license to reproduce, analyze, test, perform
and/or display publicly, prepare derivative works, distribute, and
otherwise use the Software alone or in any derivative version,
provided, however, that the BeOpen Python License is retained in the
Software, alone or in any derivative version prepared by Licensee.
3. BeOpen is making the Software available to Licensee on an "AS IS"
basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
5. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
6. This License Agreement shall be governed by and interpreted in all
respects by the law of the State of California, excluding conflict of
law provisions. Nothing in this License Agreement shall be deemed to
create any relationship of agency, partnership, or joint venture
between BeOpen and Licensee. This License Agreement does not grant
permission to use BeOpen trademarks or trade names in a trademark
sense to endorse or promote products or services of Licensee, or any
third party. As an exception, the "BeOpen Python" logos available at
http://www.pythonlabs.com/logos.html may be used according to the
permissions granted on that web page.
7. By copying, installing or otherwise using the software, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
---------------------------------------
1. This LICENSE AGREEMENT is between the Corporation for National
Research Initiatives, having an office at 1895 Preston White Drive,
Reston, VA 20191 ("CNRI"), and the Individual or Organization
("Licensee") accessing and otherwise using Python 1.6.1 software in
source or binary form and its associated documentation.
2. Subject to the terms and conditions of this License Agreement, CNRI
hereby grants Licensee a nonexclusive, royalty-free, world-wide
license to reproduce, analyze, test, perform and/or display publicly,
prepare derivative works, distribute, and otherwise use Python 1.6.1
alone or in any derivative version, provided, however, that CNRI's
License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
1995-2001 Corporation for National Research Initiatives; All Rights
Reserved" are retained in Python 1.6.1 alone or in any derivative
version prepared by Licensee. Alternately, in lieu of CNRI's License
Agreement, Licensee may substitute the following text (omitting the
quotes): "Python 1.6.1 is made available subject to the terms and
conditions in CNRI's License Agreement. This Agreement together with
Python 1.6.1 may be located on the internet using the following
unique, persistent identifier (known as a handle): 1895.22/1013. This
Agreement may also be obtained from a proxy server on the internet
using the following URL: http://hdl.handle.net/1895.22/1013".
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python 1.6.1 or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python 1.6.1.
4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
7. This License Agreement shall be governed by the federal
intellectual property law of the United States, including without
limitation the federal copyright law, and, to the extent such
U.S. federal law does not apply, by the law of the Commonwealth of
Virginia, excluding Virginia's conflict of law provisions.
Notwithstanding the foregoing, with regard to derivative works based
on Python 1.6.1 that incorporate non-separable material that was
previously distributed under the GNU General Public License (GPL), the
law of the Commonwealth of Virginia shall govern this License
Agreement only as to issues arising under or with respect to
Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
License Agreement shall be deemed to create any relationship of
agency, partnership, or joint venture between CNRI and Licensee. This
License Agreement does not grant permission to use CNRI trademarks or
trade name in a trademark sense to endorse or promote products or
services of Licensee, or any third party.
8. By clicking on the "ACCEPT" button where indicated, or by copying,
installing or otherwise using Python 1.6.1, Licensee agrees to be
bound by the terms and conditions of this License Agreement.
ACCEPT
CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
--------------------------------------------------
Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
The Netherlands. All rights reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ZERO-CLAUSE BSD LICENSE FOR CODE IN THE PYTHON DOCUMENTATION
----------------------------------------------------------------------
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
+42
View File
@@ -0,0 +1,42 @@
# Bundled license texts
This directory carries the full license texts for the third-party components the diskOS installer
bundles. See `../NOTICE.md` for the component→license mapping and the static-linking obligations.
| Component (bundled) | License | Full text |
|---|---|---|
| usbboot | GPL-2.0-or-later | [`GPL-2.0.txt`](GPL-2.0.txt) |
| squashfs-tools 4.6.1 | GPL-2.0 | [`GPL-2.0.txt`](GPL-2.0.txt) |
| liblzo2 (static in mksquashfs/unsquashfs) | GPL-2.0-or-later | [`GPL-2.0.txt`](GPL-2.0.txt) |
| libusb-1.0.27 (static in usbboot) | LGPL-2.1 | [`LGPL-2.1.txt`](LGPL-2.1.txt) |
| glibc (static in usbboot/mksquashfs/unsquashfs) | LGPL-2.1-or-later | [`LGPL-2.1.txt`](LGPL-2.1.txt); corresponding source in `../corresponding-source/glibc_2.39*` (see `../NOTICE.md` for the relink path) |
| PyInstaller bootloader (only for a self-built onefile) | GPL-2.0 + bootloader exception | [`GPL-2.0.txt`](GPL-2.0.txt) + exception note in `../NOTICE.md` |
| zlib / liblzma (static in squashfs-tools) | zlib / public-domain | permissive notices travel with the squashfs-tools sources the build script fetches |
| pyusb | BSD-3-Clause | [`BSD-3-Clause-pyusb.txt`](BSD-3-Clause-pyusb.txt) (verbatim from pyusb 1.3.1) |
| pycryptodome | BSD-2-Clause + public-domain | [`pycryptodome-LICENSE.txt`](pycryptodome-LICENSE.txt) (verbatim from pycryptodome 3.23.0) |
| CPython | Python Software Foundation License | [`PSF-Python.txt`](PSF-Python.txt) (verbatim from the bundled CPython) |
| LVGL (diskOS UI) | MIT | [`MIT-LVGL.txt`](MIT-LVGL.txt) (verbatim from `native-ui/lvgl/LICENCE.txt`) |
| JSMN (diskOS UI JSON parser) | MIT | [`MIT-JSMN.txt`](MIT-JSMN.txt) (verbatim from `native-ui/ipodos-native/jsmn.h`, © 2010 Serge Zaitsev) |
| Font Awesome Free glyphs (via LVGL `LV_SYMBOL_*`) | OFL-1.1 (fonts) + CC-BY-4.0 (icons) | [`OFL-1.1-FontAwesome.txt`](OFL-1.1-FontAwesome.txt) (Fonticons' own LICENSE.txt: full OFL-1.1 + MIT) + [`CC-BY-4.0.txt`](CC-BY-4.0.txt) |
| musl libc (static in diskOS UI `mq_ui`) | MIT | [`MIT-musl.txt`](MIT-musl.txt) |
| SQLite (amalgamation in `mq_ui`) | Public domain | https://sqlite.org/copyright.html (no license text required) |
| QR Code generator, Nayuki (via LVGL, in `mq_ui`) | MIT | [`MIT-qrcodegen.txt`](MIT-qrcodegen.txt) (verbatim from the LVGL source header) |
| TJpgDec, ChaN (via LVGL, in `mq_ui`) | BSD-style | [`LICENSE-TJpgDec.txt`](LICENSE-TJpgDec.txt) (verbatim from the LVGL source header) |
| Montserrat font (via LVGL built-in fonts, in `mq_ui`) | OFL-1.1 | [`OFL-1.1-Montserrat.txt`](OFL-1.1-Montserrat.txt) |
| Source Han Sans SC (CJK fallback font in `mq_ui`) | OFL-1.1 | [`OFL-1.1-SourceHanSans.txt`](OFL-1.1-SourceHanSans.txt) |
| MD5, Peslyak/"Solar Designer" (in `mq_ui`) | Public domain | in the (unpublished) UI source; no license text required |
| dropbearmulti (Dropbear SSH 2022.83, Debug Mode) | MIT-style | [`LICENSE-dropbear.txt`](LICENSE-dropbear.txt) (verbatim upstream) |
| disc_spl_lpddr3.bin (X2000 stage-1 SPL) | GPL-2.0 | [`GPL-2.0.txt`](GPL-2.0.txt); corresponding source in `../spl-src/` (see `../SPL_SOURCE.md`) |
All texts above are included **verbatim from the actual upstream sources** (not hand-written), with
their real copyright lines. **Copyleft texts (GPL-2.0, LGPL-2.1)** carry the redistribution
obligations (corresponding source + relink path; see `../NOTICE.md`). The only text not vendored here
is zlib/liblzma's permissive notice, which travels inside the squashfs-tools source the build script
fetches.
## diskOS's own license
The **Python installer, build scripts, and docs** are licensed **MIT** - `Copyright (c) 2026 diskOS
contributors`. See [`../LICENSE`](../LICENSE). The **diskOS UI (`payload/mq_ui`)** ships as a
**binary-only** component (source not yet published, not MIT); see the README's *License* section.
Its embedded third-party notices - LVGL (MIT), JSMN (MIT), Font Awesome Free (OFL-1.1 fonts /
CC-BY-4.0 icons) - ship in this directory.
+40
View File
@@ -0,0 +1,40 @@
# Third-party libraries bundled in a self-built onefile
> **Scope:** this applies **only if you build a self-contained PyInstaller onefile yourself**
> (`build/build.sh`). The **published diskOS release does not ship such a binary** - it distributes
> source, and the Python runtime + these native libraries come from *your* system Python (see
> [`../NOTICE.md`](../NOTICE.md)), so this project does not redistribute them. If you *do* build and
> redistribute the onefile, **you** become the redistributor of everything it embeds.
>
> The onefile embeds the CPython runtime plus **~90 native shared libraries** its GUI/runtime pulls
> in (CPython + Tkinter GUI + pycryptodome + pyusb chains). The table below lists the principal
> permissive families with verbatim texts in [`bundled/`](bundled/); it is **illustrative, not a
> complete manifest** of all ~90 entries. To regenerate the full list for a given build, walk the
> extracted onefile's shared objects and map each to its distribution package. Note the GUI chain
> also pulls in **libudev (LGPL-2.1)** and **freetype (FTL/GPL dual)** - a CLI-only build
> (`excludes=['tkinter']`) avoids both.
| Bundled library (`.so`) | License | Text |
|---|---|---|
| `libcrypto.so.3` (OpenSSL 3) | Apache-2.0 | [`bundled/libcrypto.copyright.txt`](bundled/libcrypto.copyright.txt) |
| `libbrotlicommon.so.1`, `libbrotlidec.so.1` (Brotli) | MIT | [`bundled/libbrotli.copyright.txt`](bundled/libbrotli.copyright.txt) |
| `libbsd.so.0` | BSD-2/3-Clause, ISC, etc. | [`bundled/libbsd.copyright.txt`](bundled/libbsd.copyright.txt) |
| `libbz2.so.1.0` (bzip2) | bzip2 (BSD-style) | [`bundled/libbz2.copyright.txt`](bundled/libbz2.copyright.txt) |
| `libcap.so.2` | BSD-3-Clause OR GPL-2.0-only (used under BSD) | [`bundled/libcap.copyright.txt`](bundled/libcap.copyright.txt) |
| `libX11.so.6` | MIT/X11 | [`bundled/libX11.copyright.txt`](bundled/libX11.copyright.txt) |
| `libXau.so.6` | MIT/X11 | [`bundled/libXau.copyright.txt`](bundled/libXau.copyright.txt) |
| `libXdmcp.so.6` | MIT/X11 | [`bundled/libXdmcp.copyright.txt`](bundled/libXdmcp.copyright.txt) |
| `libXext.so.6` | MIT/X11 | [`bundled/libXext.copyright.txt`](bundled/libXext.copyright.txt) |
| `libXft.so.2` | MIT/X11 | [`bundled/libXft.copyright.txt`](bundled/libXft.copyright.txt) |
| `libXrender.so.1` | MIT/X11 | [`bundled/libXrender.copyright.txt`](bundled/libXrender.copyright.txt) |
| `libXss.so.1` | MIT/X11 | [`bundled/libXss.copyright.txt`](bundled/libXss.copyright.txt) |
| `libBLT.2.5.so.8.6` (BLT, a Tk widget library) | BSD-style | [`bundled/libBLT.copyright.txt`](bundled/libBLT.copyright.txt) |
CPython itself is PSF-licensed (see [`PSF-Python.txt`](PSF-Python.txt)); the Python packages `pyusb`
(BSD) and `pycryptodome` (BSD / public-domain) are covered in [`README.md`](README.md).
These libraries are present **only in a self-built onefile**. The published release runs the
installer **from source** with your own Python (`./install.sh` then `./diskos-installer`), where they
come from *your* system's Python and are **not redistributed by this project**. (`bash build/build.sh`
is the separate, optional step that produces the onefile - if you run *that* and redistribute the
result, the obligations above become yours.)
+258
View File
@@ -0,0 +1,258 @@
This package was debianized by Gordon Russell <g.russell@dcs.napier.ac.uk> on
Thu, 12 Mar 1998 11:19:54 +0000.
It was originally downloaded from http://sourceforge.net/projects/blt
Now it's downloaded from http://sourceforge.net/projects/wize
Files library/dd_protocols/* were deleted from the original distribution
because they are non-free.
Files: *
Copyright: 1991-1998 by Lucent Technologies.
License: MIT-1
Files: generic/bltArrayObj.c
Copyright: 2000 Silicon Metrics, Inc.
License: MIT-4
Files: generic/bltHash.c, generic/bltHash.in
Copyright (c) 1991-1993 The Regents of the University of California.
Copyright (c) 1994 Sun Microsystems, Inc.
License: Tcl
Comment: Here and below the Tcl licence is omitted but the code or its
portions are clearly taken from the Tcl/Tk distributions.
Copyright: 2001 Silicon Metrics Corporation.
License: MIT-4
Files: generic/blt.h, generic/bltUnixMain.c, generic/bltWinDraw.c, generic/bltWinPrnt.c, generic/bltWinUtil.c
Copyright: 1991-1998 by Bell Labs Innovations for Lucent Technologies
License: MIT-1
Files: generic/bltInterp.h
Copyright: 1987-1993 The Regents of the University of California.
Copyright: 1993-1997 Lucent Technologies.
Copyright: 1994-1998 Sun Microsystems, Inc.
License: Tcl
Files: generic/bltObjConfig.c, generic/bltObjConfig.h, generic/bltOldConfig.c
Copyright: 1990-1994 The Regents of the University of California
Copyright: 1994-1997 Sun Microsystems, Inc
License: Tcl
Files: generic/bltParse.c
Copyright: 1987-1993 The Regents of the University of California
Copyright: 1994-1998 Sun Microsystems, Inc.
License: Tcl
Files: generic/bltPool.c
Copyright: 2001 Silicon Metrics, Inc.
License: MIT-4
Files: generic/bltScrollbar.c
Copyright: 1990-1994 The Regents of the University of California
Copyright: 1994-1995 Sun Microsystems, Inc.
License: Tcl
Files: generic/bltTed.c
Copyright: 1995 by AT&T Bell Laboratories
License: MIT-5
Files: generic/bltUnixMain.c
Copyright: 1993 The Regents of the University of California
License: MIT-6
Copyright: 1991-1998 by Bell Labs Innovations for Lucent Technologies
License: MIT-1
Files: generic/bltUnixPipe.c, generic/bltWinDde.c
Copyright: 1997 by Sun Microsystems, Inc.
License: Tcl
Files: generic/tkButton.c, generic/tkFrame.c, generic/tkMenubutton.c, generic/tkScrollbar.c
Copyright: 1990-1994 The Regents of the University of California
Copyright: 1994-1995 Sun Microsystems, Inc.
License: Tcl
Files: generic/tkConsole.c, man/Blt_Tree.man3
Copyright: 1995-1996 Sun Microsystems, Inc.
License: Tcl
Files: html/tabset.html, html/tree.html, html/treeview.html
Copyright: 1995-1997 Roger E. Critchlow Jr.
License: MIT-1
Comment: These files are created by the Roger E. Critchlow Jr. tool, which
automatically added the copyright line.
Files: library/bltCanvEps.pro
Copyright: 1991-1997 Bell Labs Innovations for Lucent Technologies`
License: MIT-1
Files: library/bltGraph.pro
Copyright: 1989-1992 Regents of the University of California
License: MIT-6
Copyright: 1991-1997 Bell Labs Innovations for Lucent Technologies
License: MIT-1
Files: man/*:
Copyright: 1991-1998 by Bell Labs Innovations for Lucent Technologies
License: MIT-1
Files: man/Blt_Vector.man3, man/tree.mann, man/vector.mann
Copyright: 1991-1997 by Lucent Technologies, Inc.
License: MIT-1
Files: man/hierbox.mann, man/hiertable.mann, man/treeview.mann
Copyright: 2001-2002 by Silicon Metrics Corporation.
License: MIT-4
Files: win/X11/keysymdef.h, win/X11/keysym.h, win/X11/X.h, win/X11/Xutil.h
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, and the Massachusetts Institute of Technology, Cambridge, Massachusetts
License: MIT-2
Files: win/X11/Xfuncproto.h
Copyright: 1989, 1991 by the Massachusetts Institute of Technology
License: MIT-3
Files: win/X11/Xlib.h
Copyright: 1985, 1986, 1987, 1991 by the Massachusetts Institute of Technology
License: MIT-3
License: MIT-1
to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that both that the
copyright notice and warranty disclaimer appear in supporting documentation,
and that the names of Lucent Technologies any of their entities not be used
in advertising or publicity pertaining to distribution of the software
without specific, written prior permission.
Lucent Technologies disclaims all warranties with regard to this software,
including all implied warranties of merchantability and fitness. In no event
shall Lucent Technologies be liable for any special, indirect or
consequential damages or any damages whatsoever resulting from loss of use,
data or profits, whether in an action of contract, negligence or other
tortuous action, arising out of or in connection with the use or performance
of this software.
License: MIT-2
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
License: MIT-3
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of M.I.T. not be used in advertising
or publicity pertaining to distribution of the software without specific,
written prior permission. M.I.T. makes no representations about the
suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
License: MIT-4
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and warranty
disclaimer appear in supporting documentation, and that the names
of Lucent Technologies any of their entities not be used in
advertising or publicity pertaining to distribution of the software
without specific, written prior permission.
Silicon Metrics disclaims all warranties with regard to this
software, including all implied warranties of merchantability and
fitness. In no event shall Lucent Technologies be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether in
an action of contract, negligence or other tortuous action, arising
out of or in connection with the use or performance of this
software.
License: Tcl
This software is copyrighted by the Regents of the University of
California, Sun Microsystems, Inc., Scriptics Corporation,
and other parties. The following terms apply to all files associated
with the software unless explicitly disclaimed in individual files.
The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
GOVERNMENT USE: If you are acquiring this software on behalf of the
U.S. government, the Government shall have only "Restricted Rights"
in the software and related documentation as defined in the Federal
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
are acquiring the software on behalf of the Department of Defense, the
software shall be classified as "Commercial Computer Software" and the
Government shall have only "Restricted Rights" as defined in Clause
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license.
License: MIT-5
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and warranty
disclaimer appear in supporting documentation, and that the
names of AT&T Bell Laboratories any of their entities not be used
in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
AT&T disclaims all warranties with regard to this software, including
all implied warranties of merchantability and fitness. In no event
shall AT&T be liable for any special, indirect or consequential
damages or any damages whatsoever resulting from loss of use, data
or profits, whether in an action of contract, negligence or other
tortuous action, arising out of or in connection with the use or
performance of this software.
License: MIT-6
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the
above copyright notice and the following two paragraphs appear in
all copies of this software.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+944
View File
@@ -0,0 +1,944 @@
This package was downloaded from
https://xorg.freedesktop.org/releases/individual/lib/
The following is the 'standard copyright' agreed upon by most contributors,
and is currently the canonical license preferred by the X.Org Foundation.
This is a slight variant of the common MIT license form published by the
Open Source Initiative at https://opensource.org/licenses/mit-license.php
Copyright holders of new code should use this license statement where
possible, and insert their name to this list. Please sort by surname
for people, and by the full name for other entities (e.g. Juliusz
Chroboczek sorts before Intel Corporation sorts before Daniel Stone).
See each individual source file or directory for the license that applies
to that file.
Copyright (C) 2003-2006,2008 Jamey Sharp, Josh Triplett
Copyright © 2009 Red Hat, Inc.
Copyright 1990-1992,1999,2000,2004,2009,2010 Oracle and/or its affiliates.
All rights reserved.
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 (including the next
paragraph) 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.
----------------------------------------------------------------------
The following licenses are 'legacy' - usually MIT/X11 licenses with the name
of the copyright holder(s) in the license statement:
Copyright 1984-1994, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
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
OPEN GROUP 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.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
X Window System is a trademark of The Open Group.
----------------------------------------
Copyright 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1994, 1996 X Consortium
Copyright 2000 The XFree86 Project, Inc.
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 X CONSORTIUM 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.
Except as contained in this notice, the name of the X Consortium shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the X Consortium.
Copyright 1985, 1986, 1987, 1988, 1989, 1990, 1991 by
Digital Equipment Corporation
Portions Copyright 1990, 1991 by Tektronix, Inc.
Permission to use, copy, modify and distribute this documentation for
any purpose and without fee is hereby granted, provided that the above
copyright notice appears in all copies and that both that copyright notice
and this permission notice appear in all copies, and that the names of
Digital and Tektronix not be used in in advertising or publicity pertaining
to this documentation without specific, written prior permission.
Digital and Tektronix makes no representations about the suitability
of this documentation for any purpose.
It is provided ``as is'' without express or implied warranty.
----------------------------------------
Copyright (c) 1999-2000 Free Software Foundation, Inc.
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
FREE SOFTWARE FOUNDATION 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.
Except as contained in this notice, the name of the Free Software Foundation
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization from the
Free Software Foundation.
----------------------------------------
Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
All Rights Reserved
This file is a component of an X Window System-specific implementation
of Xcms based on the TekColor Color Management System. TekColor is a
trademark of Tektronix, Inc. The term "TekHVC" designates a particular
color space that is the subject of U.S. Patent No. 4,985,853 (equivalent
foreign patents pending). Permission is hereby granted to use, copy,
modify, sell, and otherwise distribute this software and its
documentation for any purpose and without fee, provided that:
1. This copyright, permission, and disclaimer notice is reproduced in
all copies of this software and any modification thereof and in
supporting documentation;
2. Any color-handling application which displays TekHVC color
cooordinates identifies these as TekHVC color coordinates in any
interface that displays these coordinates and in any associated
documentation;
3. The term "TekHVC" is always used, and is only used, in association
with the mathematical derivations of the TekHVC Color Space,
including those provided in this file and any equivalent pathways and
mathematical derivations, regardless of digital (e.g., floating point
or integer) representation.
Tektronix makes no representation about the suitability of this software
for any purpose. It is provided "as is" and with all faults.
TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
(c) Copyright 1995 FUJITSU LIMITED
This is source code modified by FUJITSU LIMITED under the Joint
Development Agreement for the CDE/Motif PST.
----------------------------------------
Copyright 1992 by Oki Technosystems Laboratory, Inc.
Copyright 1992 by Fuji Xerox Co., Ltd.
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of Oki Technosystems
Laboratory and Fuji Xerox not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.
Oki Technosystems Laboratory and Fuji Xerox make no representations
about the suitability of this software for any purpose. It is provided
"as is" without express or implied warranty.
OKI TECHNOSYSTEMS LABORATORY AND FUJI XEROX DISCLAIM ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL OKI TECHNOSYSTEMS
LABORATORY AND FUJI XEROX BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
OR PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright 1990, 1991, 1992, 1993, 1994 by FUJITSU LIMITED
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of FUJITSU LIMITED
not be used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission.
FUJITSU LIMITED makes no representations about the suitability of
this software for any purpose.
It is provided "as is" without express or implied warranty.
FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright (c) 1995 David E. Wexelblat. All rights reserved
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 DAVID E. WEXELBLAT 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.
Except as contained in this notice, the name of David E. Wexelblat shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from David E. Wexelblat.
----------------------------------------
Copyright 1990, 1991 by OMRON Corporation
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name OMRON not be used in
advertising or publicity pertaining to distribution of the software without
specific, written prior permission. OMRON makes no representations
about the suitability of this software for any purpose. It is provided
"as is" without express or implied warranty.
OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright 1985, 1986, 1987, 1988, 1989, 1990, 1991 by
Digital Equipment Corporation
Portions Copyright 1990, 1991 by Tektronix, Inc
Rewritten for X.org by Chris Lee <clee@freedesktop.org>
Permission to use, copy, modify, distribute, and sell this documentation
for any purpose and without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Chris Lee makes no representations about the suitability for any purpose
of the information in this document. It is provided \`\`as-is'' without
express or implied warranty.
----------------------------------------
Copyright 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
Copyright 1994 by FUJITSU LIMITED
Copyright 1994 by Sony Corporation
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Digital, FUJITSU
LIMITED and Sony Corporation not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.
DIGITAL, FUJITSU LIMITED AND SONY CORPORATION DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL, FUJITSU LIMITED
AND SONY CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright 1991 by the Open Software Foundation
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of Open Software Foundation
not be used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission. Open Software
Foundation makes no representations about the suitability of this
software for any purpose. It is provided "as is" without express or
implied warranty.
OPEN SOFTWARE FOUNDATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL OPEN SOFTWARE FOUNDATIONN BE
LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright 1990, 1991, 1992,1993, 1994 by FUJITSU LIMITED
Copyright 1993, 1994 by Sony Corporation
Permission to use, copy, modify, distribute, and sell this software and
its documentation for any purpose is hereby granted without fee, provided
that the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of FUJITSU LIMITED and Sony Corporation
not be used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission. FUJITSU LIMITED and
Sony Corporation makes no representations about the suitability of this
software for any purpose. It is provided "as is" without express or
implied warranty.
FUJITSU LIMITED AND SONY CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL FUJITSU LIMITED OR SONY CORPORATION BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
USE OR PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright (c) 1993, 1995 by Silicon Graphics Computer Systems, Inc.
Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting
documentation, and that the name of Silicon Graphics not be
used in advertising or publicity pertaining to distribution
of the software without specific prior written permission.
Silicon Graphics makes no representation about the suitability
of this software for any purpose. It is provided "as is"
without any express or implied warranty.
SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
THE USE OR PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright 1991, 1992, 1993, 1994 by FUJITSU LIMITED
Copyright 1993 by Digital Equipment Corporation
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of FUJITSU LIMITED and
Digital Equipment Corporation not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission. FUJITSU LIMITED and Digital Equipment Corporation
makes no representations about the suitability of this software for
any purpose. It is provided "as is" without express or implied
warranty.
FUJITSU LIMITED AND DIGITAL EQUIPMENT CORPORATION DISCLAIM ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
FUJITSU LIMITED AND DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
----------------------------------------
Copyright 1992, 1993 by FUJITSU LIMITED
Copyright 1993 by Fujitsu Open Systems Solutions, Inc.
Copyright 1994 by Sony Corporation
Permission to use, copy, modify, distribute and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of FUJITSU LIMITED,
Fujitsu Open Systems Solutions, Inc. and Sony Corporation not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
FUJITSU LIMITED, Fujitsu Open Systems Solutions, Inc. and
Sony Corporation make no representations about the suitability of
this software for any purpose. It is provided "as is" without
express or implied warranty.
FUJITSU LIMITED, FUJITSU OPEN SYSTEMS SOLUTIONS, INC. AND SONY
CORPORATION DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
IN NO EVENT SHALL FUJITSU OPEN SYSTEMS SOLUTIONS, INC., FUJITSU LIMITED
AND SONY CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
OR PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright 1987, 1988, 1990, 1993 by Digital Equipment Corporation,
Maynard, Massachusetts,
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
----------------------------------------
Copyright 1993 by SunSoft, Inc.
Copyright 1999-2000 by Bruno Haible
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the names of SunSoft, Inc. and
Bruno Haible not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission. SunSoft, Inc. and Bruno Haible make no representations
about the suitability of this software for any purpose. It is
provided "as is" without express or implied warranty.
SunSoft Inc. AND Bruno Haible DISCLAIM ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS, IN NO EVENT SHALL SunSoft, Inc. OR Bruno Haible BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright 1991 by the Open Software Foundation
Copyright 1993 by the TOSHIBA Corp.
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the names of Open Software Foundation and TOSHIBA
not be used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission. Open Software
Foundation and TOSHIBA make no representations about the suitability of this
software for any purpose. It is provided "as is" without express or
implied warranty.
OPEN SOFTWARE FOUNDATION AND TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL OPEN SOFTWARE FOUNDATIONN OR TOSHIBA BE
LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright 1988 by Wyse Technology, Inc., San Jose, Ca.,
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name Wyse not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
WYSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
----------------------------------------
Copyright 1991 by the Open Software Foundation
Copyright 1993, 1994 by the Sony Corporation
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the names of Open Software Foundation and
Sony Corporation not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
Open Software Foundation and Sony Corporation make no
representations about the suitability of this software for any purpose.
It is provided "as is" without express or implied warranty.
OPEN SOFTWARE FOUNDATION AND SONY CORPORATION DISCLAIM ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL OPEN
SOFTWARE FOUNDATIONN OR SONY CORPORATION BE LIABLE FOR ANY SPECIAL,
INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright 1992, 1993 by FUJITSU LIMITED
Copyright 1993 by Fujitsu Open Systems Solutions, Inc.
Permission to use, copy, modify, distribute and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of FUJITSU LIMITED and
Fujitsu Open Systems Solutions, Inc. not be used in advertising or
publicity pertaining to distribution of the software without specific,
written prior permission.
FUJITSU LIMITED and Fujitsu Open Systems Solutions, Inc. makes no
representations about the suitability of this software for any purpose.
It is provided "as is" without express or implied warranty.
FUJITSU LIMITED AND FUJITSU OPEN SYSTEMS SOLUTIONS, INC. DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL FUJITSU OPEN SYSTEMS
SOLUTIONS, INC. AND FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
OF THIS SOFTWARE.
----------------------------------------
Copyright 1993, 1994 by Sony Corporation
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of Sony Corporation
not be used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission.
Sony Corporation makes no representations about the suitability of
this software for any purpose. It is provided "as is" without
express or implied warranty.
SONY CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL SONY CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright 1986, 1998 The Open Group
Copyright (c) 2000 The XFree86 Project, Inc.
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
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
X CONSORTIUM OR THE XFREE86 PROJECT 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.
Except as contained in this notice, the name of the X Consortium or of the
XFree86 Project shall not be used in advertising or otherwise to promote the
sale, use or other dealings in this Software without prior written
authorization from the X Consortium and the XFree86 Project.
----------------------------------------
Copyright 1990, 1991 by OMRON Corporation, NTT Software Corporation,
and Nippon Telegraph and Telephone Corporation
Copyright 1991 by the Open Software Foundation
Copyright 1993 by the FUJITSU LIMITED
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the names of OMRON, NTT Software, NTT, and
Open Software Foundation not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. OMRON, NTT Software, NTT, and Open Software
Foundation make no representations about the suitability of this
software for any purpose. It is provided "as is" without express or
implied warranty.
OMRON, NTT SOFTWARE, NTT, AND OPEN SOFTWARE FOUNDATION
DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
SHALL OMRON, NTT SOFTWARE, NTT, OR OPEN SOFTWARE FOUNDATION BE
LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright 1988 by Wyse Technology, Inc., San Jose, Ca,
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL AND WYSE DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL DIGITAL OR WYSE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright 1991, 1992 by Fuji Xerox Co., Ltd.
Copyright 1992, 1993, 1994 by FUJITSU LIMITED
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of Fuji Xerox,
FUJITSU LIMITED not be used in advertising or publicity pertaining
to distribution of the software without specific, written prior
permission. Fuji Xerox, FUJITSU LIMITED make no representations
about the suitability of this software for any purpose.
It is provided "as is" without express or implied warranty.
FUJI XEROX, FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL FUJI XEROX,
FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright 2006 Josh Triplett
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 X CONSORTIUM 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.
----------------------------------------
(c) Copyright 1996 by Sebastien Marineau and Holger Veit
<marineau@genie.uottawa.ca>
<Holger.Veit@gmd.de>
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
HOLGER VEIT 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.
Except as contained in this notice, the name of Sebastien Marineau or Holger Veit
shall not be used in advertising or otherwise to promote the sale, use or other
dealings in this Software without prior written authorization from Holger Veit or
Sebastien Marineau.
----------------------------------------
Copyright 1990, 1991 by OMRON Corporation, NTT Software Corporation,
and Nippon Telegraph and Telephone Corporation
Copyright 1991 by the Open Software Foundation
Copyright 1993 by the TOSHIBA Corp.
Copyright 1993, 1994 by Sony Corporation
Copyright 1993, 1994 by the FUJITSU LIMITED
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the names of OMRON, NTT Software, NTT, Open
Software Foundation, and Sony Corporation not be used in advertising
or publicity pertaining to distribution of the software without specific,
written prior permission. OMRON, NTT Software, NTT, Open Software
Foundation, and Sony Corporation make no representations about the
suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
OMRON, NTT SOFTWARE, NTT, OPEN SOFTWARE FOUNDATION, AND SONY
CORPORATION DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
SHALL OMRON, NTT SOFTWARE, NTT, OPEN SOFTWARE FOUNDATION, OR SONY
CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright 2000 by Bruno Haible
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation, and that the name of Bruno Haible not
be used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission. Bruno Haible
makes no representations about the suitability of this software for
any purpose. It is provided "as is" without express or implied
warranty.
Bruno Haible DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
NO EVENT SHALL Bruno Haible BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
OR PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright © 2003 Keith Packard
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of Keith Packard not be used in
advertising or publicity pertaining to distribution of the software without
specific, written prior permission. Keith Packard makes no
representations about the suitability of this software for any purpose. It
is provided "as is" without express or implied warranty.
KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
----------------------------------------
Copyright (c) 2007-2009, Troy D. Hanson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
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 OWNER
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.
----------------------------------------
Copyright 1992, 1993 by TOSHIBA Corp.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of TOSHIBA not be used in advertising
or publicity pertaining to distribution of the software without specific,
written prior permission. TOSHIBA make no representations about the
suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
----------------------------------------
Copyright IBM Corporation 1993
All Rights Reserved
License to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of IBM not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS, AND
NONINFRINGEMENT OF THIRD PARTY RIGHTS, IN NO EVENT SHALL
IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
----------------------------------------
Copyright 1990, 1991 by OMRON Corporation, NTT Software Corporation,
and Nippon Telegraph and Telephone Corporation
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the names of OMRON, NTT Software, and NTT
not be used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission. OMRON, NTT Software,
and NTT make no representations about the suitability of this
software for any purpose. It is provided "as is" without express or
implied warranty.
OMRON, NTT SOFTWARE, AND NTT, DISCLAIM ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS, IN NO EVENT SHALL OMRON, NTT SOFTWARE, OR NTT, BE
LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+24
View File
@@ -0,0 +1,24 @@
This package was downloaded from
https://xorg.freedesktop.org/releases/individual/lib/
Copyright 1988, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
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
OPEN GROUP 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.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
+26
View File
@@ -0,0 +1,26 @@
This package was downloaded from
http://xorg.freedesktop.org/releases/individual/lib/
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
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
OPEN GROUP 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.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Author: Keith Packard, MIT X Consortium
+199
View File
@@ -0,0 +1,199 @@
This package was downloaded from
http://xorg.freedesktop.org/releases/individual/lib/
Copyright 1986, 1987, 1988, 1989, 1994, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
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
OPEN GROUP 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.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright (c) 1996 Digital Equipment Corporation, Maynard, Massachusetts.
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.
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
DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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.
Except as contained in this notice, the name of Digital Equipment Corporation
shall not be used in advertising or otherwise to promote the sale, use or other
dealings in this Software without prior written authorization from Digital
Equipment Corporation.
Copyright (c) 1997 by Silicon Graphics Computer Systems, Inc.
Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting
documentation, and that the name of Silicon Graphics not be
used in advertising or publicity pertaining to distribution
of the software without specific prior written permission.
Silicon Graphics makes no representation about the suitability
of this software for any purpose. It is provided "as is"
without any express or implied warranty.
SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
THE USE OR PERFORMANCE OF THIS SOFTWARE.
Copyright 1992 Network Computing Devices
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of NCD. not be used in advertising or
publicity pertaining to distribution of the software without specific,
written prior permission. NCD. makes no representations about the
suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD.
BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Copyright 1991,1993 by Digital Equipment Corporation, Maynard, Massachusetts,
and Olivetti Research Limited, Cambridge, England.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Digital or Olivetti
not be used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
Copyright 1986, 1987, 1988 by Hewlett-Packard Corporation
Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting
documentation, and that the name of Hewlett-Packard not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
Hewlett-Packard makes no representations about the
suitability of this software for any purpose. It is provided
"as is" without express or implied warranty.
This software is not subject to any license of the American
Telephone and Telegraph Company or of the Regents of the
University of California.
Copyright (c) 1994, 1995 Hewlett-Packard Company
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 HEWLETT-PACKARD COMPANY 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.
Except as contained in this notice, the name of the Hewlett-Packard
Company shall not be used in advertising or otherwise to promote the
sale, use or other dealings in this Software without prior written
authorization from the Hewlett-Packard Company.
Copyright Digital Equipment Corporation, 1996
Permission to use, copy, modify, distribute, and sell this
documentation for any purpose is hereby granted without fee,
provided that the above copyright notice and this permission
notice appear in all copies. Digital Equipment Corporation
makes no representations about the suitability for any purpose
of the information in this document. This documentation is
provided ``as is'' without express or implied warranty.
Copyright (c) 1999, 2005, 2006, Oracle and/or its affiliates. All rights reserved.
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 (including the next
paragraph) 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.
Copyright (c) 1989 X Consortium, Inc. and Digital Equipment Corporation.
Copyright (c) 1992 X Consortium, Inc. and Intergraph Corporation.
Copyright (c) 1993 X Consortium, Inc. and Silicon Graphics, Inc.
Copyright (c) 1994, 1995 X Consortium, Inc. and Hewlett-Packard Company.
Permission to use, copy, modify, and distribute this documentation for
any purpose and without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Digital Equipment Corporation, Intergraph Corporation, Silicon
Graphics, Hewlett-Packard, and the X Consortium make no
representations about the suitability for any purpose of the
information in this document. This documentation is provided ``as is''
without express or implied warranty.
+31
View File
@@ -0,0 +1,31 @@
This package was downloaded from
http://xorg.freedesktop.org/releases/individual/lib/
This package was originally Debianized by Colin Walters
<walters@debian.org> on Sun, 13 Oct 2002 15:01:50 -0400.
Later versions were Debianized by Branden Robinson <branden@debian.org>.
Upstream maintainer: Keith Packard
Copyright and license:
Copyright © 2001,2003 Keith Packard
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of Keith Packard not be used in
advertising or publicity pertaining to distribution of the software without
specific, written prior permission. Keith Packard makes no
representations about the suitability of this software for any purpose. It
is provided "as is" without express or implied warranty.
KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
+41
View File
@@ -0,0 +1,41 @@
This package was downloaded from
https://xorg.freedesktop.org/releases/individual/lib/
Copyright © 2001,2003 Keith Packard
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of Keith Packard not be used in
advertising or publicity pertaining to distribution of the software without
specific, written prior permission. Keith Packard makes no
representations about the suitability of this software for any purpose. It
is provided "as is" without express or implied warranty.
KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
Copyright © 2000 SuSE, Inc.
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of SuSE not be used in advertising or
publicity pertaining to distribution of the software without specific,
written prior permission. SuSE makes no representations about the
suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+52
View File
@@ -0,0 +1,52 @@
This package was downloaded from
https://xorg.freedesktop.org/releases/individual/lib/
Copyright (c) 1992 X Consortium
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
X CONSORTIUM 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.
Except as contained in this notice, the name of the X Consortium shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the X Consortium.
Copyright (C) 2003 The XFree86 Project, Inc. All Rights Reserved.
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 NON-INFRINGEMENT.
IN NO EVENT SHALL THE XFREE86 PROJECT 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.
Except as contained in this notice, the name of the XFree86 Project
shall not be used in advertising or otherwise to promote the sale, use
or other dealings in this Software without prior written authorization
from the XFree86 Project.
+30
View File
@@ -0,0 +1,30 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: brotli
Source: https://github.com/google/brotli
Files: *
Copyright: 2009, 2010, 2013-2015 by the Brotli Authors
License: MIT
Files: debian/*
Copyright: 2015 Tomasz Buchert <tomasz@debian.org>
License: MIT
License: MIT
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.
+558
View File
@@ -0,0 +1,558 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Files:
*
Copyright:
Copyright © 2004-2024 Guillem Jover <guillem@hadrons.org>
License: BSD-3-clause
Files:
include/bsd/err.h
include/bsd/stdlib.h
include/bsd/sys/param.h
include/bsd/unistd.h
src/bsd_getopt.c
src/err.c
src/fgetln.c
src/progname.c
Copyright:
Copyright © 2005, 2008-2012, 2019 Guillem Jover <guillem@hadrons.org>
Copyright © 2005 Hector Garcia Alvarez
Copyright © 2005 Aurelien Jarno
Copyright © 2006 Robert Millan
Copyright © 2018 Facebook, Inc.
License: BSD-3-clause
Files:
include/bsd/netinet/ip_icmp.h
include/bsd/sys/bitstring.h
include/bsd/sys/queue.h
include/bsd/sys/time.h
include/bsd/timeconv.h
include/bsd/vis.h
man/bitstring.3bsd
man/errc.3bsd
man/explicit_bzero.3bsd
man/fgetln.3bsd
man/fgetwln.3bsd
man/fpurge.3bsd
man/funopen.3bsd
man/getbsize.3bsd
man/heapsort.3bsd
man/nlist.3bsd
man/pwcache.3bsd
man/queue.3bsd
man/radixsort.3bsd
man/reallocarray.3bsd
man/reallocf.3bsd
man/setmode.3bsd
man/strmode.3bsd
man/strnstr.3bsd
man/strtoi.3bsd
man/strtou.3bsd
man/unvis.3bsd
man/vis.3bsd
man/wcslcpy.3bsd
src/getbsize.c
src/heapsort.c
src/merge.c
src/nlist.c
src/pwcache.c
src/radixsort.c
src/setmode.c
src/strmode.c
src/strnstr.c
src/strtoi.c
src/strtou.c
src/unvis.c
Copyright:
Copyright © 1980, 1982, 1986, 1989-1994
The Regents of the University of California. All rights reserved.
Copyright © 1992 Keith Muller.
Copyright © 2001 Mike Barcroft <mike@FreeBSD.org>
.
Some code is derived from software contributed to Berkeley by
the American National Standards Committee X3, on Information
Processing Systems.
.
Some code is derived from software contributed to Berkeley by
Peter McIlroy.
.
Some code is derived from software contributed to Berkeley by
Ronnie Kon at Mindcraft Inc., Kevin Lew and Elmer Yglesias.
.
Some code is derived from software contributed to Berkeley by
Dave Borman at Cray Research, Inc.
.
Some code is derived from software contributed to Berkeley by
Paul Vixie.
.
Some code is derived from software contributed to Berkeley by
Chris Torek.
.
Copyright © UNIX System Laboratories, Inc.
All or some portions of this file are derived from material licensed
to the University of California by American Telephone and Telegraph
Co. or Unix System Laboratories, Inc. and are reproduced herein with
the permission of UNIX System Laboratories, Inc.
License: BSD-3-clause-Regents
Files:
src/vis.c
Copyright:
Copyright © 1989, 1993
The Regents of the University of California. All rights reserved.
.
Copyright © 1999, 2005 The NetBSD Foundation, Inc.
All rights reserved.
License: BSD-3-clause-Regents and BSD-2-clause-NetBSD
Files:
include/bsd/libutil.h
Copyright:
Copyright © 1996 Peter Wemm <peter@FreeBSD.org>.
All rights reserved.
Copyright © 2002 Networks Associates Technology, Inc.
All rights reserved.
License: BSD-3-clause-author
Files:
man/timeradd.3bsd
Copyright:
Copyright © 2009 Jukka Ruohonen <jruohonen@iki.fi>
Copyright © 1999 Kelly Yancey <kbyanc@posi.net>
All rights reserved.
License: BSD-3-clause-John-Birrell
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of the author nor the names of any co-contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
.
THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL 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 REGENTS 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.
Files:
man/setproctitle.3bsd
Copyright:
Copyright © 1995 Peter Wemm <peter@FreeBSD.org>
All rights reserved.
License: BSD-5-clause-Peter-Wemm
Redistribution and use in source and binary forms, with or without
modification, is permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice immediately at the beginning of the file, without modification,
this list of conditions, and the following disclaimer.
2. 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.
3. This work was done expressly for inclusion into FreeBSD. Other use
is permitted provided this notation is included.
4. Absolutely no warranty of function or purpose is made by the author
Peter Wemm.
5. Modifications may be freely made to this file providing the above
conditions are met.
Files:
include/bsd/stringlist.h
man/arc4random.3bsd
man/fmtcheck.3bsd
man/humanize_number.3bsd
man/stringlist.3bsd
man/timeval.3bsd
src/fmtcheck.c
src/humanize_number.c
src/stringlist.c
src/strtonum.c
Copyright:
Copyright © 1994, 1997-2000, 2002, 2008, 2010, 2014
The NetBSD Foundation, Inc.
Copyright © 2013 John-Mark Gurney <jmg@FreeBSD.org>
All rights reserved.
.
Copyright © 2014 The NetBSD Foundation, Inc.
All rights reserved.
.
Some code was derived from software contributed to The NetBSD Foundation
by Taylor R. Campbell.
.
Some code was contributed to The NetBSD Foundation by Allen Briggs.
.
Some code was contributed to The NetBSD Foundation by Luke Mewburn.
.
Some code is derived from software contributed to The NetBSD Foundation
by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson.
.
Some code is derived from software contributed to The NetBSD Foundation
by Julio M. Merino Vidal, developed as part of Google's Summer of Code
2005 program.
.
Some code is derived from software contributed to The NetBSD Foundation
by Christos Zoulas.
.
Some code is derived from software contributed to The NetBSD Foundation
by Jukka Ruohonen.
License: BSD-2-clause-NetBSD
Files:
include/bsd/sys/endian.h
man/byteorder.3bsd
man/closefrom.3bsd
man/expand_number.3bsd
man/flopen.3bsd
man/getpeereid.3bsd
man/pidfile.3bsd
src/expand_number.c
src/pidfile.c
src/reallocf.c
src/timeconv.c
Copyright:
Copyright © 1998, M. Warner Losh <imp@freebsd.org>
All rights reserved.
.
Copyright © 2001 Dima Dorfman.
All rights reserved.
.
Copyright © 2001 FreeBSD Inc.
All rights reserved.
.
Copyright © 2002 Thomas Moestl <tmm@FreeBSD.org>
All rights reserved.
.
Copyright © 2002 Mike Barcroft <mike@FreeBSD.org>
All rights reserved.
.
Copyright © 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
All rights reserved.
.
Copyright © 2005 Colin Percival
All rights reserved.
.
Copyright © 2007 Eric Anderson <anderson@FreeBSD.org>
Copyright © 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
All rights reserved.
.
Copyright © 2007 Dag-Erling Coïdan Smørgrav
All rights reserved.
.
Copyright © 2009 Advanced Computing Technologies LLC
All rights reserved.
.
Copyright © 2011 Guillem Jover <guillem@hadrons.org>
License: BSD-2-clause
Files:
src/flopen.c
Copyright:
Copyright © 2007-2009 Dag-Erling Coïdan Smørgrav
All rights reserved.
License: BSD-2-clause-verbatim
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer
in this position and unchanged.
2. 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.
.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
Files:
include/bsd/sys/tree.h
man/fparseln.3bsd
man/tree.3bsd
src/fparseln.c
Copyright:
Copyright © 1997 Christos Zoulas.
All rights reserved.
.
Copyright © 2002 Niels Provos <provos@citi.umich.edu>
All rights reserved.
License: BSD-2-clause-author
Files:
include/bsd/readpassphrase.h
man/readpassphrase.3bsd
man/strlcpy.3bsd
man/strtonum.3bsd
src/arc4random.c
src/arc4random_linux.h
src/arc4random_uniform.c
src/arc4random_unix.h
src/arc4random_win.h
src/closefrom.c
src/freezero.c
src/getentropy_aix.c
src/getentropy_bsd.c
src/getentropy_hpux.c
src/getentropy_hurd.c
src/getentropy_linux.c
src/getentropy_osx.c
src/getentropy_solaris.c
src/getentropy_win.c
src/readpassphrase.c
src/reallocarray.c
src/recallocarray.c
src/strlcat.c
src/strlcpy.c
test/explicit_bzero.c
test/strtonum.c
Copyright:
Copyright © 2004 Ted Unangst and Todd Miller
All rights reserved.
.
Copyright © 1996 David Mazieres <dm@uun.org>
Copyright © 1998, 2000-2002, 2004-2005, 2007, 2010, 2012-2015
Todd C. Miller <Todd.Miller@courtesan.com>
Copyright © 2004 Ted Unangst
Copyright © 2004 Otto Moerbeek <otto@drijf.net>
Copyright © 2008 Damien Miller <djm@openbsd.org>
Copyright © 2008, 2010-2011, 2016-2017 Otto Moerbeek <otto@drijf.net>
Copyright © 2013 Markus Friedl <markus@openbsd.org>
Copyright © 2014 Bob Beck <beck@obtuse.com>
Copyright © 2014 Brent Cook <bcook@openbsd.org>
Copyright © 2014 Pawel Jakub Dawidek <pjd@FreeBSD.org>
Copyright © 2014 Theo de Raadt <deraadt@openbsd.org>
Copyright © 2014 Google Inc.
Copyright © 2015 Michael Felt <aixtools@gmail.com>
Copyright © 2015, 2022 Guillem Jover <guillem@hadrons.org>
License: ISC
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Files:
src/inet_net_pton.c
Copyright:
Copyright © 1996 by Internet Software Consortium.
License: ISC-Original
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
.
THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
Files:
src/setproctitle.c
Copyright:
Copyright © 2010 William Ahern
Copyright © 2012 Guillem Jover <guillem@hadrons.org>
License: Expat
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.
Files:
src/explicit_bzero.c
src/chacha_private.h
Copyright:
None
License: public-domain
Public domain.
Files:
man/mdX.3bsd
Copyright:
None
License: Beerware
"THE BEER-WARE LICENSE" (Revision 42):
<phk@login.dkuug.dk> wrote this file. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you think
this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
License: BSD-3-clause-Regents
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
License: BSD-3-clause-author
Redistribution and use in source and binary forms, with or without
modification, is permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
License: BSD-3-clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
.
THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
License: BSD-2-clause-NetBSD
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
.
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
License: BSD-2-clause-author
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
License: BSD-2-clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+48
View File
@@ -0,0 +1,48 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: bzip2
Source: http://www.bzip.org/
Files: *
Copyright: 1996-2010 Julian R Seward <jseward@bzip.org>
License: BSD-variant
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
.
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
Files: debian/*
Copyright: 2018 Nicolas Boulenguez <nicolas.boulenguez@free.fr>
2012-2015 Santiago Ruano Rincón <santiago@debian.org>
2014 Canonical Ltd.
2004-2011 Anibal Monsalve Salazar <anibal@debian.org>
1999-2002 Philippe Troin <phil@fifi.org>
1997-1999 Anthony Fok <foka@debian.org>
License: GPL-2
The full text of the GNU General Public License version 2
can be found in /usr/share/common-licenses/GPL-2.
+112
View File
@@ -0,0 +1,112 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: libcap
Upstream-Contact: Andrew G. Morgan <morgan@kernel.org>
Source: https://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/
Files: *
Copyright: 1997-2016 Andrew G. Morgan <morgan@linux.kernel.org>
License: BSD-3-clause or GPL-2
Files: libcap/cap_text.c
Copyright: 1997-2008 Andrew G. Morgan <morgan@linux.kernel.org>
1997 Andrew Main <zefram@dcs.warwick.ac.uk>
License: BSD-3-clause or GPL-2
Files: libcap/include/sys/capability.h
Copyright: 1997-2008 Andrew G. Morgan <morgan@kernel.org>
1997 Aleph One
License: BSD-3-clause or GPL-2
Files: libcap/include/sys/securebits.h
Copyright: 2010 Serge Hallyn <serue@us.ibm.com>
License: BSD-3-clause or GPL-2
Files: progs/old/sucap.c
Copyright: 1998 Finn Arne Gangstad <finnag@guardian.no>
License: BSD-3-clause or GPL-2
Files: contrib/*
Copyright: 2006, Matt Kern <matt.kern@undue.org>
2008, Andrew G. Morgan <morgan@linux.kernel.org>
2008, Chris Friedhoff <chris@friedhoff.org>
License: BSD-3-clause or GPL-2
Files: debian/*
Copyright: 2014, Daniel Baumann <mail@daniel-baumann.ch>
2014-2022, Christian Kastner <ckk@debian.org>
License: BSD-3-clause or GPL-2+
Files: debian/manpages/*
Copyright: 1997-2014 Andrew G. Morgan <morgan@linux.kernel.org>
2011 Scott Schaefer <saschaefer@neurodiverse.org>
License: BSD-3-clause or GPL-2
Files: debian/patches/*
Copyright: 2011, Andrew Straw <strawman@astraw.com>
2011, Zhi Li <lizhi1215@gmail.com>
2014-2016, Christian Kastner <ckk@debian.org>
2015, Helmut Grohne <helmut@subdivi.de>
License: BSD-3-clause or GPL-2+
License: BSD-3-clause
Redistribution and use in source and binary forms of libcap, with
or without modification, are permitted provided that the following
conditions are met:
.
1. Redistributions of source code must retain any existing copyright
notice, and this entire permission notice in its entirety,
including the disclaimer of warranties.
.
2. Redistributions in binary form must reproduce all prior and current
copyright notices, this list of conditions, and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
.
3. The name of any author may not be used to endorse or promote
products derived from this software without their specific prior
written permission.
.
THIS SOFTWARE IS PROVIDED ``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 AUTHOR(S) 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.
License: GPL-2
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2 of the License.
.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
.
The complete text of the GNU General Public License
can be found in /usr/share/common-licenses/GPL-2 file.
License: GPL-2+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
.
The complete text of the GNU General Public License
can be found in /usr/share/common-licenses/GPL-2 file.
+70
View File
@@ -0,0 +1,70 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: OpenSSL
Source: https://www.openssl.org
Files: *
Copyright: 1995-2020, The OpenSSL Project Authors
1995-1998, Eric A. Young, Tim J. Hudson
2004-2014 Akamai Technologies.
2008 Andy Polyakov <appro@openssl.org>
2017 BaishanCloud.
2015 CloudFlare Inc.
2014-2016 Cryptography Research Inc.
2012-2014 Daniel J. Bernstein
2004 EdelKey Project.
2011 Google Inc.
2018-2019 IBM Corp.
2012,2014 Intel Corporation.
2012-2016 Jean-Philippe Aumasson
2007 KISA(Korea Information Security Agency).
2004 Kungliga Tekniska Högskolan
2017 National Security Research Institute.
2006 Network Resonance Inc.
2005,2007-2020 Nokia
2006 NTT (Nippon Telegraph and Telephone Corporation)
2002,2017-2020 Oracle and/or its affiliates.
1995 Patrick Powell
2019 Red Hat Inc.
2017 Ribose Inc.
2004,2018 Richard Levitte <richard@levitte.org>
2011 RTFM Inc.
2012 Samuel Neves <sneves@dei.uc.pt>
2015-2020 Siemens AG
2002 The OpenTSA Project.
2013-2014 Timo Teräs <timo.teras@gmail.com>
2016 Viktor Dukhovni <openssl-users@dukhovni.org>.
2016 VMS Software Inc.
License: Apache-2.0
License: Apache-2.0
Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
https://www.openssl.org/source/license.html
.
On Debian systems, the complete text of the Apache 2.0 License
can be found in `/usr/share/common-licenses/Apache-2.0'
Files: debian/*
Copyright: Christoph Martin, Kurt Roeckx, Sebastian Andrzej Siewior
License: Apache-2.0
Files: external/perl/Text-Template-1.56/*
Copyright: 2013, Mark Jason Dominus <mjd@cpan.org>.
License: Artistic or GPL-1+
License: Artistic
This program is free software; you can redistribute it and/or modify
it under the terms of the Artistic License, which comes with Perl.
.
On Debian systems, the complete text of the Artistic License can be
found in `/usr/share/common-licenses/Artistic'.
License: GPL-1+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
.
On Debian systems, the complete text of version 1 of the GNU General
Public License can be found in `/usr/share/common-licenses/GPL-1'.
+61
View File
@@ -0,0 +1,61 @@
The source code in PyCryptodome is partially in the public domain
and partially released under the BSD 2-Clause license.
In either case, there are minimal if no restrictions on the redistribution,
modification and usage of the software.
Public domain
=============
All code originating from PyCrypto is free and unencumbered software
released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
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 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.
For more information, please refer to <http://unlicense.org>
BSD license
===========
All direct contributions to PyCryptodome are released under the following
license. The copyright of each piece belongs to the respective author.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. 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.
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.
+228
View File
@@ -0,0 +1,228 @@
#!/bin/sh
# diskOS first-boot installer. Runs at S97 - BEFORE S98FIIO launches the UI, and after
# S21mount_ubifs has mounted /usr/data. Installs the diskOS UI into /usr/data (which survives
# rootfs flashes) from - in deterministic precedence - (1) the copy EMBEDDED in this rootfs at
# /opt/diskos/mq_ui (present after a diskOS flash; needs no SD card), else (2) <SD>/diskos/mq_ui as
# a fallback source. EITHER source is copied ONLY after verifying it against the manifest baked into
# this rootfs (/etc/diskos_manifest): exact size, ELF32-LE, MIPS machine, and SHA-256. This stops a
# corrupt, wrong, or substituted UI from being copied in and run as root. Read-only SD mount.
#
# FAIL-CLOSED CONTRACT: the diskOS boot override in fiio_init.sh runs our UI ONLY when BOTH
# /usr/data/mq_ui AND the /usr/data/mq_player symlink exist; otherwise it falls back to the STOCK
# rootfs UI. So the load-bearing safety lever is the mq_player symlink: whenever we cannot PROVE
# /usr/data/mq_ui matches the manifest (missing/bad manifest, failed verify, failed repair), we
# remove that symlink (and move the binary aside) so the stock UI runs instead of an unverified
# binary. Every SD-touching op is time-bounded so a faulty card can delay but never hang boot.
#
# RESIDUAL LIMITS (documented, not shell-fixable): a process wedged in uninterruptible (D-state)
# kernel I/O cannot be killed by any signal, so a truly dead SD controller can still stall this
# script until the kernel gives up on the I/O; and if BusyBox lacks the `timeout` applet the
# bounds degrade to best-effort. Neither is reachable from userspace shell.
# EARLIEST fail-closed trap - the FIRST executable statement in the script (only comments precede
# it; no file operation runs before it). For every catchable TERMINATING signal it arms an inline
# handler that performs the load-bearing action (drop the mq_player symlink -> boot override
# disabled; move the binary aside) and exit 1, so even a signal during setup can't leave a
# pre-existing unverified override enabled for S98. Ordered most-likely-first (TERM/HUP/INT) because
# POSIX sh has no atomic multi-signal trap: the sub-microsecond gradual-arming window across the
# loop is an irreducible shell limitation, minimized by arming the boot-relevant signals first.
# Excludes SIGKILL/SIGSTOP (uncatchable) and the non-terminating/stop/ignore-default signals
# (TSTP/TTIN/TTOU/WINCH/URG/CHLD/CONT). The trailing `7` is SIGEMT: busybox ash rejects the NAME
# "EMT" but the deployment arch is MIPS where SIGEMT=7, so it's armed numerically (SIGSTKFLT is
# undefined on MIPS, so nothing further is needed). Per-signal arming (`2>/dev/null || true`) so a
# name an odd build rejects can't abort the set. Superseded below by the guarded trap once
# quarantine() exists.
SIGS="TERM HUP INT QUIT PWR ABRT ALRM PIPE USR1 USR2 XCPU XFSZ ILL TRAP BUS FPE SEGV SYS VTALRM PROF IO 7"
_qtrap='rm -rf /usr/data/mq_player 2>/dev/null; [ -e /usr/data/mq_ui ] && mv -f /usr/data/mq_ui /usr/data/mq_ui.rejected 2>/dev/null; exit 1'
# Arm the standard signals FIRST - this loop is the first executable statement (only the two var
# assignments above, which touch no files, precede it), so the boot-relevant signals (TERM/HUP/INT)
# are covered immediately.
for s in $SIGS; do trap "$_qtrap" "$s" 2>/dev/null || true; done
# THEN arm each real-time signal (SIGRTMIN..SIGRTMAX, 32..127 on MIPS Linux) AND record it in SIGS
# within the SAME iteration - so no batch list-build ever precedes arming. RT signals are catchable
# and default-terminate; nothing sends them to a boot init script, armed only for completeness.
# Per-signal arming skips any number the running kernel doesn't define (a 64-signal host arms
# 32..64; the MIPS device arms 32..127).
n=32; while [ "$n" -le 127 ]; do trap "$_qtrap" "$n" 2>/dev/null || true; SIGS="$SIGS $n"; n=$((n+1)); done
LOG=/usr/data/diskos_install.log
log() { echo "$(date 2>/dev/null || true) S97: $*" >> "$LOG" 2>/dev/null; }
# override_on: true iff the boot hook would launch our UI (it needs BOTH regular files present).
override_on() { [ -f /usr/data/mq_ui ] && [ -f /usr/data/mq_player ]; }
# quarantine: fail-closed, with a checked postcondition. Drop the mq_player path FIRST (that alone
# disables the override), move the binary aside, then PROVE the override is off; if it somehow
# isn't (e.g. rm/mv failed), remove the binary itself as a last resort and, if even that fails,
# log CRITICAL and return non-zero rather than silently claiming safety. Returns 0 iff the override
# is provably disabled.
quarantine() {
rm -rf /usr/data/mq_player 2>/dev/null # clear file/dir/symlink at the path
[ -e /usr/data/mq_ui ] && mv -f /usr/data/mq_ui /usr/data/mq_ui.rejected 2>/dev/null
if override_on; then
rm -f /usr/data/mq_ui 2>/dev/null # last resort: remove the override binary
if override_on; then
log "CRITICAL: could NOT disable diskOS override${1:+ ($1)} (fs unwritable?) -- unverified UI MAY run"
return 1
fi
fi
log "quarantined${1:+ ($1)} -> stock UI will run"
return 0
}
# Now that quarantine() exists, UPGRADE the early inline trap to the guarded one: while installed!=1
# a signal quarantines (with the checked postcondition + CRITICAL logging) and exits non-zero; once
# installed=1 it skips quarantine so a completed install is never torn down. A stray signal before
# install merely downgrades to the STOCK UI (safe), never up to running something unverified.
# disarm() clears it on success paths. SIGKILL/SIGSTOP + D-state I/O are non-trappable residuals;
# and if /usr/data is unwritable, quarantine cannot unlink the override AND this script cannot stop
# the SysV dispatcher reaching S98 - unrecoverable-from-shell, logged CRITICAL (a true boot
# fail-stop belongs in the rootfs boot hook, tracked separately, not this S-script).
disarm() { for s in $SIGS; do trap - "$s" 2>/dev/null || true; done; }
installed=0
for s in $SIGS; do trap '[ "$installed" = 1 ] || quarantine "signal"; exit 1' "$s" 2>/dev/null || true; done
# TO: run a command under a hard time bound. Prefer SIGKILL (-s KILL) so a stuck-but-killable op
# is force-terminated, not just SIGTERM'd. Falls back to running directly only if `timeout` is
# absent (logged once) - the one case we cannot bound from shell.
warned_to=0
TO() {
if command -v timeout >/dev/null 2>&1; then
timeout -s KILL 60 "$@"
else
[ "$warned_to" = 1 ] || { log "WARNING: no 'timeout' applet -> SD ops are UNBOUNDED this boot"; warned_to=1; }
"$@"
fi
}
# publish_symlink: make an already-verified /usr/data/mq_ui runnable (exec bit + mq_player link) and
# PROVE the symlink resolves to exactly /usr/data/mq_ui. Nukes whatever sits at the mq_player path
# first (a pre-existing dir/file/stale symlink would otherwise make `ln -sf` succeed without
# publishing the right target). Returns non-zero on any failure so the caller can quarantine.
publish_symlink() {
chmod +x /usr/data/mq_ui 2>/dev/null || return 1 # a 0644 hash-match would boot-select but not exec
rm -rf /usr/data/mq_player 2>/dev/null # remove any file/dir/symlink at the path
ln -sf /usr/data/mq_ui /usr/data/mq_player 2>/dev/null || return 1
[ "$(readlink /usr/data/mq_player 2>/dev/null)" = /usr/data/mq_ui ] || return 1 # prove exact target
return 0
}
MAN=/etc/diskos_manifest
# No/'malformed manifest = we cannot verify anything -> fail closed (quarantine any existing override).
[ -f "$MAN" ] || { quarantine "no manifest" || exit 1; disarm; exit 0; }
MSHA=$(grep '^SHA256=' "$MAN" | cut -d= -f2)
MSIZE=$(grep '^SIZE=' "$MAN" | cut -d= -f2)
[ -n "$MSHA" ] && [ -n "$MSIZE" ] || { quarantine "malformed manifest" || exit 1; disarm; exit 0; }
# verify_ui <file>: 0 only if it exactly matches the manifest (size, ELF32-LE, MIPS, sha256).
verify_ui() {
f="$1"; [ -f "$f" ] || return 1
sz=$(stat -c%s "$f" 2>/dev/null); [ -n "$sz" ] || sz=$(wc -c < "$f" 2>/dev/null | tr -d ' ')
[ "$sz" = "$MSIZE" ] || { log "verify $f: size $sz != $MSIZE"; return 1; }
[ "$(od -An -tx1 -N4 "$f" | tr -d ' ')" = "7f454c46" ] || { log "verify $f: not ELF"; return 1; }
[ "$(od -An -tx1 -j4 -N2 "$f" | tr -d ' ')" = "0101" ] || { log "verify $f: not ELF32-LE"; return 1; } # EI_CLASS=32,EI_DATA=LE
[ "$(od -An -tx1 -j18 -N2 "$f" | tr -d ' ')" = "0800" ] || { log "verify $f: not MIPS"; return 1; }
[ "$(sha256sum "$f" | cut -d' ' -f1)" = "$MSHA" ] || { log "verify $f: sha256 mismatch"; return 1; }
return 0
}
rm -f /usr/data/.mq_ui.tmp 2>/dev/null # never trust a leftover temp from a prior interrupted run
# FAST PATH: an already-installed matching UI -> just repair exec bit + symlink and boot.
if verify_ui /usr/data/mq_ui; then
if publish_symlink; then
installed=1; disarm # a completed install: disarm before exit so no late-signal quarantine
log "already installed + verified -> repaired +x/symlink, booting diskOS"
exit 0
fi
log "already-installed repair (chmod/ln) failed -> quarantining"
quarantine "repair failed" || exit 1 # can't guarantee it launches -> fall back to stock
disarm; exit 0
fi
# Reaching here means /usr/data/mq_ui is absent or does NOT match the manifest. Pre-emptively
# QUARANTINE any existing override NOW - BEFORE the SD window - so an interrupted copy can never
# leave the unverified binary enabled for S98 to launch. A successful SD install below republishes
# a verified one. (The whole-run trap above already covers signals; this closes the window
# deterministically even absent a signal.)
if [ -e /usr/data/mq_ui ] || [ -e /usr/data/mq_player ]; then
quarantine "unverified at boot" || exit 1
fi
# INSTALL PATH - SOURCE PRECEDENCE (deterministic, NOT newest-wins): try the copy EMBEDDED in this
# rootfs at /opt/diskos/mq_ui FIRST (present after a diskOS flash, needs no SD card); if it is absent
# OR its local copy fails manifest verification, fall through to <SD>/diskos/mq_ui as a recovery
# source. The embedded source only "wins" (copied=1, SD skipped) when its temp passes verify_ui - so
# a valid same-hash SD copy CAN rescue a corrupted embedded copy. The SD is a fallback SOURCE, not an
# override (no version/newer-wins). The winning temp is re-verified + published below.
copied=0; src=
EMBED=/opt/diskos/mq_ui
if [ -f "$EMBED" ]; then
# Embedded copy lives in the read-only rootfs we just flashed. TO-bound the cp for consistency
# (a NAND read fault shouldn't stall boot), and verify_ui the temp IN-BRANCH: only a verified
# embedded copy suppresses the SD fallback.
if TO cp "$EMBED" /usr/data/.mq_ui.tmp 2>/dev/null && verify_ui /usr/data/.mq_ui.tmp; then
copied=1; src=embedded; log "staged verified UI from embedded rootfs copy ($EMBED)"
else
rm -f /usr/data/.mq_ui.tmp 2>/dev/null
log "embedded UI absent or failed verify -> trying SD fallback"
fi
fi
# SD FALLBACK: only when the rootfs carried no VERIFIED UI. Mount the SD read-only, copy
# <SD>/diskos/mq_ui to the LOCAL temp, unmount; mount/cp/umount are all TO-bounded; no verification
# ever runs against the (possibly faulty) card (the publish block below verifies the local copy).
if [ "$copied" != 1 ]; then
MP=/tmp/diskos_sd; mkdir -p "$MP"; mounted=0
for dev in /dev/mmcblk0p1 /dev/mmcblk1p1 /dev/mmcblk0 /dev/mmcblk1; do
[ -b "$dev" ] || continue
for fs in exfat vfat; do
TO mount -t $fs -o ro "$dev" "$MP" 2>/dev/null && { mounted=1; break; }
done
[ "$mounted" = 1 ] && break
done
if [ "$mounted" = 1 ]; then
# No pre-stat of the SD path (that could hang) - let the bounded cp fail fast if it's absent.
if TO cp "$MP/diskos/mq_ui" /usr/data/.mq_ui.tmp 2>/dev/null; then
copied=1; src=SD
else
log "no readable <SD>/diskos/mq_ui (or copy timed out) -> nothing to install"
fi
if TO umount "$MP" 2>/dev/null || TO umount -l "$MP" 2>/dev/null; then :; else
log "WARNING: SD would not unmount (card may stay mounted; publish is unaffected - it uses the local copy)"
fi
else
log "no SD mounted -> nothing to install this boot"
fi
fi
if [ "$copied" = 1 ]; then
# Verify the LOCAL copy, then publish atomically. installed=1 is gated on the CORRECTNESS steps
# only (verify -> chmod -> mv -> publish_symlink[proves exact target] -> re-verify); publishing
# is independent of whether the SD unmounted, since it works entirely on the local copy.
# Durability rides on /usr/data being sync-mounted ubifs; the explicit sync is TO-bounded and
# deliberately NOT part of the success gate.
if verify_ui /usr/data/.mq_ui.tmp \
&& chmod +x /usr/data/.mq_ui.tmp \
&& mv -f /usr/data/.mq_ui.tmp /usr/data/mq_ui \
&& publish_symlink \
&& verify_ui /usr/data/mq_ui; then
installed=1; log "installed verified mq_ui from ${src:-?} (size $MSIZE)"
TO sync 2>/dev/null || log "post-install sync slow/timed-out (ubifs is sync-mounted; already durable)"
else
log "SD copy failed verification/publish -> not installed"
fi
fi
rm -f /usr/data/.mq_ui.tmp 2>/dev/null # always clean the temp, incl. a timed-out/partial copy
# FINALIZE (fail-closed): if we did not publish this boot, make sure only a manifest-verified UI
# can run. A verified-but-unpublished binary gets its exec bit + symlink repaired; anything that
# does NOT verify is quarantined so the stock UI runs.
if [ "$installed" != 1 ]; then
if verify_ui /usr/data/mq_ui; then
publish_symlink || quarantine "finalize repair failed" || exit 1
elif [ -e /usr/data/mq_ui ] || [ -e /usr/data/mq_player ]; then
quarantine "unverified override" || exit 1
fi
fi
disarm # clean end: fail-closed state is settled, disarm so no late signal quarantines it
exit 0
+88
View File
@@ -0,0 +1,88 @@
#!/bin/sh
# diskOS dev/recovery: USB CDC-ACM serial console on the device USB-C port.
# Host enumerates 0525:a4a7 -> /dev/ttyACM0 -> root shell (raw, no login).
#
# Robust against the failure that killed the previous attempt: the stock
# serial_config.sh binds the UDC exactly once and never retries, so a UDC that
# registers (or a host that plugs in) a moment later was missed. This runs a
# persistent supervisor: (re)bind whenever a UDC is present, keep a shell alive
# on ttyGS0. All steps best-effort + logged to a persistent (rw) partition.
LOG=/usr/data/fiio/usbserial.log
G=/sys/kernel/config/usb_gadget/serial_demo
log() { echo "$(date 2>/dev/null) $*" >> "$LOG" 2>/dev/null; }
build_gadget() {
[ -d /sys/kernel/config/usb_gadget ] || mount -t configfs none /sys/kernel/config 2>/dev/null
[ -d "$G" ] && return 0
mkdir -p "$G" || return 1
echo 0x0525 > "$G/idVendor"
echo 0xa4a7 > "$G/idProduct"
echo 0x0200 > "$G/bcdUSB"
echo 0x2400 > "$G/bcdDevice"
echo 0x02 > "$G/bDeviceClass"
echo 0x00 > "$G/bDeviceSubClass"
echo 0x00 > "$G/bDeviceProtocol"
mkdir -p "$G/strings/0x409"
echo "INGENIC" > "$G/strings/0x409/manufacturer"
echo "diskOS Serial" > "$G/strings/0x409/product"
echo "diskos-serial" > "$G/strings/0x409/serialnumber"
mkdir -p "$G/configs/c.1/strings/0x409"
echo 120 > "$G/configs/c.1/MaxPower"
echo 0x80 > "$G/configs/c.1/bmAttributes"
echo "serial" > "$G/configs/c.1/strings/0x409/configuration"
mkdir -p "$G/functions/acm.0"
ln -sf "$G/functions/acm.0" "$G/configs/c.1/" 2>/dev/null
log "gadget built"
}
# Best-effort nudge into peripheral mode. dr_mode=otg already auto-switches to
# device when plugged into a host (CC/pin), so this is only a safety net. Only
# the unambiguous "device" token is written -- never anything that could select
# host mode and break enumeration.
force_device_mode() {
for f in /sys/devices/platform/*otg*/dwc2_mode \
/sys/devices/platform/*otg*/dwc2_force_dr_mode \
/sys/devices/platform/*/13500000.otg/dwc2_mode; do
[ -e "$f" ] || continue
echo device > "$f" 2>/dev/null && log "wrote device-mode to $f"
done
}
bound() { [ -n "$(cat "$G/UDC" 2>/dev/null)" ]; }
bind_when_ready() {
udc=$(ls /sys/class/udc/ 2>/dev/null | head -n1)
[ -n "$udc" ] || return 1
echo "$udc" > "$G/UDC" 2>/dev/null && { log "bound UDC=$udc"; return 0; }
return 1
}
# Delegate the ttyGS0 shell to diskos-debug (the SINGLE owner - fuser-guarded + self-respawning).
# Two independent shell respawners on one tty is the classic "answers once then goes silent" wedge,
# so this script no longer binds its own shell; it only builds the gadget and asks diskos-debug to
# attach the one shell. Idempotent: serial-on is a no-op if a shell already owns ttyGS0.
DEBUG=/usr/project/diskos-debug.sh
ensure_shell() {
[ -c /dev/ttyGS0 ] || return 0
[ -x "$DEBUG" ] && "$DEBUG" serial-on >/dev/null 2>&1
}
main() {
: > "$LOG" 2>/dev/null
log "S99usbserial start"
build_gadget
force_device_mode
while true; do
bound || bind_when_ready
ensure_shell
sleep 2
done
}
case "$1" in
start) main & ;;
*) exit 1 ;;
esac
exit 0
+165
View File
@@ -0,0 +1,165 @@
#!/bin/sh
# diskOS debug access. Two independent channels, both OFF unless explicitly enabled:
# - SSH (dropbear over WiFi) with a RANDOM per-enable password. We NEVER use or expose the
# stock root password: the caller (mq_ui) passes a fresh sha512 crypt hash, which we place in a
# private shadow file bind-mounted over /etc/shadow (the on-disk stock /etc/shadow is untouched).
# - SERIAL (a root shell on the USB gadget /dev/ttyGS0). Local USB only; no network exposure.
# State + keys live under /usr/data/sshd (persists across rootfs flashes). Idempotent; every op is
# best-effort so a missing tool or busy resource never wedges the caller.
#
# Usage:
# diskos-debug.sh ssh-on <root_sha512_hash> # start dropbear with this password hash
# diskos-debug.sh ssh-off # stop dropbear + drop the shadow overlay
# diskos-debug.sh serial-on # bind ONE root shell to /dev/ttyGS0
# diskos-debug.sh serial-off # stop the serial shell
# diskos-debug.sh status # print: SSH=on/off SERIAL=on/off
SELF=/usr/data/sshd
DB="$SELF/dropbearmulti"
KEYS="$SELF/keys"
SHADOW="$SELF/shadow" # our private shadow, bind-mounted over /etc/shadow while SSH is on
SERIALPID="$SELF/serial.pid" # pid of the single ttyGS0 shell supervisor
BUNDLED=/usr/project/dropbearmulti # read-only rootfs copy shipped in the image
# FAIL-CLOSED test for the private shadow overlay. Returns 0 (present) if it is bind-mounted over
# /etc/shadow OR if we cannot tell (/proc/mounts unreadable); returns 1 (absent) ONLY when a readable
# /proc/mounts definitively shows no such mount. `grep` exit codes: 0=match, 1=no match, >=2=error;
# we must treat "no match" as absent but any error as still-present, so we never report a clean state
# on uncertainty.
overlay_present() {
grep -q ' /etc/shadow ' /proc/mounts 2>/dev/null
_g=$?
[ "$_g" -eq 1 ] && return 1 # readable, definitively no overlay
return 0 # matched (0) or read error (>=2) -> present/unknown, fail closed
}
ensure_db() {
mkdir -p "$KEYS" 2>/dev/null
# Provision/refresh the dropbear binary from the shipped rootfs copy (survives flashes on /usr/data).
if [ ! -x "$DB" ] && [ -f "$BUNDLED" ]; then cp "$BUNDLED" "$DB" 2>/dev/null; chmod +x "$DB" 2>/dev/null; fi
[ -x "$DB" ] || return 1
[ -s "$KEYS/ed25519_host_key" ] || "$DB" dropbearkey -t ed25519 -f "$KEYS/ed25519_host_key" >/dev/null 2>&1
[ -s "$KEYS/rsa_host_key" ] || "$DB" dropbearkey -t rsa -s 2048 -f "$KEYS/rsa_host_key" >/dev/null 2>&1
return 0
}
# FAIL-CLOSED: SSH starts only once the private-password overlay is PROVEN active. Any failure (no
# hash, stuck overlay, empty/garbled shadow, bind failure, dropbear not up) returns non-zero WITHOUT
# leaving dropbear authenticating against the stock /etc/shadow.
ssh_on() {
hash="$1"
[ -n "$hash" ] || { echo "err: no hash"; return 1; }
ensure_db || { echo "err: no dropbear binary"; return 1; }
# STOP any already-running dropbear BEFORE touching the overlay. Otherwise, in the window between
# unmounting the old overlay and binding the new one, a running daemon would authenticate against
# the STOCK /etc/shadow (and any later failure would leave it there). No daemon runs during the swap.
for p in $(pgrep -f "dropbearmulti dropbear" 2>/dev/null); do kill "$p" 2>/dev/null; done
i=0; while pgrep -f "dropbearmulti dropbear" >/dev/null 2>&1 && [ "$i" -lt 5 ]; do sleep 1; i=$((i+1)); done
for p in $(pgrep -f "dropbearmulti dropbear" 2>/dev/null); do kill -9 "$p" 2>/dev/null; done
pgrep -f "dropbearmulti dropbear" >/dev/null 2>&1 && { echo "err: could not stop existing dropbear"; return 1; }
# Drop any existing overlay and CONFIRM it is gone - reading /etc/shadow while it still aliases
# $SHADOW would let `>` truncate it to empty. If it will not unmount, refuse.
if overlay_present; then
umount /etc/shadow 2>/dev/null
overlay_present && { echo "err: shadow overlay stuck"; return 1; }
fi
[ -f /etc/shadow ] || { echo "err: no /etc/shadow"; return 1; }
# Build the private shadow (root line = our random hash) and PROVE it holds that hash before
# trusting it - never bind an empty or malformed shadow.
awk -v h="$hash" -F: 'BEGIN{OFS=":"} $1=="root"{$2=h} {print}' /etc/shadow > "$SHADOW" 2>/dev/null \
|| { echo "err: shadow gen failed"; return 1; }
chmod 600 "$SHADOW" 2>/dev/null
awk -F: -v h="$hash" '$1=="root" && $2==h{ok=1} END{exit ok?0:1}' "$SHADOW" 2>/dev/null \
|| { echo "err: shadow bad"; rm -f "$SHADOW"; return 1; }
mount -o bind "$SHADOW" /etc/shadow 2>/dev/null || mount --bind "$SHADOW" /etc/shadow 2>/dev/null
# CONFIRM the overlay is live BEFORE starting SSH; if the bind failed, dropbear would authenticate
# against the STOCK /etc/shadow (stock root password reachable over the network) - refuse.
grep -q ' /etc/shadow ' /proc/mounts 2>/dev/null || { echo "err: overlay failed, refusing SSH"; return 1; }
pgrep -f "dropbearmulti dropbear" >/dev/null 2>&1 || \
"$DB" dropbear -p 22 -r "$KEYS/ed25519_host_key" -r "$KEYS/rsa_host_key" >/dev/null 2>&1
if ! pgrep -f "dropbearmulti dropbear" >/dev/null 2>&1; then
# dropbear failed to start: tear the overlay back down and CONFIRM it is gone (retry once).
# Report which state we ended in so the caller never assumes a clean OFF while it is still mounted.
umount /etc/shadow 2>/dev/null
overlay_present && { sleep 1; umount /etc/shadow 2>/dev/null; }
if overlay_present; then
echo "err: dropbear did not start AND overlay stuck"; return 2
fi
echo "err: dropbear did not start"; return 1
fi
echo on
}
# FAIL-CLOSED: kill dropbear and CONFIRM it is gone BEFORE dropping the overlay (a surviving process
# would otherwise fall back to the stock /etc/shadow once the bind is removed). Report the REAL state.
ssh_off() {
for p in $(pgrep -f "dropbearmulti dropbear" 2>/dev/null); do kill "$p" 2>/dev/null; done
i=0; while pgrep -f "dropbearmulti dropbear" >/dev/null 2>&1 && [ "$i" -lt 4 ]; do sleep 1; i=$((i+1)); done
for p in $(pgrep -f "dropbearmulti dropbear" 2>/dev/null); do kill -9 "$p" 2>/dev/null; done
# brief settle, then drop the overlay. Whole path stays under ~6s so the UI's bounded call
# (12s, see debug_ui.c disable_dbg) always lets us finish the umount before it can kill us -
# otherwise the UI could report OFF while the overlay is still mounted.
i=0; while pgrep -f "dropbearmulti dropbear" >/dev/null 2>&1 && [ "$i" -lt 2 ]; do sleep 1; i=$((i+1)); done
# NEVER drop the overlay while a daemon might still be alive: if a process somehow survived SIGKILL,
# unmounting would drop it back onto the STOCK /etc/shadow. Keep the overlay (so it stays bound to
# OUR shadow) and fail instead. Only umount once dropbear is CONFIRMED gone.
if pgrep -f "dropbearmulti dropbear" >/dev/null 2>&1; then
echo "err: dropbear still running - overlay kept, refusing to expose stock shadow"; return 1
fi
overlay_present && umount /etc/shadow 2>/dev/null
if overlay_present; then
echo "err: overlay stuck"; return 1
fi
echo off
}
# True only if $SERIALPID names a LIVE process that is actually OUR supervisor. A bare `kill -0` would
# be fooled by PID reuse (some unrelated process now holding that number) - so we also confirm the
# process's cmdline still contains the ttyGS0 supervisor marker before trusting/signalling it.
serial_alive() {
[ -f "$SERIALPID" ] || return 1
_sp=$(cat "$SERIALPID" 2>/dev/null); [ -n "$_sp" ] || return 1
kill -0 "$_sp" 2>/dev/null || return 1
tr '\0' ' ' < "/proc/$_sp/cmdline" 2>/dev/null | grep -q 'ttyGS0'
}
serial_on() {
[ -c /dev/ttyGS0 ] || { echo "no ttyGS0"; return 1; }
# Exactly ONE supervisor owns ttyGS0. A plain `fuser` guard is NOT enough: between shell respawns
# the supervisor sleeps 1s without holding the tty, so a repeated serial-on (e.g. S99's loop) would
# see no owner and start a SECOND supervisor = the two-shell wedge. Guard on the SUPERVISOR pid
# (which stays alive across that gap, validated as really ours) via a pidfile instead.
if serial_alive; then echo on; return 0; fi
rm -f "$SERIALPID" 2>/dev/null # stale/reused pid - clear it so a real supervisor can start
setsid sh -c 'echo $$ > '"$SERIALPID"'; while true; do /bin/sh </dev/ttyGS0 >/dev/ttyGS0 2>&1; sleep 1; done' </dev/null >/dev/null 2>&1 &
# Confirm the supervisor actually came up (setsid/fork/pidfile-write can all fail) before claiming
# success - otherwise the caller would show "serial on" with no shell behind it. Bounded to ~2s
# (portable whole-second sleep) so it stays well under the UI's serial-on timeout.
serial_alive || sleep 1
serial_alive || sleep 1
if serial_alive; then echo on; return 0; fi
echo "err: serial supervisor did not start"; return 1
}
serial_off() {
# Only signal the pidfile's process if it is verifiably OUR supervisor (never a reused PID).
if serial_alive; then kill "$(cat "$SERIALPID" 2>/dev/null)" 2>/dev/null; fi
rm -f "$SERIALPID" 2>/dev/null
fuser -k /dev/ttyGS0 2>/dev/null
echo off
}
status() {
s=off; pgrep -f "dropbearmulti dropbear" >/dev/null 2>&1 && s=on
r=off; serial_alive && r=on
echo "SSH=$s SERIAL=$r"
}
case "$1" in
ssh-on) ssh_on "$2" ;;
ssh-off) ssh_off ;;
serial-on) serial_on ;;
serial-off) serial_off ;;
status) status ;;
*) echo "usage: $0 {ssh-on <hash>|ssh-off|serial-on|serial-off|status}"; exit 1 ;;
esac
BIN
View File
Binary file not shown.
Executable
BIN
View File
Binary file not shown.
+5
View File
@@ -0,0 +1,5 @@
# Python runtime dependencies for the diskOS installer.
# install.sh pip-installs these into a local .venv. Versions are pinned so the
# vendored license texts in licenses/ match what actually gets installed.
pyusb==1.3.1 # mask-ROM USB device detection (BSD-3-Clause)
pycryptodome==3.23.0 # AES-decrypt of FiiO OTA chunks (BSD-2-Clause + public-domain)
@@ -0,0 +1,120 @@
From 08f128d82f8e86dac5ca277d4fe4cc3fd7fef204 Mon Sep 17 00:00:00 2001
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
Date: Mon, 24 Aug 2026 22:51:34 +1000
Subject: [PATCH 1/8] baseline: burner_x2000 SPL that loads+executes on device
(-fcommon + mask-ROM return shim)
---
arch/mips/cpu/xburst2/x2000/start.S | 23 +++++++++++++++++++++++
config.mk | 2 +-
tools/ingenic-tools/mmc_params | Bin 0 -> 14472 bytes
3 files changed, 24 insertions(+), 1 deletion(-)
create mode 100755 tools/ingenic-tools/mmc_params
diff --git a/arch/mips/cpu/xburst2/x2000/start.S b/arch/mips/cpu/xburst2/x2000/start.S
index caab455..2dcc1e2 100755
--- a/arch/mips/cpu/xburst2/x2000/start.S
+++ b/arch/mips/cpu/xburst2/x2000/start.S
@@ -167,6 +167,29 @@ cache_alloc_a_line:
li sp, 0x80001000
#endif
+#ifdef CONFIG_BURNER
+ /*
+ * DDR-only USB stage-1 (burner mode): board_init_f() brings up clocks and
+ * SDRAM and then RETURNS (see arch/mips/cpu/xburst2/x2000/soc.c, the
+ * CONFIG_BURNER branch). For usbboot to keep driving the USB session we
+ * must hand control back to the mask ROM afterwards. Preserve the mask-ROM
+ * return address (and sp) in a fixed TCSM scratch slot across the call --
+ * board_init_f repoints/uses the stack internally, so a stack-relative save
+ * is not reliable for the outer return. 0xb24017f0 lies in the param/pad
+ * region below the code (offset 0x800) and is untouched by DDR init.
+ */
+ li t0, 0xb24017f0
+ sw ra, 0(t0)
+ sw sp, 4(t0)
+ jal board_init_f
+ nop
+ li t0, 0xb24017f0
+ lw ra, 0(t0)
+ lw sp, 4(t0)
+ jr ra
+ nop
+#else
j board_init_f
nop
+#endif
diff --git a/config.mk b/config.mk
index f71e145..d78be30 100755
--- a/config.mk
+++ b/config.mk
@@ -195,7 +195,7 @@ endif
ARFLAGS = $(error update your Makefile to use cmd_link_o_target and not AR)
RELFLAGS= $(PLATFORM_RELFLAGS)
DBGFLAGS= -g # -DDEBUG
-OPTFLAGS= -Os #-fomit-frame-pointer
+OPTFLAGS= -Os -fcommon #-fomit-frame-pointer (-fcommon: 2013 tree relies on tentative defs; GCC>=10 defaults -fno-common)
OBJCFLAGS += --gap-fill=0xff
diff --git a/tools/ingenic-tools/mmc_params b/tools/ingenic-tools/mmc_params
new file mode 100755
index 0000000000000000000000000000000000000000..78adebd875be1ac2ec4d41c346622d76fea5e1c4
GIT binary patch
literal 14472
zcmeHOZ)_Y_5r1bp^~H70ra0gvZM_P1)lhu7a~#V_Wa58G)>Rwa)&?pXuIsx!`|$l^
zZ%v%4#MhV<pBzgrNVFASEIuVdkf<t^sYJLo5U7w!Q&eQWG-*YUt<vB^DQST$Gy7)F
z>%|uTKe1!o{@(m%=FQu=x9@iEo+l36bFj?k6D;N8lLEEbTO`v-1~p6#fKJgaHo@^W
zajUoq^a`7k_D%_4m9kK_8vVqV17ch~HrBvfB@G#*@CXqxZapbhN(-Z?l{&_4z$WQ#
zEYLU@*<Q-0U@(YcA4@on4j_!qIIPW7vuzer9WJE0%o1`Osu=ea#XUuFjLVddk?V;y
z!B;z-hZ{p+Lt%8sjZmB$du5nl#2hFOTs33=PQHGM%PV#_!i}wx7L1(lK8VA*{IkMu
z^Zk@>z4u|9>d#2!6+4rOp|;kY$yjqTkscdw9&c}JZfgzZGQk#m2skbUUO1-?9Uc_W
zO%XXNqbSQuo%=&u9of<U+uE}~f8$8mFW#Cy^L$|IJCB$Bc;EBrgX6{+^g+S?c#5Eo
z?P_?TkF3XI(2^YDCH>_T;(D?J40LI)a``%F$|^=G{QztEWB#@HPp`w@y$;{74u2MS
z1zv8!oNMK6T!%joyaF$`>;q!En?yYl$(dSoG!h*djl{J?5{RskNSkqFgrRFOk;&?5
zpkanY(b+H~DJ_9abX<$X6KO4(ctjV`WG1JJqejBiMKY)BqXGkP2DOPp_w;r5L|THo
zf~}?YN~<NfyTtBl6_LJydm}O3(1#N_Q#S_g?MY_R`hYf+)FJ0^DwC#BM5ODQjyQ9C
zFq<mig?~Pnxp?IH>I2I|aQb}Rm|GGXadyXvt4ky{;R<7rKDHI@<>FD&pMByRFdfUp
z6zC|t-tjt<{jlU`X+2{;M7+OK+L>p4VZY>YuH&3zx#HlR*T<rR=e{sz*}>n;od8~U
z@OWLZ%n^?tCtM@6op$hey|SEh@b>2n8Ri|lyk4cD=-}xi%QpPf!9#&d@`{76DzRR}
ztAJMluL52Lyb5>~@G9`HSKtpdw|}5c{?@NfZ}`<tA=Hyav&?!$o&1sig58<5`wKu@
zO-VS`G;|8|A3@8~o0et8XKfvC%$8nV(eZ|C>BSWtZ=jZ*S<&&vY3W-lI^HlXeQia@
z8>OWaCEaQ|4B6u~4ZXt7Z#DfUxLSYRrT@~UzwFX4y7cod{kc_o*Faz4-N6T-OiE0h
zu4uXwhNl*K8|%ZxpY%4`cg&Mknc1dJf8>XF>gvqyGXWtM=im(Hu{P@TKx2JOy{pa+
ztvR_7NGP%Lxg%W<T~Mcw`@_Za7`S*GA_^By7Hg(n0ySJzXOfL|Z&lVbi1OaXYWo3E
zEnF*HhUC?YVQ@ZKoVW^|S3^n-QrhXm#l<_og!Fs}x_Rsa@vsmRfteE)<o!NALO%Vc
z_pyt@ix79f5qIr|WrbfokMB?6^5Qwr)ESc!12F*v#MMq-uP|@xg9Ltv-|mS2E;uZ0
z#FMzZcmn$>E(y@s^(;I>@DL}_^>sKb?tufmxnF^#^8F3J-B-BudA0DSI{EA6{(%GG
zV)!L>rsIp?XKnr%d@=HFJjnjQ_W`5MZ0JVVbKTqwQ~4%r!&KgAU8!lvW4{*&!GDYG
zzxx)19XHg%viicc{pt(X%T?b+_0kQq4mx=46S4!pbw$oQj>q|)??AH{yK7LL?05#7
zYT>F`txk752g+jKU*V);FxHD3z5}}N2*j51WBk%lFhUfz?Q5@ewE^jgR{^gAUIn}g
zcopy};8nn@fL8&p0$v6FM-}kF<KSRU8`k$KO*tiQWK!`&Qdi6jLRF>s6#UkOmIH>7
zF{(r=6;*QCq!P`HrA?(nX$rNEE8WLTJ-41MnTd{qv1de&j_y@HgFlBk`V+ow<@@lr
zUi=DR?st}j-z_N1mNg3)0z8d8U=gtP_m<TUh=RYRqWB)UU--srecP%l{j>0Ri#+Zb
zn19Ez?m&m$O8Wu55t^7M1Ud46B2arUP=9yL%}4!tv488HkMC;Sjx@&O?_g8lX9pq)
zg1iZ@Jn&g0NJ4<8;I#n!Fh1)a4Ah<~>kZUDUfvZ@CM$Xaon?os0!mk)zAI4M9q@NK
ze|@4(Jn$;uRluu&R{^gAUIn}gcopy};8o!Nssg+}j`zdiqXY^*i=b3XC~eT&MEaw&
ze{Kuuyzg!s>3+hkguMR_pOH}5{>K|u2K95a*^T$G)l!4^t}T$A_n<9c5C}ij)Js)t
zCS;&6F-7~>@aIkxe7-}$=PMN63-?i}ih3fL|11rJ$6X{p-YduXZzrDp{%pzfgSy%j
z{FZ2+ub=vZU*v3^>kf~cw!TQ`|32w_9@PDR4S0XIyTcGYgmx146Fy9sCCn4f61w~O
zM>_AfJk-;(SGjX=2p;dpl<+Rtp&Dv#8?)7x<1MYhP-`%}gA76hb0ay^Fts5Oge|hV
zkrlyo#?*tu>9JtefPJ!tdCWl#jU`}1bs|PoS9f2tsSOL;eMHNRh+ynkI(IB3(KMvx
zOS+LuWYVjY2-plgsbK)MvPlz1k$@vKgTonW<n*Wrn)*1Xus1gW-kF$YY9gqQMB;{)
z(jy}==#4emM?^CW4Tg>p+=f(IDgm9z@S$8z1f!W$N>Ae#1OK7m^@DSduM7A8Mey~?
zX?UKpj>`aEBOJfp{(tu8>w<OsuEZJd{yzZx{=_M`MZhV0Kyk*Oq6>vlaXLfW9e)V8
z_uv}i@$)*w$oY94a*zK$h{qaoJg-xX?Nl%vBQ`mn*NX>%!y$7#uX~KV&Vh?9?)q!M
z;u^y7ylyb^`pe^IKgKk~<C?@euS<;mGOb->=lF>hUxo(Ol;e4wWGs>+=Xam~S1G=m
z{CM4EJne|bnz`ej01n5+{g*b9(|W|8N7T*Vz5n<fnloOZIL15&67n*~_@pa-jtq?K
z$K9~bIOmE#M+U|$2NH4|;~7`H@*(NS_#nSAu6R<#Syw!Nt~2uIJ^Q<_pYKt8DUCv&
zgcGDPxZ{5S2CP5F=N0M6*ecc1(H;LYusGxA73s=Ylxpe7^M{GopaC0+N_*}3K8F8q
z$L-HL;~NlL<A~?`oLSiAgTj7NThW<+8w@yi`SYDWkNN+w`2VeN{XpS3e*eD-9G*YN
z^L@_LPV|QV50g+jay;XEU~$HaPI3)N<UGWd^0WRIXkcHQzqV6aYAK%cNLJ?JHX{BD
hAm%6cl8NJ~j3pj@QJl!Rr9~b)sKY9DB%@0ee*=w<BPsv@
literal 0
HcmV?d00001
--
2.43.0
@@ -0,0 +1,76 @@
From 8f93e72bd6b1c770269ce746d401cebb063e71dc Mon Sep 17 00:00:00 2001
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
Date: Mon, 24 Aug 2026 22:55:29 +1000
Subject: [PATCH 2/8] =?UTF-8?q?ddr:=20add=20LPDDR3=20support=20(mr11=20fie?=
=?UTF-8?q?ld,=20LPDDR3=20MR=20sequence,=20W63AH6NKB=20type-force)=20?=
=?UTF-8?q?=E2=80=94=20ported=20from=20tobunto=20X2000?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
arch/mips/cpu/xburst2/ddr_innophy.c | 20 ++++++++++++++++++++
arch/mips/cpu/xburst2/ddr_reg_data.h | 2 ++
2 files changed, 22 insertions(+)
diff --git a/arch/mips/cpu/xburst2/ddr_innophy.c b/arch/mips/cpu/xburst2/ddr_innophy.c
index 5257e3a..e08a5df 100755
--- a/arch/mips/cpu/xburst2/ddr_innophy.c
+++ b/arch/mips/cpu/xburst2/ddr_innophy.c
@@ -454,6 +454,21 @@ static void ddrc_dfi_init(enum ddr_type type, int bypass)
ddr_writel(DDRC_LMR_MR(2), DDRC_LMR); //MR2
ddr_writel(DDRC_LMR_MR(3), DDRC_LMR); //MR3
ddr_writel(DDRC_DLMR_VALUE | DDRC_LMR_START | DDRC_LMR_CMD_ZQCL_CS0, DDRC_LMR); //ZQCL
+#undef DDRC_LMR_MR
+ break;
+ case LPDDR3:
+ /* LPDDR3 MR sequence - ported from tobunto/u-boot X2000 (matches the vendor
+ * disc_spl.bin trace): MR63,10,1,2,3,11 each followed by mdelay(1); no ZQ. */
+#define DDRC_LMR_MR(n) \
+ DDRC_DLMR_VALUE | DDRC_LMR_START | DDRC_LMR_CMD_LMR | \
+ ((DDR_MR##n##_VALUE & 0xff) << 24) | \
+ (((DDR_MR##n##_VALUE >> 8) & 0xff) << (16))
+ ddr_writel(DDRC_LMR_MR(63), DDRC_LMR); mdelay(1); //set MRS reset
+ ddr_writel(DDRC_LMR_MR(10), DDRC_LMR); mdelay(1); //set IO calibration
+ ddr_writel(DDRC_LMR_MR(1), DDRC_LMR); mdelay(1); //set MR1
+ ddr_writel(DDRC_LMR_MR(2), DDRC_LMR); mdelay(1); //set MR2
+ ddr_writel(DDRC_LMR_MR(3), DDRC_LMR); mdelay(1); //set MR3
+ ddr_writel(DDRC_LMR_MR(11), DDRC_LMR); mdelay(1); //set MR11
#undef DDRC_LMR_MR
break;
default:
@@ -556,6 +571,11 @@ void sdram_init(void)
soc_ddr_init();
type = get_ddr_type();
+ /* Snowsky Disc = Winbond W63AH6NKB-BI LPDDR3. The controller CFG.TYPE field reads as
+ * LPDDR2(5) for this part (the vendor SPL dispatches on the logical record type=3, not
+ * CFG.TYPE), so force the LPDDR3 MR sequence here. Only ddrc_dfi_init consumes `type`
+ * (the X2000 prev_ddr_init hook is a no-op). */
+ type = LPDDR3;
clk_set_rate(DDR, gd->arch.gi->ddrfreq);
if(ddr_hook && ddr_hook->prev_ddr_init)
ddr_hook->prev_ddr_init(type);
diff --git a/arch/mips/cpu/xburst2/ddr_reg_data.h b/arch/mips/cpu/xburst2/ddr_reg_data.h
index 4878267..b48575f 100755
--- a/arch/mips/cpu/xburst2/ddr_reg_data.h
+++ b/arch/mips/cpu/xburst2/ddr_reg_data.h
@@ -27,6 +27,7 @@ struct ddr_registers
uint32_t ddr_mr2;
uint32_t ddr_mr3;
uint32_t ddr_mr10;
+ uint32_t ddr_mr11;
uint32_t ddr_mr63;
uint32_t ddr_chip0_size;
uint32_t ddr_chip1_size;
@@ -59,6 +60,7 @@ extern struct ddr_registers *g_ddr_param;
#define DDR_MR2_VALUE g_ddr_param->ddr_mr2
#define DDR_MR3_VALUE g_ddr_param->ddr_mr3
#define DDR_MR10_VALUE g_ddr_param->ddr_mr10
+#define DDR_MR11_VALUE g_ddr_param->ddr_mr11
#define DDR_MR63_VALUE g_ddr_param->ddr_mr63
#define DDR_CHIP_0_SIZE g_ddr_param->ddr_chip0_size
#define DDR_CHIP_1_SIZE g_ddr_param->ddr_chip1_size
--
2.43.0
@@ -0,0 +1,149 @@
From 15c4698350fdd6ef22a15ce8daaab4b332f9762a Mon Sep 17 00:00:00 2001
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
Date: Mon, 24 Aug 2026 23:17:06 +1000
Subject: [PATCH 3/8] ddr: instrument DDR bring-up with TCSM breadcrumbs +
bounded polls (diagnostic build)
---
arch/mips/cpu/xburst2/ddr_innophy.c | 45 +++++++++++++++++++++++------
1 file changed, 36 insertions(+), 9 deletions(-)
diff --git a/arch/mips/cpu/xburst2/ddr_innophy.c b/arch/mips/cpu/xburst2/ddr_innophy.c
index e08a5df..91cf6a3 100755
--- a/arch/mips/cpu/xburst2/ddr_innophy.c
+++ b/arch/mips/cpu/xburst2/ddr_innophy.c
@@ -46,6 +46,23 @@
#include <asm/io.h>
#include <asm/arch/clk.h>
#define CONFIG_DWC_DEBUG 0
+
+/* ---- DDR bring-up diagnostics (breadcrumbs to TCSM pad @0xb24017c0, below the
+ * start.S return-shim scratch at 0x17f0). usbboot uploads this region after the SPL
+ * returns to the mask ROM, so ONE device cycle localises any DDR-init stall.
+ * Layout: [0]=magic [1]=last stage reached [2]=first fail id [3]=status@fail [4]=fail count */
+#define DDR_DIAG ((volatile unsigned int *)0xb24017c0)
+#define DDR_DIAG_MAGIC 0xD1A6C0DEu
+static inline void ddr_diag_init(void){ DDR_DIAG[0]=DDR_DIAG_MAGIC; DDR_DIAG[1]=0; DDR_DIAG[2]=0; DDR_DIAG[3]=0; DDR_DIAG[4]=0; __asm__ __volatile__("sync"); }
+static inline void ddr_diag_stage(unsigned int s){ DDR_DIAG[1]=s; __asm__ __volatile__("sync"); }
+static inline void ddr_diag_fail(unsigned int id, unsigned int status){ if(DDR_DIAG[2]==0){ DDR_DIAG[2]=id; DDR_DIAG[3]=status; } DDR_DIAG[4]++; __asm__ __volatile__("sync"); }
+/* bounded busy-wait: wait for (cond); on ~1e6-iter timeout record (id,statusexpr) and stop waiting
+ * (never spins forever, so the SPL always returns and the breadcrumb is readable). */
+#define DDR_BOUND(cond, id, statusexpr) do { \
+ unsigned int _bt = 1000000u; \
+ while(!(cond)) { if(!--_bt){ ddr_diag_fail((id), (unsigned int)(statusexpr)); break; } } \
+ } while(0)
+
#define ddr_hang() do{ \
printf("%s %d\n",__FUNCTION__,__LINE__); \
hang(); \
@@ -250,7 +267,7 @@ static void ddrp_pll_init(void)
ddr_writel(0, DDRP_INNOPHY_PLL_CTRL);
#endif
- while(!(ddr_readl(DDRP_INNOPHY_PLL_LOCK) & 1 << 3));
+ DDR_BOUND(ddr_readl(DDRP_INNOPHY_PLL_LOCK) & (1 << 3), 10 /*PLL_LOCK*/, ddr_readl(DDRP_INNOPHY_PLL_LOCK));
}
static void ddrp_register_cfg(void)
@@ -311,14 +328,15 @@ static void ddrp_hardware_calibration(void)
unsigned int timeout = 1000000;
/* ddr_writel(ddr_readl(DDRP_INNOPHY_TRAINING_CTRL) | 1, DDRP_INNOPHY_TRAINING_CTRL); */
ddr_writel(1, DDRP_INNOPHY_TRAINING_CTRL);
+ /* bounded (fixes the original timeout-- unsigned wrap); diagnostic, no hang() */
do
{
val = ddr_readl(DDRP_INNOPHY_CALIB_DONE);
- } while (((val & 0xf) != 0x3) && timeout--);
+ } while (((val & 0xf) != 0x3) && --timeout);
- if(!timeout) {
- printf("timeout:INNOPHY_CALIB_DONE %x\n", ddr_readl(DDRP_INNOPHY_CALIB_DONE));
- hang();
+ if(((val & 0xf) != 0x3)) {
+ ddr_diag_fail(30 /*CALIB_DONE*/, val);
+ ddr_writel(0, DDRP_INNOPHY_TRAINING_CTRL); /* clear training on failure (Codex) */
}
ddr_writel(0, DDRP_INNOPHY_TRAINING_CTRL);
@@ -424,7 +442,7 @@ static void ddrc_dfi_init(enum ddr_type type, int bypass)
FUNC_ENTER();
ddr_writel(DDRC_DWCFG_DFI_INIT_START, DDRC_DWCFG); // dfi_init_start high
ddr_writel(0, DDRC_DWCFG); // set buswidth 16bit
- while(!(ddr_readl(DDRC_DWSTATUS) & DDRC_DWSTATUS_DFI_INIT_COMP)); //polling dfi_init_complete
+ DDR_BOUND(ddr_readl(DDRC_DWSTATUS) & DDRC_DWSTATUS_DFI_INIT_COMP, 20 /*DFI_INIT_COMP*/, ddr_readl(DDRC_DWSTATUS)); //polling dfi_init_complete
ddr_writel(0, DDRC_CTRL); //set dfi_reset_n high
ddr_writel(DDRC_CFG_VALUE, DDRC_CFG);
@@ -496,8 +514,7 @@ static void ddr_calibration(struct ddr_calib_value *dcv, int div)
val = REG32(CPM_DDRCDR);
val |= ((1 << 29) | (1 << 25));
REG32(CPM_DDRCDR) = val;
- while((REG32(CPM_DDRCDR) & (1 << 24)))
- ;
+ DDR_BOUND(!(REG32(CPM_DDRCDR) & (1 << 24)), 40 /*DDRCDR_BUSY*/, REG32(CPM_DDRCDR));
/* // Set clock divider */
val = REG32(CPM_DDRCDR);
val &= ~(0xf);
@@ -505,7 +522,7 @@ static void ddr_calibration(struct ddr_calib_value *dcv, int div)
REG32(CPM_DDRCDR) = val;
// Polling PHY_FREQ_DONE
- while(((ddr_readl(DDRC_DWSTATUS) & (1 << 3 | 1 << 1)) & 0xf) != 0xa);
+ DDR_BOUND(((ddr_readl(DDRC_DWSTATUS) & (1 << 3 | 1 << 1)) & 0xf) == 0xa, 50 /*PHY_FREQ_DONE*/, ddr_readl(DDRC_DWSTATUS));
ddrp_hardware_calibration();
/* ddrp_software_calibration(); */
@@ -567,6 +584,8 @@ void sdram_init(void)
int bypass = 0;
debug("sdram init start\n");
+ ddr_diag_init(); /* breadcrumb record @0xb24017c0 */
+ ddr_diag_stage(1); /* entered sdram_init */
soc_ddr_init();
@@ -582,26 +601,33 @@ void sdram_init(void)
rate = clk_get_rate(DDR);
debug("DDR clk rate %d\n", rate);
+ ddr_diag_stage(2);
ddrc_reset_phy();
+ ddr_diag_stage(3);
ddr_phy_init();
dump_ddrp_register();
+ ddr_diag_stage(4);
ddrc_dfi_init(type, bypass);
+ ddr_diag_stage(5);
ddrc_prev_init();
/**
* bypass = 1 or calibration = 0
*/
bypass = 0;
+ ddr_diag_stage(6);
ddrp_calibration(bypass);
+ ddr_diag_stage(7);
ddrc_post_init();
if(ddr_hook && ddr_hook->post_ddr_init)
ddr_hook->post_ddr_init(type);
+ ddr_diag_stage(8);
get_dynamic_calib_value(rate);
if(DDRC_AUTOSR_EN_VALUE) {
@@ -616,6 +642,7 @@ void sdram_init(void)
dump_ddrc_register();
/* DDRC address remap configure*/
+ ddr_diag_stage(9); /* 9 = sdram_init completed (success if no fail id recorded) */
debug("sdram init finished\n");
}
--
2.43.0
@@ -0,0 +1,144 @@
From eb05eaef0f7dac0fb1f166f88d69e1b895eb2e1a Mon Sep 17 00:00:00 2001
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
Date: Mon, 24 Aug 2026 23:46:16 +1000
Subject: [PATCH 4/8] ddr: bound clk.c DDR-clock polls + constrain
dynamic-calib div; board_init_f breadcrumbs
---
arch/mips/cpu/xburst2/ddr_innophy.c | 1 +
arch/mips/cpu/xburst2/x2000/clk.c | 6 +++---
arch/mips/cpu/xburst2/x2000/soc.c | 22 +++++++++++++++++++++
arch/mips/include/asm/arch-x2000/ddr_diag.h | 17 ++++++++++++++++
4 files changed, 43 insertions(+), 3 deletions(-)
create mode 100644 arch/mips/include/asm/arch-x2000/ddr_diag.h
diff --git a/arch/mips/cpu/xburst2/ddr_innophy.c b/arch/mips/cpu/xburst2/ddr_innophy.c
index 91cf6a3..c9b19f8 100755
--- a/arch/mips/cpu/xburst2/ddr_innophy.c
+++ b/arch/mips/cpu/xburst2/ddr_innophy.c
@@ -563,6 +563,7 @@ static void get_dynamic_calib_value(unsigned int rate)
ddr_calibration(&dcv[cur_div], cur_div);
break;
}
+ if(div > 0xf) { ddr_diag_fail(60 /*calib div overflow - bad DDR rate*/, (unsigned int)rate); break; }
dcv[div].rate = drate;
dcv[div].refcnt = get_refcnt_value(div);
ddr_calibration(&dcv[div], div);
diff --git a/arch/mips/cpu/xburst2/x2000/clk.c b/arch/mips/cpu/xburst2/x2000/clk.c
index c700a03..30764b6 100755
--- a/arch/mips/cpu/xburst2/x2000/clk.c
+++ b/arch/mips/cpu/xburst2/x2000/clk.c
@@ -27,6 +27,7 @@
#include <asm/gpio.h>
#include <asm/arch/cpm.h>
#include <asm/arch/clk.h>
+#include <asm/arch/ddr_diag.h>
#include <generated/clk_reg_values.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -68,7 +69,7 @@ void clk_prepare(void)
/*set div max*/
regval |= cgusetting[i].val;
writel(regval, reg);
- while (readl(reg) & (1 << cgusetting[i].busy));
+ DDR_BOUND(!(readl(reg) & (1 << cgusetting[i].busy)), 4 /*cgu init busy*/, readl(reg));
} else {
regval &= ~(1 << cgusetting[i].ce);
writel(regval, reg);
@@ -244,8 +245,7 @@ void clk_set_rate(int clk_id, unsigned long rate)
regval &= ~(3 << cgu->stop | 0xff);
regval |= ((1 << cgu->ce) | cdr);
writel(regval, reg);
- while (readl(reg) & (1 << cgu->busy))
- ;
+ DDR_BOUND(!(readl(reg) & (1 << cgu->busy)), 5 /*DDR clk busy (clk_set_rate)*/, readl(reg));
#ifdef DUMP_CGU_SELECT
printf("%s(0x%x) :0x%x\n",clk_name[clk_id] ,reg, readl(reg));
#endif
diff --git a/arch/mips/cpu/xburst2/x2000/soc.c b/arch/mips/cpu/xburst2/x2000/soc.c
index 54ff3b7..6b96c5b 100755
--- a/arch/mips/cpu/xburst2/x2000/soc.c
+++ b/arch/mips/cpu/xburst2/x2000/soc.c
@@ -67,11 +67,23 @@ extern void ddr_test_refresh(unsigned int start_addr, unsigned int end_addr);
extern void flush_cache_all(void);
+/* DIAG: breadcrumb record @0xb24017c0 (shared with ddr_innophy.c). Set 1 to early-return
+ * before sdram_init to prove the mask-ROM return path works in isolation. */
+#define DIAG_SKIP_SDRAM 0
+#define BIF_CRUMB(s) do { *(volatile unsigned int*)0xb24017c4 = (s); __asm__ __volatile__("sync"); } while(0)
+
void board_init_f(ulong dummy)
{
/* Set global data pointer */
gd = &gdata;
+ /* DIAG: mark that we reached board_init_f (magic + stage 0xF0) */
+ *(volatile unsigned int*)0xb24017c0 = 0xD1A6C0DEu;
+ *(volatile unsigned int*)0xb24017c8 = 0;
+ *(volatile unsigned int*)0xb24017cc = 0;
+ *(volatile unsigned int*)0xb24017d0 = 0;
+ BIF_CRUMB(0xF0);
+
/* Setup global info */
#ifndef CONFIG_BURNER
gd->arch.gi = &ginfo;
@@ -80,6 +92,7 @@ void board_init_f(ulong dummy)
#endif
gpio_init();
+ BIF_CRUMB(0xF1);
*(volatile unsigned int *)0xb0000020 = 0; //clk gate enable.
*(volatile unsigned int *)0xb0000028 = 0; //clk gate enable.
@@ -93,15 +106,24 @@ void board_init_f(ulong dummy)
#endif
debug("Timer init\n");
timer_init();
+ BIF_CRUMB(0xF2);
debug("CLK stop\n");
// clk_prepare();
debug("PLL init\n");
pll_init();
+ BIF_CRUMB(0xF3);
debug("CLK init\n");
clk_init();
+ BIF_CRUMB(0xF4);
+
+#if DIAG_SKIP_SDRAM
+ /* DIAG: return before DDR to test the mask-ROM return path in isolation. */
+ BIF_CRUMB(0xFE);
+ return;
+#endif
debug("SDRAM init\n");
sdram_init();
diff --git a/arch/mips/include/asm/arch-x2000/ddr_diag.h b/arch/mips/include/asm/arch-x2000/ddr_diag.h
new file mode 100644
index 0000000..68654ec
--- /dev/null
+++ b/arch/mips/include/asm/arch-x2000/ddr_diag.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_ARCH_DDR_DIAG_H
+#define _ASM_ARCH_DDR_DIAG_H
+/* Shared DDR bring-up breadcrumb record @0xb24017c0 (TCSM pad below the start.S return
+ * shim scratch at 0x17f0). usbboot uploads it after the SPL returns to the mask ROM.
+ * Layout: [0]=magic [1]=stage [2]=first fail id [3]=status@fail [4]=fail count */
+#define DDR_DIAG ((volatile unsigned int *)0xb24017c0)
+#define DDR_DIAG_MAGIC 0xD1A6C0DEu
+#define ddr_diag_fail_raw(id, status) do { \
+ if(DDR_DIAG[2]==0){ DDR_DIAG[2]=(unsigned int)(id); DDR_DIAG[3]=(unsigned int)(status); } \
+ DDR_DIAG[4]++; __asm__ __volatile__("sync"); \
+ } while(0)
+/* bounded busy-wait: wait for (cond); on ~1e6-iter timeout record (id,statusexpr) and stop. */
+#define DDR_BOUND(cond, id, statusexpr) do { \
+ unsigned int _bt = 1000000u; \
+ while(!(cond)) { if(!--_bt){ ddr_diag_fail_raw((id), (statusexpr)); break; } } \
+ } while(0)
+#endif
--
2.43.0
@@ -0,0 +1,35 @@
From f51bc90392b4c0dc42456d876a37dc05926db445 Mon Sep 17 00:00:00 2001
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
Date: Mon, 24 Aug 2026 23:48:18 +1000
Subject: [PATCH 5/8] ddr: disable verbose DEBUG/DWC_DEBUG printf dumps (slim
SPL, no UART-wait in DDR path)
---
arch/mips/cpu/xburst2/ddr_innophy.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/mips/cpu/xburst2/ddr_innophy.c b/arch/mips/cpu/xburst2/ddr_innophy.c
index c9b19f8..b394dad 100755
--- a/arch/mips/cpu/xburst2/ddr_innophy.c
+++ b/arch/mips/cpu/xburst2/ddr_innophy.c
@@ -21,7 +21,7 @@
* MA 02111-1307 USA
*/
-#define DEBUG
+/* #define DEBUG */ /* off: shrink SPL + remove printf UART-waits from DDR path (breadcrumbs replace it) */
/* #define DEBUG_READ_WRITE */
#include <config.h>
#include <common.h>
@@ -45,7 +45,7 @@
#endif
#include <asm/io.h>
#include <asm/arch/clk.h>
-#define CONFIG_DWC_DEBUG 0
+/* #define CONFIG_DWC_DEBUG 0 */ /* off: use the empty dump_ddr*_register() no-ops (shrinks SPL) */
/* ---- DDR bring-up diagnostics (breadcrumbs to TCSM pad @0xb24017c0, below the
* start.S return-shim scratch at 0x17f0). usbboot uploads this region after the SPL
--
2.43.0
@@ -0,0 +1,49 @@
From 26f15d13ea9b7e92eaf2326909b202799797f440 Mon Sep 17 00:00:00 2001
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
Date: Mon, 24 Aug 2026 23:52:48 +1000
Subject: [PATCH 6/8] ddr: fix PHY PLL divisors 20/5 -> 8/4 for W63AH6NKB
LPDDR3 400MHz (calibration root cause)
---
arch/mips/cpu/xburst2/ddr_innophy.c | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/arch/mips/cpu/xburst2/ddr_innophy.c b/arch/mips/cpu/xburst2/ddr_innophy.c
index b394dad..4c7b921 100755
--- a/arch/mips/cpu/xburst2/ddr_innophy.c
+++ b/arch/mips/cpu/xburst2/ddr_innophy.c
@@ -247,25 +247,22 @@ static void ddrp_pll_init(void)
{
unsigned int val;
+ /* PHY PLL divisors for W63AH6NKB LPDDR3 @400MHz: FBDIV=8, PDIV=4 (from tobunto X2000,
+ * matches the vendor SPL). The tree's stock 20/5 sets the wrong PHY clock -> training
+ * (CALIB_DONE) never converges. */
val = ddr_readl(DDRP_INNOPHY_PLL_FBDIV);
val &= ~(0xff);
- val |= 0x14;
+ val |= 0x8;
ddr_writel(val, DDRP_INNOPHY_PLL_FBDIV);
val = ddr_readl(DDRP_INNOPHY_PLL_PDIV);
val &= ~(0xff);
- val |= 0x5;
+ val |= 4;
ddr_writel(val, DDRP_INNOPHY_PLL_PDIV);
- /* ddr_writel(0x14, DDRP_INNOPHY_PLL_FBDIV); */
- /* ddr_writel(0x5, DDRP_INNOPHY_PLL_PDIV); */
-#ifdef DEBUG_READ_WRITE
+ /* toggle PLLPDEN via RMW (preserve other PLL_CTRL bits), as tobunto/vendor do */
ddr_writel(ddr_readl(DDRP_INNOPHY_PLL_CTRL) | DDRP_PLL_CTRL_PLLPDEN, DDRP_INNOPHY_PLL_CTRL);
ddr_writel(ddr_readl(DDRP_INNOPHY_PLL_CTRL) & ~DDRP_PLL_CTRL_PLLPDEN, DDRP_INNOPHY_PLL_CTRL);
-#else
- ddr_writel(DDRP_PLL_CTRL_PLLPDEN, DDRP_INNOPHY_PLL_CTRL);
- ddr_writel(0, DDRP_INNOPHY_PLL_CTRL);
-#endif
DDR_BOUND(ddr_readl(DDRP_INNOPHY_PLL_LOCK) & (1 << 3), 10 /*PLL_LOCK*/, ddr_readl(DDRP_INNOPHY_PLL_LOCK));
}
--
2.43.0
@@ -0,0 +1,74 @@
From e951f0e6e47ab7b0ffe4df2de1120685a11cd63a Mon Sep 17 00:00:00 2001
From: b0hemia <50309975+b0hemia@users.noreply.github.com>
Date: Tue, 25 Aug 2026 00:02:46 +1000
Subject: [PATCH 7/8] spl: strip board_init_f test scaffolding (keep bounded
polls + sdram diag as hardening)
---
arch/mips/cpu/xburst2/x2000/soc.c | 21 ---------------------
1 file changed, 21 deletions(-)
diff --git a/arch/mips/cpu/xburst2/x2000/soc.c b/arch/mips/cpu/xburst2/x2000/soc.c
index 6b96c5b..ab9e437 100755
--- a/arch/mips/cpu/xburst2/x2000/soc.c
+++ b/arch/mips/cpu/xburst2/x2000/soc.c
@@ -67,23 +67,11 @@ extern void ddr_test_refresh(unsigned int start_addr, unsigned int end_addr);
extern void flush_cache_all(void);
-/* DIAG: breadcrumb record @0xb24017c0 (shared with ddr_innophy.c). Set 1 to early-return
- * before sdram_init to prove the mask-ROM return path works in isolation. */
-#define DIAG_SKIP_SDRAM 0
-#define BIF_CRUMB(s) do { *(volatile unsigned int*)0xb24017c4 = (s); __asm__ __volatile__("sync"); } while(0)
-
void board_init_f(ulong dummy)
{
/* Set global data pointer */
gd = &gdata;
- /* DIAG: mark that we reached board_init_f (magic + stage 0xF0) */
- *(volatile unsigned int*)0xb24017c0 = 0xD1A6C0DEu;
- *(volatile unsigned int*)0xb24017c8 = 0;
- *(volatile unsigned int*)0xb24017cc = 0;
- *(volatile unsigned int*)0xb24017d0 = 0;
- BIF_CRUMB(0xF0);
-
/* Setup global info */
#ifndef CONFIG_BURNER
gd->arch.gi = &ginfo;
@@ -92,7 +80,6 @@ void board_init_f(ulong dummy)
#endif
gpio_init();
- BIF_CRUMB(0xF1);
*(volatile unsigned int *)0xb0000020 = 0; //clk gate enable.
*(volatile unsigned int *)0xb0000028 = 0; //clk gate enable.
@@ -106,24 +93,16 @@ void board_init_f(ulong dummy)
#endif
debug("Timer init\n");
timer_init();
- BIF_CRUMB(0xF2);
debug("CLK stop\n");
// clk_prepare();
debug("PLL init\n");
pll_init();
- BIF_CRUMB(0xF3);
debug("CLK init\n");
clk_init();
- BIF_CRUMB(0xF4);
-#if DIAG_SKIP_SDRAM
- /* DIAG: return before DDR to test the mask-ROM return path in isolation. */
- BIF_CRUMB(0xFE);
- return;
-#endif
debug("SDRAM init\n");
sdram_init();
--
2.43.0

Some files were not shown because too many files have changed in this diff Show More