From 6c9122df16dedb686e94eb33f7bc72af38809467 Mon Sep 17 00:00:00 2001 From: Andrew Page Date: Thu, 24 Jul 2025 20:22:29 +0000 Subject: [PATCH] Docker building Closes #8 Adds validator tool --- .github/workflows/build_and_test.yml | 32 ++++++++-- README.md | 88 +++++++++++++++++----------- docker/.gitignore | 1 + docker/Dockerfile | 17 ++++++ docker/ubuntu.sources | 13 ++++ src/lib.rs | 3 +- src/register_tool.rs | 45 ++++++++------ tools/ucompleter | 2 +- 8 files changed, 142 insertions(+), 59 deletions(-) create mode 100644 docker/.gitignore create mode 100644 docker/Dockerfile create mode 100644 docker/ubuntu.sources diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 48b79e6..397a378 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -23,7 +23,7 @@ # -name: Rust +name: register_tool on: push: @@ -36,12 +36,36 @@ jobs: build: runs-on: ubuntu-latest - + container: rust:latest steps: - uses: actions/checkout@v4 with: - submodules: recursive + submodules: recursive + - run: rustup update + - name: Install cargo-deb + run: cargo install cargo-deb - name: Build run: cargo build --verbose - name: Run tests - run: cargo test --verbose + run: cargo test && cd aep_rust_common && cargo test + - name: rustup aarch64 + run: rustup target add aarch64-unknown-linux-gnu + - name: gcc-arm64 + run: apt-get update && apt-get install -y gcc-aarch64-linux-gnu + - name: aarch64 + run: cargo build --target=aarch64-unknown-linux-gnu + - name: deb aarch64 + run: cargo deb --target=aarch64-unknown-linux-gnu + - name: deb amd64 + run: cargo deb + - uses: actions/upload-artifact@v4 + with: + name: register_tool-arm64 + path: "target/aarch64-unknown-linux-gnu/debian/register_tool*.deb" + overwrite: true + - uses: actions/upload-artifact@v4 + with: + name: register_tool-x86 + path: target/debian/register_tool*.deb + overwrite: true + diff --git a/README.md b/README.md index 13a8ecc..77c74f1 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,6 @@ This is a tool for examining and manipulating memory mapped registers in embedde names instead of raw addresses. The program reads a register configuration file in yaml format which contains register definitions. -# Usage - -```bash -register_tool [options] [=]... -``` - # Building ## aarch64-unknown-linux-gnu @@ -17,14 +11,22 @@ register_tool [options] [=]... Suitable for executing on a raspberrypi OS, or ubuntu ```bash +rustup target add aarch64-unknown-linux-gnu # once +sudo apt-get install -y gcc-aarch64-linux-gnu # once + git clone https://https://github.com/AndrewOfC/register_tool.git --recursive cd register_tool -rustup target add aarch64-unknown-linux-gnu # once +cargo build + cargo build --target aarch64-unknown-linux-gnu ``` +# Usage -# Parameters and options +```bash +register_tool [options] [=]... +``` +## Parameters and options | P/O | meaning | |-----------|---------------------------------------------------------------| @@ -34,6 +36,16 @@ cargo build --target aarch64-unknown-linux-gnu | -f | Override register file(s) that might be in REGISTER_TOOL_PATH | | -t | Test mode. Do not map memory, allocate a block of 'length' | +## Exit Status + +| Status | Meaning | +|--------|--------------------------------------------------------------------------------------------| +| 0 | success | +| 1 | if any operation is illegal(reading a write-only register or writing a read-only register) | +| 2 | if a configuration file cannot be found or an error in reading | + +Paths and values may be specified multiple times. Before any action is taken +the values are checked for legality. # Concepts @@ -43,7 +55,6 @@ A 'path' describes the location of a register in the yaml definition file. The to dereferencing a python or javascript object. A dot(.) will access fields in an associative array or hash block and [] may be used to access individual array members. - ### Example ```yaml @@ -65,34 +76,38 @@ GPIO: bits: 30:30 ``` -__GPIO.pins[0]__ +__GPIO.pins[0].set__ -will access the pin 0 +will access the pin 0 set register ## Bits Bits are specified by "hibit:lobit" (inclusive). This allows you to set/clear bits individually in a -regsiter without changing the other bits in he register. Example to set pin 1 in the above exmple +regsiter without changing the other bits in the register. Example to set pin 1 in the above exmple this command would be used: ```bash register_tool GPIO.pins[0].set=1 ``` -Inside register tool, the current +Inside register tool, the current value is read from the register(for rw registers) +or the shadow register(for wo registers) and the value is only appled to the +bits in question before being written. + +Attempting to read a write-only register that has no shadow produces an error # Environment Variables: -| Var | Effect | -|-----|----------------------------------------------------------------------| -| REGISTER_TOOL_PATH | colon separated list of directories to search for register_tool.yaml | +| Var | Effect | +|----------------------------|----------------------------------------------------------------------| +| REGISTER_TOOL_PATH | colon separated list of directories to search for register_tool.yaml | # How To ## Define a device -The root of your yaml configuration file should contain the following fields +The root of your YAML configuration file should contain the following fields ```yaml base: 0x7E200000 @@ -148,26 +163,17 @@ registers: This is information that the [ucompleter](https://github.com/AndrewOfC/ucompleter) tool will use to provide completions of your registers on the bash command line. It is not required, but it is recommended. -| Field | Purpose | -|-----------------|----------------------------------------------------------------------------------------------| -| root | Path to the element where register definitions are to be found | -| terminal-fields | If any of these fields are present in a hash as the tree is descended the descent is stopped | +| Field | Purpose | +|-----------------|-----------------------------------------------------------------------------------------------| +| root | Path to the element where register definitions are to be found | +| terminal-fields | If any of these fields are present in a hash as the tree is descended the descent is stopped | # Example Files -| File | Contents | -|---------------------------------------------------|------------------------------------------| +| File | Contents | +|-----------------------------------------------------------------|------------------------------------------| | [raspberrypi4b_source.yaml](examples/raspberrypi4b_source.yaml) | Register definitions for RaspberryPi 4b This file was constructed with data from: [bcm2711-peripherals.pdf](https://datasheets.raspberrypi.com/bcm2711/bcm2711-peripherals.pdf)| -| [raspberrypi4b.yaml](examples/raspberrypi4b.yaml) | The raspberrypi4b_source.yaml file remapped for a 'per pin' perspective. | - -# Companion tools - -The ucompleter tool can be configured with bash to provide register completions. -Once enabled pressing TAB-TAB after register_tool will provide you with the available completions - -```bash -complete -o bashdefault -o default -o nospace -C ucompleter register_tool -``` +| [raspberrypi4b.yaml](examples/raspberrypi4b.yaml) | The raspberrypi4b_source.yaml file remapped for a 'per pin' perspective. | # Example @@ -188,3 +194,19 @@ register_tool GPIO.pins[27].clear=1 # sets pin 27 lo | src | Rust source code | | target | cargo output directory | | [tools](tools) | Optional tools that can assist with use | + + +# Companion tools + +## tools/ucompleter +The ucompleter tool can be configured with bash to provide register completions. +Once enabled pressing TAB-TAB after register_tool will provide you with the available completions + +```bash +complete -o bashdefault -o default -o nospace -C ucompleter register_tool +``` + +## tools/register_config_validator.py + +Python script to validate configuration files. Gathers all potential errors +before exitting. diff --git a/docker/.gitignore b/docker/.gitignore new file mode 100644 index 0000000..934178f --- /dev/null +++ b/docker/.gitignore @@ -0,0 +1 @@ +/sudoer.andrew diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..570530c --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,17 @@ +# WIP +FROM ubuntu:latest +RUN apt-get update && apt-get upgrade -y +RUN apt-get install -y build-essential git sudo file rustup +RUN rustup default stable +RUN cargo install cargo-deb +RUN dpkg --add-architecture arm64 +COPY ubuntu.sources /etc/apt/sources.list.d/ +RUN apt-get update +RUN apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc6-dev:arm64 +RUN rustup target add aarch64-unknown-linux-gnu + +COPY sudoer.user* /etc/sudoers.d/$USER +RUN chown root /etc/sudoers.d/$USER +RUN deluser ubuntu +RUN useradd andrew -u 1000 -G sudo +RUN echo andrew:password | chpasswd diff --git a/docker/ubuntu.sources b/docker/ubuntu.sources new file mode 100644 index 0000000..24220f4 --- /dev/null +++ b/docker/ubuntu.sources @@ -0,0 +1,13 @@ +Types: deb +URIs: http://archive.ubuntu.com/ubuntu/ +Suites: noble noble-updates noble-backports noble-security +Components: main universe restricted multiverse +Architectures: amd64 i386 +Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg + +Types: deb +URIs: http://ports.ubuntu.com/ubuntu-ports/ +Suites: noble noble-updates noble-backports noble-security +Components: main universe restricted multiverse +Architectures: arm64 +Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg diff --git a/src/lib.rs b/src/lib.rs index 0f45a04..7cabb4b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,5 +24,4 @@ mod unittests; pub mod unsafes; pub mod register_tool; -pub mod register_op; -mod register_tool_dump; +pub mod register_op; \ No newline at end of file diff --git a/src/register_tool.rs b/src/register_tool.rs index e1493e9..8755382 100644 --- a/src/register_tool.rs +++ b/src/register_tool.rs @@ -1,18 +1,21 @@ -// +use crate::register_op::RegisterOp; +use crate::unsafes::mmap_memory; +use aep_rust_common::descender::Descender; +// // SPDX-License-Identifier: MIT -// +// // Copyright (c) 2025 Andrew Ellis Page -// +// // 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 @@ -20,16 +23,8 @@ // 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. -// +// use std::io::Write; -use clap::parser::ValuesRef; -use libc::fanotify_init; -use regex::Regex; -use yaml_rust::Yaml; -use aep_rust_common::descender; -use aep_rust_common::descender::Descender; -use crate::register_op::RegisterOp; -use crate::unsafes::mmap_memory; pub struct RegisterTool { descender: Box>, @@ -61,7 +56,7 @@ impl RegisterTool { match offset { Ok(o) => println!(" offset: 0x{o:04X}"), Err(e) => { - println!(" offset: NOT FOUND") ; + println!(" {e} offset: NOT FOUND") ; fail = true ; bad_regs.push(path) ; } @@ -71,7 +66,13 @@ impl RegisterTool { println!(" bits: {}", bits) ; println!(" description: \"{}\"", desc) ; } - self.descender.set_root(&*old_root) ; + match self.descender.set_root(&*old_root) { + Ok(_) => {}, + Err(e) => { + println!("Error resetting root: {}", e); + fail = true; + } + } if fail { let bad_reg_list = bad_regs.join(" "); Err(format!("invalid registers: {}", bad_reg_list)) @@ -115,8 +116,8 @@ impl RegisterTool { if parts.len() > 2 { return Err(format!("Bad argument {}", spec)); } - let isSet = parts.len() == 2 ; - let value = if isSet { + let is_set = parts.len() == 2 ; + let value = if is_set { match parts[1].parse::() { Ok(v) => Some(v), Err(_) => return Err(format!("Bad argument {}", spec)), @@ -130,7 +131,13 @@ impl RegisterTool { self.regs.push(r) } - self.descender.set_root(&*old_root) ; + match self.descender.set_root(&*old_root) { + Ok(_) => {}, + Err(e) => { + println!("Error resetting root: {}", e); + return Err(format!("Error resetting root: {}", e)); + } + } Ok(()) } diff --git a/tools/ucompleter b/tools/ucompleter index 5b8d415..deebbfd 160000 --- a/tools/ucompleter +++ b/tools/ucompleter @@ -1 +1 @@ -Subproject commit 5b8d4154e2066ff65df48da246330fb2610c0029 +Subproject commit deebbfd356a7aeb3a5fbf29bf65103b0c9b35b53