diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 75312b9..b1cdc86 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -8,6 +8,7 @@ on: name: Rust jobs: + # TODO switch to beta and then to stable check: name: Check firmware runs-on: ubuntu-latest @@ -18,32 +19,14 @@ jobs: - name: Install nightly toolchain uses: actions-rs/toolchain@v1 with: - components: rust-src # needed by cargo-xbuild + target: armv7a-none-eabi toolchain: nightly override: true - - name: Cache cargo installs - id: cache-cargo-bin - uses: actions/cache@v1 - with: - path: ~/.cargo/bin - key: ${{ runner.os }}-cargo-bin-${{ hashFiles('dev-dependencies.txt') }} - - - name: Install dev-dependencies - # NOTE we need this check because the cache action won't restore `.cargo/.{crates2.json,.crates.toml}` - if: steps.cache-cargo-bin.outputs.cache-hit != 'true' - # FIXME `cache-hit` is not being set when the cache is found - # (is it because there's a permission error when un-tar-ing it?) - run: | - which cargo-audit || cargo install `cat dev-dependencies.txt` - - - name: Set environment for cargo-xbuild - run: echo ::set-env name=RUST_TARGET_PATH::$(echo ${GITHUB_WORKSPACE}/firmware ) - - - name: Run cargo xcheck + - name: Run cargo check working-directory: ./firmware run: | - cargo xcheck + cargo check # NOTE the `common` directory is currently empty so this is a no-op # host-test: @@ -110,35 +93,25 @@ jobs: # - name: Install nightly toolchain # uses: actions-rs/toolchain@v1 # with: -# components: rust-src # needed by cargo-xbuild +# target: armv7a-none-eabi # toolchain: nightly # override: true -# - name: Cache cargo installs -# id: cache-cargo-bin -# uses: actions/cache@v1 -# with: -# path: ~/.cargo/bin -# key: ${{ runner.os }}-cargo-bin-${{ hashFiles('dev-dependencies.txt') }} - # - name: Install QEMU # run: | # sudo apt update # sudo apt install qemu-system-arm -# - name: Install dev-dependencies -# if: steps.cache-cargo-bin.outputs.cache-hit != 'true' +# - name: Install flip-lld # run: | -# cargo install `cat dev-dependencies.txt` - -# - name: Set environment for cargo-xbuild -# run: echo ::set-env name=RUST_TARGET_PATH::$(echo ${GITHUB_WORKSPACE}/firmware ) +# cargo install --git https://github.com/japaric/flip-lld # - name: Run examples # working-directory: ./firmware/usbarmory # run: | -# cargo xrun --example qemu-hello --release +# cargo run --example qemu-hello --release + # TODO switch to beta and then to stable # test that all our examples link it_links: name: Check that all examples link in dev and release mode @@ -150,39 +123,36 @@ jobs: - name: Install nightly toolchain uses: actions-rs/toolchain@v1 with: - components: rust-src # needed by cargo-xbuild + target: armv7a-none-eabi toolchain: nightly override: true - - name: Cache cargo installs - id: cache-cargo-bin - uses: actions/cache@v1 - with: - path: ~/.cargo/bin - key: ${{ runner.os }}-cargo-bin-${{ hashFiles('dev-dependencies.txt') }} + # - name: Cache cargo installs + # id: cache-cargo-bin + # uses: actions/cache@v1 + # with: + # path: ~/.cargo/bin + # key: ${{ runner.os }}-cargo-bin-${{ hashFiles('dev-dependencies.txt') }} - - name: Install dev-dependencies - if: steps.cache-cargo-bin.outputs.cache-hit != 'true' - run: | - which cargo-audit || cargo install `cat dev-dependencies.txt` + # - name: Install dev-dependencies + # if: steps.cache-cargo-bin.outputs.cache-hit != 'true' + # run: | + # which flip-lld || cargo install `cat dev-dependencies.txt` # TODO cache in dev-dependencies.txt when available on crates.io - name: Install flip-lld run: | cargo install --git https://github.com/japaric/flip-lld - - name: Set environment for cargo-xbuild - run: echo ::set-env name=RUST_TARGET_PATH::$(echo ${GITHUB_WORKSPACE}/firmware ) - - name: Build examples using the dev profile working-directory: ./firmware/usbarmory run: | - cargo xbuild --examples + cargo build --examples - name: Build examples using the release profile working-directory: ./firmware/usbarmory run: | - cargo xbuild --examples --release + cargo build --examples --release fmt: name: Rustfmt @@ -205,6 +175,7 @@ jobs: run: | cargo fmt --all -- --check + # TODO switch to beta and then to stable clippy: name: Clippy runs-on: ubuntu-latest @@ -212,32 +183,17 @@ jobs: - name: Checkout sources uses: actions/checkout@v2 - - name: Install stable toolchain + - name: Install nightly toolchain uses: actions-rs/toolchain@v1 with: - components: rust-src # needed by cargo-xbuild + target: armv7a-none-eabi toolchain: nightly override: true - - name: Cache cargo installs - id: cache-cargo-bin - uses: actions/cache@v1 - with: - path: ~/.cargo/bin - key: ${{ runner.os }}-cargo-bin-${{ hashFiles('dev-dependencies.txt') }} - - - name: Install dev-dependencies - if: steps.cache-cargo-bin.outputs.cache-hit != 'true' - run: | - which cargo-audit || cargo install `cat dev-dependencies.txt` - - name: Install clippy run: rustup component add clippy - - name: Set environment for cargo-xbuild - run: echo ::set-env name=RUST_TARGET_PATH::$(echo ${GITHUB_WORKSPACE}/firmware ) - - name: Run cargo clippy working-directory: ./firmware run: | - cargo xclippy -- -D warnings + cargo clippy -- -D warnings diff --git a/dev-dependencies.txt b/dev-dependencies.txt index a8db6cb..79421e6 100644 --- a/dev-dependencies.txt +++ b/dev-dependencies.txt @@ -1 +1 @@ -cargo-audit cargo-xbuild \ No newline at end of file +cargo-audit diff --git a/firmware/.cargo/config b/firmware/.cargo/config index aac0f17..b0d875c 100644 --- a/firmware/.cargo/config +++ b/firmware/.cargo/config @@ -1,3 +1,3 @@ [build] -target = "armv7-none-eabi" # soft float ABI, emulated float operations -# target = "armv7-none-eabihf" # hard float ABI, float operations on hardware \ No newline at end of file +target = "armv7a-none-eabi" # soft float ABI, emulated float operations +# target = "armv7a-none-eabihf" # hard float ABI, float operations on hardware \ No newline at end of file diff --git a/firmware/Cargo.lock b/firmware/Cargo.lock index 7a1b618..9cd9106 100644 --- a/firmware/Cargo.lock +++ b/firmware/Cargo.lock @@ -81,7 +81,7 @@ dependencies = [ [[package]] name = "cortex-m-semihosting" version = "0.3.5" -source = "git+https://github.com/japaric/cortex-m-semihosting?branch=cortex-a#c68cad0d3705e218d33f9918f789d463ca80e29d" +source = "git+https://github.com/japaric/cortex-m-semihosting?branch=cortex-a#585e741cef93a0a1376326ea864f4b17ea9ad429" dependencies = [ "cortex-m", ] @@ -123,9 +123,9 @@ dependencies = [ [[package]] name = "heapless" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f6c9395cad684c09e7172ac2b333b838f4099d0545ffd89ba7a89d10dfd605" +checksum = "10b591a0032f114b7a77d4fbfab452660c553055515b7d7ece355db080d19087" dependencies = [ "as-slice", "generic-array 0.13.2", diff --git a/firmware/README.md b/firmware/README.md index 6489df1..1a8e61c 100644 --- a/firmware/README.md +++ b/firmware/README.md @@ -4,14 +4,11 @@ Cortex-A7. There are two compilation targets (see `--target` in `rustc -h`) for this embedded target: -- armv7-none-eabihf, hard float ABI; float operations are performed on the +- armv7a-none-eabihf, hard float ABI; float operations are performed on the hardware FPU. NOTE: currently untested -- armv7-none-eabi, soft float ABI; float operations are emulated +- armv7a-none-eabi, soft float ABI; float operations are emulated The default compilation target for the whole directory is currently set to the most compatible soft float target. If you need to use the hard float target -modify `.cargo/config`, or pass `--target armv7-none-eabihf` to Xargo. - -*NOTE* all the code under this directory needs Rust nightly and Xargo. See the -README in the [`usbarmory`](usbarmory) directory for more information. +modify `.cargo/config`, or pass `--target armv7a-none-eabihf` to Cargo. diff --git a/firmware/armv7-none-eabi.json b/firmware/armv7-none-eabi.json deleted file mode 100644 index c4e4018..0000000 --- a/firmware/armv7-none-eabi.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "abi-blacklist": [ - "stdcall", - "fastcall", - "vectorcall", - "thiscall", - "win64", - "sysv64" - ], - "arch": "arm", - "data-layout": "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", - "emit-debug-gdb-scripts": false, - "env": "", - "executables": true, - "features": "+v7,+thumb2,+soft-float,+strict-align,-neon", - "linker": "rust-lld", - "linker-flavor": "ld.lld", - "llvm-target": "armv7a-none-eabi", - "max-atomic-width": 64, - "os": "none", - "panic-strategy": "abort", - "relocation-model": "static", - "target-c-int-width": "32", - "target-endian": "little", - "target-pointer-width": "32", - "vendor": "" -} diff --git a/firmware/armv7-none-eabihf.json b/firmware/armv7-none-eabihf.json deleted file mode 100644 index fbd0348..0000000 --- a/firmware/armv7-none-eabihf.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "abi-blacklist": [ - "stdcall", - "fastcall", - "vectorcall", - "thiscall", - "win64", - "sysv64" - ], - "arch": "arm", - "data-layout": "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", - "emit-debug-gdb-scripts": false, - "env": "", - "executables": true, - "features": "+v7,+vfp3,-d32,+thumb2,+strict-align,-neon", - "linker": "rust-lld", - "linker-flavor": "ld.lld", - "llvm-target": "armv7a-none-eabihf", - "max-atomic-width": 64, - "os": "none", - "panic-strategy": "abort", - "relocation-model": "static", - "target-c-int-width": "32", - "target-endian": "little", - "target-pointer-width": "32", - "vendor": "" -} diff --git a/firmware/cortex-a/asm.s b/firmware/cortex-a/asm.s index db06314..cd8638a 100644 --- a/firmware/cortex-a/asm.s +++ b/firmware/cortex-a/asm.s @@ -72,3 +72,8 @@ __isb: __wfi: wfi bx lr + + .global __udf + .section .text.__udf +__udf: + udf diff --git a/firmware/cortex-a/assemble.sh b/firmware/cortex-a/assemble.sh index 2c42709..da1272b 100755 --- a/firmware/cortex-a/assemble.sh +++ b/firmware/cortex-a/assemble.sh @@ -7,11 +7,11 @@ main() { # NOTE: cflags taken from cc 1.0.49 / armv7-unknown-linux-gnueabi arm-none-eabi-as -march=armv7-a asm.s -o bin/$pkg_name.o - ar crs bin/armv7-none-eabi.a bin/$pkg_name.o + ar crs bin/armv7a-none-eabi.a bin/$pkg_name.o # cc uses the same flags for the gnueabihf variant arm-none-eabi-as -march=armv7-a+vfpv3 asm.s -o bin/$pkg_name.o - ar crs bin/armv7-none-eabihf.a bin/$pkg_name.o + ar crs bin/armv7a-none-eabihf.a bin/$pkg_name.o rm bin/*.o } diff --git a/firmware/cortex-a/bin/armv7-none-eabi.a b/firmware/cortex-a/bin/armv7-none-eabi.a deleted file mode 100644 index 8a02a98..0000000 Binary files a/firmware/cortex-a/bin/armv7-none-eabi.a and /dev/null differ diff --git a/firmware/cortex-a/bin/armv7-none-eabihf.a b/firmware/cortex-a/bin/armv7-none-eabihf.a deleted file mode 100644 index 405d5a4..0000000 Binary files a/firmware/cortex-a/bin/armv7-none-eabihf.a and /dev/null differ diff --git a/firmware/cortex-a/bin/armv7a-none-eabi.a b/firmware/cortex-a/bin/armv7a-none-eabi.a new file mode 100644 index 0000000..be1fb31 Binary files /dev/null and b/firmware/cortex-a/bin/armv7a-none-eabi.a differ diff --git a/firmware/cortex-a/bin/armv7a-none-eabihf.a b/firmware/cortex-a/bin/armv7a-none-eabihf.a new file mode 100644 index 0000000..9190412 Binary files /dev/null and b/firmware/cortex-a/bin/armv7a-none-eabihf.a differ diff --git a/firmware/cortex-a/src/lib.rs b/firmware/cortex-a/src/lib.rs index d1ad054..38f1bfe 100644 --- a/firmware/cortex-a/src/lib.rs +++ b/firmware/cortex-a/src/lib.rs @@ -1,7 +1,5 @@ //! Low level access to Cortex-A processors -// FIXME replace inline assembly with external assembly -#![feature(asm)] #![no_std] #![warn(missing_docs, rust_2018_idioms, unused_qualifications)] @@ -110,3 +108,14 @@ pub fn wfi() { unsafe { __wfi() } } + +/// UnDeFined instruction +/// +/// Calling this will result in a `UndefinedInstrution` exception +pub fn udf() -> ! { + extern "C" { + fn __udf() -> !; + } + + unsafe { __udf() } +} diff --git a/firmware/cortex-a/src/register/cpsr.rs b/firmware/cortex-a/src/register/cpsr.rs index 7c28b38..da463db 100644 --- a/firmware/cortex-a/src/register/cpsr.rs +++ b/firmware/cortex-a/src/register/cpsr.rs @@ -1,6 +1,7 @@ //! Current Program Status Register /// Reads the CPSR register +#[cfg(TODO = "external-assembly")] pub fn read() -> u32 { let cpsr: u32; unsafe { asm!("mrs $0, cpsr" : "=r"(cpsr)) } diff --git a/firmware/cortex-a/src/register/scr.rs b/firmware/cortex-a/src/register/scr.rs index aecedb8..0f5ee18 100644 --- a/firmware/cortex-a/src/register/scr.rs +++ b/firmware/cortex-a/src/register/scr.rs @@ -1,6 +1,7 @@ //! Security Control Register /// Reads the SCR register +#[cfg(TODO = "external-assembly")] pub fn read() -> u16 { let scr; unsafe { asm!("mrc p15, 0, $0, c1, c1, 0" : "=r"(scr)) } diff --git a/firmware/cortex-a/src/register/sctlr.rs b/firmware/cortex-a/src/register/sctlr.rs index 27a2449..f070ab4 100644 --- a/firmware/cortex-a/src/register/sctlr.rs +++ b/firmware/cortex-a/src/register/sctlr.rs @@ -1,6 +1,7 @@ //! System Control Register /// Reads the SCTLR register +#[cfg(TODO = "external-assembly")] pub fn read() -> u32 { let sctlr; unsafe { asm!("mrc p15, 0, $0, c1, c1, 0" : "=r"(sctlr)) } diff --git a/firmware/usbarmory-rt/assemble.sh b/firmware/usbarmory-rt/assemble.sh index e6053b3..f47d1aa 100755 --- a/firmware/usbarmory-rt/assemble.sh +++ b/firmware/usbarmory-rt/assemble.sh @@ -8,11 +8,11 @@ main() { # NOTE: cflags taken from cc 1.0.49 / armv7-unknown-linux-gnueabi arm-none-eabi-as -march=armv7-a asm-common.s -o bin/$crate-common.o arm-none-eabi-as -march=armv7-a asm-no-vfp.s -o bin/$crate-no-vfp.o - ar crs bin/armv7-none-eabi.a bin/$crate-{common,no-vfp}.o + ar crs bin/armv7a-none-eabi.a bin/$crate-{common,no-vfp}.o arm-none-eabi-as -march=armv7-a+vfpv3 asm-common.s -o bin/$crate-common.o arm-none-eabi-as -march=armv7-a+vfpv3 asm-vfp.s -o bin/$crate-vfp.o - ar crs bin/armv7-none-eabihf.a bin/$crate-{common,vfp}.o + ar crs bin/armv7a-none-eabihf.a bin/$crate-{common,vfp}.o rm bin/*.o } diff --git a/firmware/usbarmory-rt/bin/armv7-none-eabi.a b/firmware/usbarmory-rt/bin/armv7a-none-eabi.a similarity index 100% rename from firmware/usbarmory-rt/bin/armv7-none-eabi.a rename to firmware/usbarmory-rt/bin/armv7a-none-eabi.a diff --git a/firmware/usbarmory-rt/bin/armv7-none-eabihf.a b/firmware/usbarmory-rt/bin/armv7a-none-eabihf.a similarity index 100% rename from firmware/usbarmory-rt/bin/armv7-none-eabihf.a rename to firmware/usbarmory-rt/bin/armv7a-none-eabihf.a diff --git a/firmware/usbarmory/.cargo/config b/firmware/usbarmory/.cargo/config index a323b12..da13a89 100644 --- a/firmware/usbarmory/.cargo/config +++ b/firmware/usbarmory/.cargo/config @@ -1,15 +1,15 @@ -[target.armv7-none-eabi] +[target.armv7a-none-eabi] runner = "qemu-system-arm -cpu cortex-a7 -machine mcimx6ul-evk -nographic -semihosting-config enable=on,target=native -kernel" rustflags = [ "-C", "linker=flip-lld", "-C", "link-arg=-Tlink.x", ] -[target.armv7-none-eabihf] +[target.armv7a-none-eabihf] rustflags = [ "-C", "linker=flip-lld", "-C", "link-arg=-Tlink.x", ] [build] -target = "armv7-none-eabi" \ No newline at end of file +target = "armv7a-none-eabi" \ No newline at end of file diff --git a/firmware/usbarmory/Cargo.toml b/firmware/usbarmory/Cargo.toml index 61231fe..3bf1145 100644 --- a/firmware/usbarmory/Cargo.toml +++ b/firmware/usbarmory/Cargo.toml @@ -20,5 +20,5 @@ usbarmory-rt = { path = "../usbarmory-rt" } cortex-a-rtfm = { path = "../cortex-a-rtfm" } cortex-m-semihosting = { git = "https://github.com/japaric/cortex-m-semihosting", branch = "cortex-a" } exception-reset = { path = "../exception-reset" } -heapless = "0.5.2" +heapless = "0.5.3" panic-serial = { path = "../panic-serial" } diff --git a/firmware/usbarmory/README.md b/firmware/usbarmory/README.md index 9f82e48..9c61e1d 100644 --- a/firmware/usbarmory/README.md +++ b/firmware/usbarmory/README.md @@ -14,7 +14,7 @@ from [F-Secure]. ## Minimum Supported Rust Version -- Rust **1.42** +- Rust **1.42** / `nightly-2020-01-24` or newer ## Status @@ -23,14 +23,16 @@ stage and will not be ready to use for some time. ## Building dependencies -- [Xargo](https://crates.io/crates/xargo), for the time being. `cargo install -xargo` (run this command *outside* the `firmware` directory) - - [flip-lld], linker wrapper that adds zero-cost stack overflow protection. `cargo install --git https://github.com/japaric/flip-lld`. ## Development dependencies +- `arm-none-eabi-binutils` OR (`cargo-binutils` + `llvm-tools-preview`), if you + need to inspect ELF files. `pacman -S arm-none-eabi-binutils` for the former; + `cargo install cargo-binutils` (run it outside the `firmware` directory) and + `rustup component add llvm-tools-preview` for the latter. + - `arm-none-eabi-gcc`, only required if modifying assembly (`.s`) files - `qemu-system-arm` v4.x, to run firmware on the host and for some unit testing. @@ -38,19 +40,11 @@ xargo` (run this command *outside* the `firmware` directory) ## Building examples -As the `armv7-none-eabi` target is not in `rustc` / `rustup` you'll have to use -Rust nightly and Xargo for now. - ``` rust -$ # run this command from this directory -$ export RUST_TARGET_PATH=$(dirname `pwd`) - -$ xargo build --example $example_name +$ # on this directory +$ cargo build --example $example_name ``` -*NOTE* You'll need to set the `RUST_TARGET_PATH` variable to use *any* Xargo -command that involves building, including `xargo run`. - ## Running on QEMU The examples whose name is prefixed with `qemu-` are meant to be run on QEMU and @@ -68,13 +62,13 @@ $ qemu-system-arm \ -machine mcimx6ul-evk \ -nographic \ -semihosting-config enable=on,target=native \ - -kernel ../target/armv7-none-eabi/release/examples/qemu-hello + -kernel ../target/armv7a-none-eabi/release/examples/qemu-hello ``` Or simply run: ``` rust -$ xargo run --example qemu-hello +$ cargo run --example qemu-hello ``` If a example doesn't explicitly terminate itself, press `C-a` + `c` to bring up @@ -99,7 +93,37 @@ that makes up the program (that is machine code, strings, initial values for static variables, etc.) and *metadata* to indicates where this data should be loaded when the programs starts executing. -> TODO binutils +Because of metadata the size of ELF files on disk does not accurately reflect +the size of the program once it's loaded in memory. To see the real size of the +program you need to run the `size` program on the ELF file. + +``` rust +$ cargo build --example hello --release + +$ stat --printf="%s\n" ../target/armv7a-none-eabi/release/examples/hello +40104 + +$ # if you installed `arm-none-eabi-binutils` +$ arm-none-eabi-size -Ax ../target/armv7a-none-eabi/release/examples/hello +../target/armv7a-none-eabi/release/examples/hello : +section size addr +.text 0x564 0x91f820 +.rodata 0x27b 0x91fd84 +.data 0x0 0x91ffff +.bss 0x1 0x91ffff + +$ # if you installed `cargo-binutils` +$ cargo size --release --example hello -- -A +hello : +section size addr +.text 1380 0x91f820 +.rodata 635 0x91fd84 +.data 0 0x91ffff +.bss 1 0x91ffff +``` + +The ELF file is 40 KB on disk but only uses around 2 KB of memory when loaded +in RAM. ### One time setup @@ -358,8 +382,6 @@ set window 5 ### Loading an ELF image -> TODO - Once you are done configuring u-boot on the target and C-Kermit on the host use the following procedure to load ELF images: @@ -417,7 +439,7 @@ Type ? or HELP for help. Then tell C-Kermit where to find the ELF image using the `send` command: ``` console -(/tmp) C-Kermit> send /a/b/usbarmory.rs/firmware/target/armv7-none-eabi/release/examples/leds +(/tmp) C-Kermit> send /a/b/usbarmory.rs/firmware/target/armv7a-none-eabi/release/examples/leds ``` You'll briefly see a progress bar and then return to the C-Kermit console. Now diff --git a/firmware/usbarmory/examples/abort.rs b/firmware/usbarmory/examples/abort.rs index 1ae8b9d..04f58c5 100644 --- a/firmware/usbarmory/examples/abort.rs +++ b/firmware/usbarmory/examples/abort.rs @@ -1,7 +1,6 @@ // Generates an undefined instruction exception to test that overriding // exception handlers work -#![feature(core_intrinsics)] #![no_main] #![no_std] @@ -16,10 +15,7 @@ use usbarmory::println; fn main() -> ! { // this operation will trigger the `UndefinedInstruction` handler defined // below - unsafe { - // this lowers to the UDF (undefined) instruction - core::intrinsics::abort(); - } + cortex_a::udf() } #[allow(non_snake_case)] diff --git a/firmware/usbarmory/examples/fpu.rs b/firmware/usbarmory/examples/fpu.rs index ec898ae..1f2e80b 100644 --- a/firmware/usbarmory/examples/fpu.rs +++ b/firmware/usbarmory/examples/fpu.rs @@ -1,7 +1,7 @@ //! Test the FPU //! -//! NOTE you must use the `armv7-none-eabihf` target to use the hardware FPU; -//! the other target, `armv7-none-eabihf`, will perform floating point +//! NOTE you must use the `armv7a-none-eabihf` target to use the hardware FPU; +//! the other target, `armv7a-none-eabihf`, will perform floating point //! operations in software #![no_main]