CantripOS includes a multi-platform build framework. This framwork leverages make, cmake, and cargo. To get started follow these steps:
- Clone the Sparrow project from GitHub using the repo tool We assume below this lands in a top-level directory named "sparrow".
- Download, build, and boot the system to the Cantrip shell prompt. For now the only target platform that works is "rpi3" (for a raspi3b machine running in simulation on qemu).
mkdir sparrow
cd sparrow
repo init -u https://github.com/AmbiML/sparrow-manifest -m sparrow-manifest.xml
repo sync -j$(nproc)
export PLATFORM=rpi3
source build/setup.sh
m prereqs
m simulate
[Beware that if your repo tool is out of date you may need to supply -b main
to the init request as older versions of repo only check for a master
branch.]
Note the above assumes you have the follow prerequisites installed on your system and in your shell's search path:
- Gcc (or clang) for the target architecture
- Rust; any nightly build >=nightly-2021-11-05 should work. A default version is set
in the build/setup.sh script; if that is not what you are using either edit the shell
script or export
CANTRIP_RUST_VERSION
in each shell where you work. Beware that we use various nightly-only features that are not supported by stable versions of Rust (e.g. to override the default TLS model). - Whichever simulator seL4 expects for your target architecture; e.g. for aarch64 this is qemu-system-aarch64.
The m prereqs
step installs required python packages using the pip
tool. At the moment this mostly sets up a virtual environment for the
project.
Because Shodan is a CAmkES project you also need CAmkES dependencies.
Sparrow uses repo to download and piece together Sparrow git repositories as well as dependent projects / repositories such as seL4.
$ repo init -u https://github.com/AmbiML/sparrow-manifest -m sparrow-manifest.xml
Downloading Repo source from https://gerrit.googlesource.com/git-repo
repo has been initialized in <your-directory>/sparrow/
If this is not the directory in which you want to initialize repo, please run:
rm -r <your-directory>/sparrow//.repo
and try again.
$ repo sync -j12
Fetching: 100% (23/23), done in 9.909s
Garbage collecting: 100% (23/23), done in 0.218s
Checking out: 100% (23/23), done in 0.874s
repo sync has finished successfully.
$ export PLATFORM=rpi3
$ export CANTRIP_RUST_VERSION=nightly
$ source build/setup.sh
========================================
ROOTDIR=/<your-directory>/sparrow
OUT=/<your-directory>/sparrow/out
PLATFORM=rpi3
PYTHON_SPARROW_ENV=<your-directory>/sparrow/cache/rpi3-venv
========================================
Type 'm [target]' to build.
Targets available are:
...
cantrip cantrip-build-debug-prepare cantrip-build-release-prepare cantrip-builtins
cantrip-builtins-debug cantrip-builtins-release cantrip-bundle-debug cantrip-bundle-release
cantrip-clean cantrip-clean-headers cantrip-clippy cantrip-component-headers
...
$ m prereqs
<your-directory>/sparrow/scripts/install-prereqs.sh \
-p "<your-directory>/sparrow/scripts/python-requirements.txt \
" \
-a ""
Installing apt package dependencies...
Installing python package dependencies...
Creating virtual python environment <your-directory>/sparrow/cache/rpi3-venv
...
Installation complete.
$ m simulate
...
info: component 'rust-std' for target 'aarch64-unknown-none' is up to date
loading initial cache file <your-directory>/sparrow/cantrip/projects/camkes/settings.cmake
-- Set platform details from PLATFORM=rpi3
-- KernelPlatform: bcm2837
-- KernelARMPlatform: rpi3
-- Setting from flags KernelSel4Arch: aarch64
-- Found seL4: <your-directory>/sparrow/kernel
-- The C compiler identification is GNU 11.2.1
...
[291/291] Generating images/capdl-loader-image-arm-bcm2837
...
qemu-system-aarch64 -machine raspi3b -nographic -serial null -serial mon:stdio -m size=1024M -s \
-kernel /<your-directory>/sparrow/out/cantrip/aarch64-unknown-elf/release/capdl-loader-image \
--mem-path /<your-directory>/sparrow/out/cantrip/aarch64-unknown-elf/release/cantrip.mem
ELF-loader started on CPU: ARM Ltd. Cortex-A53 r0p4
paddr=[8bd000..fed0ff]
No DTB passed in from boot loader.
Looking for DTB in CPIO archive...found at 9b3ef8.
Loaded DTB from 9b3ef8.
paddr=[23c000..23ffff]
ELF-loading image 'kernel' to 0
paddr=[0..23bfff]
vaddr=[ffffff8000000000..ffffff800023bfff]
virt_entry=ffffff8000000000
ELF-loading image 'capdl-loader' to 240000
paddr=[240000..4c0fff]
vaddr=[400000..680fff]
virt_entry=4009e8
Enabling MMU and paging
Jumping to kernel-image entry point...
Warning: gpt_cntfrq 62500000, expected 19200000
Bootstrapping kernel
Booting all finished, dropped to user space
cantrip_os_rootserver::Bootinfo: (1969, 131072) empty slots 1 nodes (15, 83) untyped 131072 cnode slots
cantrip_os_rootserver::Model: 1821 objects 1 irqs 0 untypeds 2 asids
cantrip_os_rootserver::capDL spec: 0.39 Mbytes
cantrip_os_rootserver::CAmkES components: 5.85 Mbytes
cantrip_os_rootserver::Rootserver executable: 1.07 Mbytes
<<seL4(CPU 0) [decodeARMFrameInvocation/2137 T0xffffff80004c7400 "rootserver" @44373c]: ARMPageMap: Attempting to remap a frame that does not belong to the passed address space>>
...
<<seL4(CPU 0) [decodeCNodeInvocation/107 T0xffffff80009a3400 "rootserver" @4268a0]: CNode Copy/Mint/Move/Mutate: Source slot invalid or empty.>>
...
CANTRIP> builtins
autostart.repl 336
hello.app 1084
keyval.app 32276
logtest.app 26948
panic.app 25688
timer.app 33060
CANTRIP> install hello.app
cantrip_memory_manager::Global memory: 0 allocated 130543360 free, reserved: 2273280 kernel 1359872 user
Collected 1084 bytes of data, crc32 5b847193
Application "hello" installed
CANTRIP> start hello
Bundle "hello" started.
CANTRIP> install keyval.app
I am a C app!
Done, sleeping in WFI loop
Collected 32276 bytes of data, crc32 bcf05273
Application "keyval" installed
CANTRIP> start keyval
Bundle "keyval" started.
...
CANTRIP> mstats
48 bytes in-use, 130543312 bytes free, 720512 bytes requested, 1359872 overhead
2 objs in-use, 196 objs requested
CANTRIP> EOF
The m simulate
command can be run repeatedly. If you need to reset
your setup just remove the build tree and re-run m simulate
; e.g.
$ cd sparrow
$ m clean
$ m simulate
The setup procedure required:
$ export PLATFORM=rpi3
$ export CANTRIP_RUST_VERSION=nightly # force use of "nightly" channel
$ source build/setup.sh
This defined various shell functions/aliases for working with CantripOS. In particular
the m
command is the primary mechanism for building and running simulations.
The default target command is simulate
so these are equivalent:
$ m simulate
$ m # default target is simulate
As seen above, another useful target is m simulate-debug
which builds a debug version
of the system and starts up a simulator. In this case the simulator (platform-dependent)
supports connecting GDB with scripts/kgdb.sh in a separate window/terminal. For more
information on using GDB with seL4 check here.
There is tab completion for build targets depending on your shell; e.g.
$ m <TAB>
cargo_test_debugconsole_zmodem kata-gen-headers
cargo_test_kata keyval_debug
cargo_test_kata_os_common_logger keyval_release
cargo_test_kata_os_common_slot_allocator logtest_debug
cargo_test_kata_proc_interface logtest_release
cargo_test_kata_proc_manager matcha_tock_clean
clean matcha_tock_debug
collate_kata_rust_toolchain matcha_tock_release
collate_matcha_rust_toolchain minisel_debug
collate_rust_toolchains minisel_release
elfconvert multihart_boot_rom
fibonacci_debug multihart_boot_rom_clean
fibonacci_release panic_debug
flatbuffers panic_release
flatbuffers-clean prereqs
...
There is also a hmm
command that can display help information for a build target. For example,
$ hmm sel4test
sel4test: (defined in build/platforms/shodan/sim_sel4test.mk)
C-based libsel4 syscall api wrappers. The result is run under Renode.
The build system supports multiple target platforms. But at the moment there are only two platforms--shodan & rpi3--so this is less exciting. The current platform is kept in your shell's environmnet so after a default setup you will see:
$ source build/setup.sh
$ printenv PLATFORM
shodan
But this also means that you need to source build/setup.sh
in each shell
where you work on the software.
To switch the current platform use the set-platform
shell function:
$ set-platform rpi3
$ printenv PLATFORM
rpi3
There is also a list-platforms
shell function that you can use in lieu of
tab completion with the set-platform
command.
Most of the time m simulate
or m simulate-debug
is all you need to do work:
make dependencies will cause only necessary operations to be done.
But sometimes it's necessary to remove build artifacts (e.g. because depeencies
are incorrect or the dependencies are overly conservative resulting in excessive
build steps).
Therre are many targets that selectively clear out unwanted artifacts but most
of the time you will just want to use:
$ m cantrip-clean
which removes all build artifacts for the current platform, or
$ m clean
which removes all build artifacts for all platforms.