Add the libtock_runtime crate and platform switching.
diff --git a/Cargo.toml b/Cargo.toml index 99543d9..89185d4 100644 --- a/Cargo.toml +++ b/Cargo.toml
@@ -83,6 +83,7 @@ "codegen", "core", "core/platform", + "core/runtime", "test_runner", "tools/print_sizes", ]
diff --git a/core/runtime/Cargo.toml b/core/runtime/Cargo.toml new file mode 100644 index 0000000..8da4f70 --- /dev/null +++ b/core/runtime/Cargo.toml
@@ -0,0 +1,19 @@ +[package] +authors = ["Tock Project Developers <tock-dev@googlegroups.com>"] +categories = ["embedded", "no-std", "os"] +description = """libtock-rs runtime. Provides raw system call implementations \ + and language items necessary for Tock apps.""" +edition = "2018" +license = "Apache-2.0 OR MIT" +name = "libtock_runtime" +repository = "https://www.github.com/tock/libtock-rs" +version = "0.1.0" + +[dependencies] +libtock_platform = { path = "../platform" } + +[features] +# By default, libtock_runtime looks for the LIBTOCK_PLATFORM variable to decide +# what layout file to use. If you are providing your own linker script, set +# no_auto_layout to disable the layout file logic. +no_auto_layout = []
diff --git a/core/runtime/build.rs b/core/runtime/build.rs new file mode 100644 index 0000000..e8794f3 --- /dev/null +++ b/core/runtime/build.rs
@@ -0,0 +1,57 @@ +use std::fs::copy; +use std::path::PathBuf; + +// auto_layout() identifies the correct linker scripts to use based on the +// LIBTOCK_PLATFORM environment variable, and copies the linker scripts into +// OUT_DIR. The cargo invocation must pass -C link-arg=-Tlayout.ld to rustc +// (using the rustflags cargo config). +#[cfg(not(feature = "no_auto_layout"))] +fn auto_layout(out_dir: &str) { + const PLATFORM_CFG_VAR: &str = "LIBTOCK_PLATFORM"; + const LAYOUT_GENERIC_FILENAME: &str = "layout_generic.ld"; + + // Note: we need to print these rerun-if commands before using the variable + // or file, so that if the build script fails cargo knows when to re-run it. + println!("cargo:rerun-if-env-changed={}", PLATFORM_CFG_VAR); + + // Read configuration from environment variables. + + // Read the platform environment variable as a String (our platform names + // should all be valid UTF-8). + let platform = + std::env::var(PLATFORM_CFG_VAR).expect("Please specify LIBTOCK_PLATFORM"); + + // Copy the platform-specific layout file into OUT_DIR. + let platform_filename = format!("{}.ld", platform); + let platform_path: PathBuf = ["layouts", &platform_filename].iter().collect(); + println!("cargo:rerun-if-changed={}", platform_path.display()); + if !platform_path.exists() { + panic!("Unknown platform {}", platform); + } + let out_platform_path: PathBuf = [out_dir, "layout.ld"].iter().collect(); + copy(&platform_path, out_platform_path).expect("Unable to copy platform layout into OUT_DIR"); + + // Copy the generic layout file into OUT_DIR. + let out_layout_generic: PathBuf = [out_dir, LAYOUT_GENERIC_FILENAME].iter().collect(); + println!("cargo:rerun-if-changed={}", LAYOUT_GENERIC_FILENAME); + copy(LAYOUT_GENERIC_FILENAME, out_layout_generic) + .expect("Unable to copy layout_generic.ld into OUT_DIR"); +} + +fn main() { + // Note: cargo fails if run in a path that is not valid Unicode, so this + // script doesn't need to handle non-Unicode paths. Also, OUT_DIR cannot be + // in a location with a newline in it, or we have no way to pass + // rustc-link-search to cargo. + let out_dir = &std::env::var("OUT_DIR").expect("Unable to read OUT_DIR"); + if out_dir.contains('\n') { + panic!("Build path contains a newline, which is unsupported"); + } + + #[cfg(not(feature = "no_auto_layout"))] + auto_layout(out_dir); + + // This link search path is used by both auto_layout() and extern_asm(). + // TODO: Add external assembly and extern_asm(). + println!("cargo:rustc-link-search={}", out_dir); +}
diff --git a/core/runtime/layout_generic.ld b/core/runtime/layout_generic.ld new file mode 100644 index 0000000..0bbef87 --- /dev/null +++ b/core/runtime/layout_generic.ld
@@ -0,0 +1,171 @@ +/* Userland Generic Layout + * + * Currently, due to incomplete ROPI-RWPI support in rustc (see + * https://github.com/tock/libtock-rs/issues/28), this layout implements static + * linking. An application init script must define the FLASH and SRAM address + * ranges as well as MPU_MIN_ALIGN before including this layout file. + * + * Here is a an example application linker script to get started: + * MEMORY { + * /* FLASH memory region must start immediately *after* the Tock + * * Binary Format headers, which means you need to offset the + * * beginning of FLASH memory region relative to where the + * * application is loaded. + * FLASH (rx) : ORIGIN = 0x10030, LENGTH = 0x0FFD0 + * SRAM (RWX) : ORIGIN = 0x20000, LENGTH = 0x10000 + * } + * MPU_MIN_ALIGN = 8K; + * INCLUDE ../libtock-rs/layout.ld + */ + +ENTRY(_start) + +SECTIONS { + /* Section for just the app crt0 header. + * This must be first so that the app can find it. + */ + .crt0_header : + { + _beginning = .; /* Start of the app in flash. */ + /** + * Populate the header expected by `crt0`: + * + * struct hdr { + * uint32_t got_sym_start; + * uint32_t got_start; + * uint32_t got_size; + * uint32_t data_sym_start; + * uint32_t data_start; + * uint32_t data_size; + * uint32_t bss_start; + * uint32_t bss_size; + * uint32_t reldata_start; + * uint32_t stack_size; + * }; + */ + /* Offset of GOT symbols in flash */ + LONG(LOADADDR(.got) - _beginning); + /* Offset of GOT section in memory */ + LONG(_got); + /* Size of GOT section */ + LONG(SIZEOF(.got)); + /* Offset of data symbols in flash */ + LONG(LOADADDR(.data) - _beginning); + /* Offset of data section in memory */ + LONG(_data); + /* Size of data section */ + LONG(SIZEOF(.data)); + /* Offset of BSS section in memory */ + LONG(_bss); + /* Size of BSS section */ + LONG(SIZEOF(.bss)); + /* First address offset after program flash, where elf2tab places + * .rel.data section */ + LONG(LOADADDR(.endflash) - _beginning); + /* The size of the stack requested by this application */ + LONG(_stack_top_aligned - _sstack); + /* Pad the header out to a multiple of 32 bytes so there is not a gap + * between the header and subsequent .data section. It's unclear why, + * but LLD is aligning sections to a multiple of 32 bytes. */ + . = ALIGN(32); + } > FLASH =0xFF + + /* Text section, Code! */ + .text : + { + . = ALIGN(4); + _text = .; + KEEP (*(.start)) + *(.text*) + *(.rodata*) + KEEP (*(.syscalls)) + *(.ARM.extab*) + . = ALIGN(4); /* Make sure we're word-aligned here */ + _etext = .; + } > FLASH =0xFF + + /* Application stack */ + .stack (NOLOAD) : + { + /* elf2tab requires that the `_sram_origin` symbol be present to + * mark the first address in the SRAM memory. Since ELF files do + * not really need to specify this address as they only care about + * loading into flash, we need to manually mark this address for + * elf2tab. elf2tab will use it to add a fixed address header in the + * TBF header if needed. + */ + _sram_origin = .; + _sstack = .; + KEEP(*(.stack_buffer)) + _stack_top_unaligned = .; + . = ALIGN(8); + _stack_top_aligned = .; + } > SRAM + + /* Data section, static initialized variables + * Note: This is placed in Flash after the text section, but needs to be + * moved to SRAM at runtime + */ + .data : AT (_etext) + { + . = ALIGN(4); /* Make sure we're word-aligned here */ + _data = .; + KEEP(*(.data*)) + *(.sdata*) /* RISC-V small-pointer data section */ + . = ALIGN(4); /* Make sure we're word-aligned at the end of flash */ + } > SRAM + + /* Global Offset Table */ + .got : + { + . = ALIGN(4); /* Make sure we're word-aligned here */ + _got = .; + *(.got*) + *(.got.plt*) + . = ALIGN(4); + } > SRAM + + /* BSS section, static uninitialized variables */ + .bss : + { + . = ALIGN(4); /* Make sure we're word-aligned here */ + _bss = .; + KEEP(*(.bss* .sbss*)) + *(COMMON) + . = ALIGN(4); + } > SRAM + + /* End of flash. */ + .endflash : + { + } > FLASH + + /* ARM Exception support + * + * This contains compiler-generated support for unwinding the stack, + * consisting of key-value pairs of function addresses and information on + * how to unwind stack frames. + * https://wiki.linaro.org/KenWerner/Sandbox/libunwind?action=AttachFile&do=get&target=libunwind-LDS.pdf + * + * .ARM.exidx is sorted, so has to go in its own output section. + * + * __NOTE__: It's at the end because we currently don't actually serialize + * it to the binary in elf2tbf. If it was before the RAM sections, it would + * through off our calculations of the header. + */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + /* (C++) Index entries for section unwinding */ + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + PROVIDE_HIDDEN (__exidx_end = .); + + /DISCARD/ : + { + *(.eh_frame) + } +} + +ASSERT((_stack_top_aligned - _stack_top_unaligned) == 0, " +STACK_SIZE must be 8 byte multiple")
diff --git a/core/runtime/layouts/apollo3.ld b/core/runtime/layouts/apollo3.ld new file mode 100644 index 0000000..8713c27 --- /dev/null +++ b/core/runtime/layouts/apollo3.ld
@@ -0,0 +1,11 @@ +/* Layout for the Apollo3 MCU, used by the examples in this repository. */ + +MEMORY { + /* The application region is 64 bytes (0x40) */ + FLASH (rx) : ORIGIN = 0x00040040, LENGTH = 0x0005FFC0 + SRAM (rwx) : ORIGIN = 0x10002000, LENGTH = 0x2000 +} + +MPU_MIN_ALIGN = 8K; + +INCLUDE layout_generic.ld
diff --git a/core/runtime/layouts/hail.ld b/core/runtime/layouts/hail.ld new file mode 100644 index 0000000..179a883 --- /dev/null +++ b/core/runtime/layouts/hail.ld
@@ -0,0 +1,11 @@ +/* Layout for the Hail board, used by the examples in this repository. */ + +MEMORY { + /* The application region is 64 bytes (0x40) */ + FLASH (rx) : ORIGIN = 0x00030040, LENGTH = 0x0005FFC0 + SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 62K +} + +MPU_MIN_ALIGN = 8K; + +INCLUDE layout_generic.ld
diff --git a/core/runtime/layouts/hifive1.ld b/core/runtime/layouts/hifive1.ld new file mode 100644 index 0000000..20294ce --- /dev/null +++ b/core/runtime/layouts/hifive1.ld
@@ -0,0 +1,18 @@ +/* Layout for the RISC-V 32 boards, used by the examples in this repository. */ + +MEMORY { + /* + * The TBF header can change in size so use 0x40 combined with + * --protected-region-size with elf2tab to cover a header upto that + * size. + * + * Note that the SRAM address may need to be changed depending on + * the kernel binary, check for the actual address of APP_MEMORY! + */ + FLASH (rx) : ORIGIN = 0x20040040, LENGTH = 32M + SRAM (rwx) : ORIGIN = 0x80002400, LENGTH = 0x1C00 +} + +MPU_MIN_ALIGN = 1K; + +INCLUDE layout_generic.ld
diff --git a/core/runtime/layouts/imxrt1050.ld b/core/runtime/layouts/imxrt1050.ld new file mode 100644 index 0000000..3e7f904 --- /dev/null +++ b/core/runtime/layouts/imxrt1050.ld
@@ -0,0 +1,11 @@ +/* Layout for the iMX.RT1050 board, used by the examples in this repository. */ + +MEMORY { + /* The application region is 64 bytes (0x40) */ + FLASH (rx) : ORIGIN = 0x63002040, LENGTH = 0xFFFFC0 + SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 112K +} + +MPU_MIN_ALIGN = 8K; + +INCLUDE layout_generic.ld
diff --git a/core/runtime/layouts/msp432.ld b/core/runtime/layouts/msp432.ld new file mode 100644 index 0000000..2c9d2a4 --- /dev/null +++ b/core/runtime/layouts/msp432.ld
@@ -0,0 +1,9 @@ +MEMORY { + /* The application region is 64 bytes (0x40) */ + FLASH (rx) : ORIGIN = 0x00020040, LENGTH = 0x0001FFC0 + SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 0x2000 +} + +MPU_MIN_ALIGN = 8K; + +INCLUDE layout_generic.ld
diff --git a/core/runtime/layouts/nrf52.ld b/core/runtime/layouts/nrf52.ld new file mode 100644 index 0000000..942e86b --- /dev/null +++ b/core/runtime/layouts/nrf52.ld
@@ -0,0 +1,11 @@ +/* Layout for the nRF52-DK, used by the examples in this repository. */ + +MEMORY { + /* The application region is 64 bytes (0x40) */ + FLASH (rx) : ORIGIN = 0x00030040, LENGTH = 0x0005FFC0 + SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 62K +} + +MPU_MIN_ALIGN = 8K; + +INCLUDE layout_generic.ld
diff --git a/core/runtime/layouts/nrf52840.ld b/core/runtime/layouts/nrf52840.ld new file mode 100644 index 0000000..31bf346 --- /dev/null +++ b/core/runtime/layouts/nrf52840.ld
@@ -0,0 +1,11 @@ +/* Layout for the nRF52840-DK, usable by the examples in this repository. */ + +MEMORY { + /* The application region is 64 bytes (0x40) */ + FLASH (rx) : ORIGIN = 0x00030040, LENGTH = 0x000CFFC0 + SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 62K +} + +MPU_MIN_ALIGN = 8K; + +INCLUDE layout_generic.ld
diff --git a/core/runtime/layouts/nucleo_f429zi.ld b/core/runtime/layouts/nucleo_f429zi.ld new file mode 100644 index 0000000..3e407b4 --- /dev/null +++ b/core/runtime/layouts/nucleo_f429zi.ld
@@ -0,0 +1,11 @@ +/* Layout for the Nucleo F429zi, used by the examples in this repository. */ + +MEMORY { + /* The application region is 64 bytes (0x40) */ + FLASH (rx) : ORIGIN = 0x08040040, LENGTH = 255K + SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 112K +} + +MPU_MIN_ALIGN = 8K; + +INCLUDE layout_generic.ld
diff --git a/core/runtime/layouts/nucleo_f446re.ld b/core/runtime/layouts/nucleo_f446re.ld new file mode 100644 index 0000000..83e698b --- /dev/null +++ b/core/runtime/layouts/nucleo_f446re.ld
@@ -0,0 +1,11 @@ +/* Layout for the Nucleo F446re, used by the examples in this repository. */ + +MEMORY { + /* The application region is 64 bytes (0x40) */ + FLASH (rx) : ORIGIN = 0x08040040, LENGTH = 255K + SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 176K +} + +MPU_MIN_ALIGN = 8K; + +INCLUDE layout_generic.ld
diff --git a/core/runtime/layouts/opentitan.ld b/core/runtime/layouts/opentitan.ld new file mode 100644 index 0000000..ada781c --- /dev/null +++ b/core/runtime/layouts/opentitan.ld
@@ -0,0 +1,18 @@ +/* Layout for the RISC-V 32 boards, used by the examples in this repository. */ + +MEMORY { + /* + * The TBF header can change in size so use 0x40 combined with + * --protected-region-size with elf2tab to cover a header upto that + * size. + * + * Note that the SRAM address may need to be changed depending on + * the kernel binary, check for the actual address of APP_MEMORY! + */ + FLASH (rx) : ORIGIN = 0x20030040, LENGTH = 32M + SRAM (rwx) : ORIGIN = 0x10004000, LENGTH = 512K +} + +MPU_MIN_ALIGN = 1K; + +INCLUDE layout_generic.ld
diff --git a/core/runtime/layouts/stm32f3discovery.ld b/core/runtime/layouts/stm32f3discovery.ld new file mode 100644 index 0000000..9368003 --- /dev/null +++ b/core/runtime/layouts/stm32f3discovery.ld
@@ -0,0 +1,11 @@ +/* Layout for the stm32f3discovery board, usable by the examples in this repository. */ + +MEMORY { + /* The application region is 64 bytes (0x40) */ + FLASH (rx) : ORIGIN = 0x08020040, LENGTH = 0x00020000 + SRAM (rwx) : ORIGIN = 0x20004000, LENGTH = 48K +} + +MPU_MIN_ALIGN = 8K; + +INCLUDE layout_generic.ld
diff --git a/core/runtime/src/lib.rs b/core/runtime/src/lib.rs new file mode 100644 index 0000000..d7ea623 --- /dev/null +++ b/core/runtime/src/lib.rs
@@ -0,0 +1,21 @@ +//! `libtock_runtime` provides the runtime for Tock process binaries written in +//! Rust as well as interfaces to Tock's system calls. +//! +//! `libtock_runtime` is designed for statically-compiled binaries, and needs to +//! know the location (in non-volatile memory and RAM) at which the process will +//! execute. It reads the `LIBTOCK_PLATFORM` variable to determine what location +//! to build for (see the `layouts/` directory to see what platforms are +//! available). It expects the following cargo config options to be set (e.g. in +//! `.cargo/config`): +//! ``` +//! [build] +//! rustflags = [ +//! "-C", "relocation-model=static", +//! "-C", "link-arg=-Tlayout.ld", +//! ] +//! ``` +//! If a process binary wants to support another platform, it can set the +//! `no_auto_layout` feature on `libtock_runtime` to disable this functionality +//! and provide its own layout file. + +#![no_std]