Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#


name: Rust
name: register_tool

on:
push:
Expand All @@ -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

88 changes: 55 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,29 @@ 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] <path>[=<value>]...
```

# Building

## aarch64-unknown-linux-gnu

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] <path>[=<value>]...
```
## Parameters and options

| P/O | meaning |
|-----------|---------------------------------------------------------------|
Expand All @@ -34,6 +36,16 @@ cargo build --target aarch64-unknown-linux-gnu
| -f <file> | 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

Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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.
1 change: 1 addition & 0 deletions docker/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/sudoer.andrew
17 changes: 17 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -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
13 changes: 13 additions & 0 deletions docker/ubuntu.sources
Original file line number Diff line number Diff line change
@@ -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
3 changes: 1 addition & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
45 changes: 26 additions & 19 deletions src/register_tool.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,30 @@
//
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
// 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.
//
//
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<dyn Descender<dyn Write>>,
Expand Down Expand Up @@ -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) ;
}
Expand All @@ -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))
Expand Down Expand Up @@ -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::<u32>() {
Ok(v) => Some(v),
Err(_) => return Err(format!("Bad argument {}", spec)),
Expand All @@ -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(())
}

Expand Down
Loading