Use llvm objcopy from rust toolchain 🎉

Its the last missing util we needed to be a rust-toolchain-only project.

https://github.com/rust-lang/rust/pull/50336
https://github.com/japaric/cargo-binutils
pull/4/head
Andre Richter 6 years ago
parent 038c8ac55c
commit 323a346b07
No known key found for this signature in database
GPG Key ID: 2116C1AB102F615E

@ -1,118 +0,0 @@
AArch64 Kereszt-Fordító
=======================
Mielőtt nekiugranál az oktatóanyagoknak, szükséged lesz néhány szerszámra. Nevezetesen egy fordítóra, ami
képes AArch64-re fordítani, és a hozzá kapcsolódó programokra.
**FONTOS MEGJEGYZÉS**: ez az leírás nem a kereszt-fordítókról szól úgy általánosságban, hanem arról, hogy
hogyan fordítsunk konkrétan *aarch64-elf* target-re. Ha problémád adódik, keress rá a google-ön arra, "hogyan
fordítsunk gcc kereszt-fordítót" vagy kérdezz az operációs rendszered szerinti támogatói fórumokon. Nem tudok és
nem is fogok segíteni a környezeted kialakításában, azt neked kell megoldanod. Mint a bevezetőben már írtam,
feltételezem, hogy tudod, hogyan kell programokat fordítani (beleértve a kereszt-fordító fordítását).
Build rendszer
--------------
A fordítás levezénylésére a GNU make-t fogjuk használni. Ezt nem kell kereszt-fordítani, mivel csak az asztali gépen
fogjuk futtatni, nem a céleszközön. Azért választottam ezt az oktatóanyagokhoz, mert a GNU make-re a fordító
lefordításához is szükséged lesz, szóval ígyis-úgyis kelleni fog.
Források letöltése és kicsomagolása
------------------------------------
Legelőször is, töltsd le a binutils és gcc forrásait. Ebben a példában az íráskor legfrissebb verziókat használtam.
Javaslom, hogy nézd meg a szervereket, és a legfrissebbre módosítsd a fájlneveket.
```sh
wget http://ftpmirror.gnu.org/binutils/binutils-2.29.tar.gz
wget http://ftpmirror.gnu.org/gcc/gcc-7.2.0/gcc-7.2.0.tar.gz
wget http://ftpmirror.gnu.org/mpfr/mpfr-3.1.6.tar.gz
wget http://ftpmirror.gnu.org/gmp/gmp-6.1.2.tar.bz2
wget http://ftpmirror.gnu.org/mpc/mpc-1.0.3.tar.gz
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.18.tar.bz2
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/cloog-0.18.1.tar.gz
```
Miután végezett a letöltés, csomagold ki a tömörített fájlokat:
```sh
for i in *.tar.gz; do tar -xzf $i; done
for i in *.tar.bz2; do tar -xjf $i; done
```
Szükség lesz még néhány symlink-re mielőtt a fordtást elkezdhetnénk, hozzuk létre ezeket:
```sh
cd binutils-*
ln -s ../isl-* isl
cd ..
cd gcc-*
ln -s ../mpfr-* mpfr
ln -s ../gmp-* gmp
ln -s ../mpc-* mpc
ln -s ../cloog-* cloog
cd ..
```
Források lefordítása
--------------------
Oké, két csomagot kell fordítanunk. Az egyik a *binutils*, ami tartalmazza a linker-t, assembler-t és még pár
hasznos parancsot.
```sh
cd binutils-*
configure --prefix=/usr/local/cross-compiler --target=aarch64-elf \
--enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit \
--disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-plugin \
--disable-linker-build-id --enable-lto --enable-install-libiberty --with-linker-hash-style=gnu --with-gnu-ld\
--enable-gnu-indirect-function --disable-multilib --disable-werror --enable-checking=release --enable-default-pie \
--enable-default-ssp --enable-gnu-unique-object
make -j4
make install
```
Az első paraméter megmondja a configure szkriptnek, hogy a `/usr/local/cross-compiler` mappába telepítsen. A második
megadja a célarchítektúrát, amire a most fordítandó eszközök fordítanak majd. A maradék paramétek ki és bekapcsolgat
bizonyos funkciókat, ne foglalkozz velük. Elég annyit tudni, hogy ezek egy beágyazott fordítóhoz vannak optimalizálva.
A második csomag, természetesen maga a *gcc* fordító.
```sh
cd gcc-*
configure --prefix=/usr/local/cross-compiler --target=aarch64-elf --enable-languages=c \
--enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit \
--disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-plugin \
--disable-linker-build-id --enable-lto --enable-install-libiberty --with-linker-hash-style=gnu --with-gnu-ld\
--enable-gnu-indirect-function --disable-multilib --disable-werror --enable-checking=release --enable-default-pie \
--enable-default-ssp --enable-gnu-unique-object
make -j4 all-gcc
make install-gcc
```
Itt ugyanúgy megadjuk a könyvtárat és a célarchitektúrát, mint az előbb. Megadjuk azt is, hogy csak C fordítót kérünk,
mivel a gcc rengeteg nyelvet ismer, amire nem lesz szükség. Ez jelentősen lecsökkenti a fordítási időt. A fennmaradó
kapcsolók ugyan azok, mint a binutils esetében.
Ha végzett, nézd meg a `bin` mappát a `/usr/local/cross-compiler` könyvtárban. Egy rakás futtatható programot kell
ott találnod. Meggyőződésem, hogy ezt a mappát hozzá akarod adni a PATH-odhoz is.
```sh
$ ls /usr/local/cross-compiler/bin
aarch64-elf-addr2line aarch64-elf-elfedit aarch64-elf-gcc-ranlib aarch64-elf-ld aarch64-elf-ranlib
aarch64-elf-ar aarch64-elf-gcc aarch64-elf-gcov aarch64-elf-ld.bfd aarch64-elf-readelf
aarch64-elf-as aarch64-elf-gcc-7.2.0 aarch64-elf-gcov-dump aarch64-elf-nm aarch64-elf-size
aarch64-elf-c++filt aarch64-elf-gcc-ar aarch64-elf-gcov-tool aarch64-elf-objcopy aarch64-elf-strings
aarch64-elf-cpp aarch64-elf-gcc-nm aarch64-elf-gprof aarch64-elf-objdump aarch64-elf-strip
```
Amik ezek közül számunkra érdekesek:
- aarch64-elf-as - az assembler
- aarch64-elf-gcc - a C fordító
- aarch64-elf-ld - a linker
- aarch64-elf-objcopy - az ELF futtathatók IMG-re való konvertálásához kell
- aarch64-elf-objdump - futtathatók disassemblálására (debuggoláshoz)
- aarch64-elf-readelf - hasznos eszköz a futtathatókban lévő szekciók és szegmensek listázásra (debuggoláshoz)
Ha mind a hat fenti futtahatót látod, és hibaüzenet nélkül le is futnak, gratulálok!
Minden eszköz a rendelkezésedre áll, elkezdheted az oktatóanyagot!

@ -1,118 +0,0 @@
AArch64 Cross Compiler
======================
Before we could start our tutorials, you'll need some tools. Namely a compiler that compiles for the AArch64
architecture and it's companion utilities.
**IMPORTANT NOTE**: this description is not about how to compile a cross-compiler in general. It's about how to
compile one specifically for the *aarch64-elf* target. If you have problems, google "how to build a gcc cross-compiler"
or ask on an appropriate support forum for your operating system. I can't and won't help you with your environment,
you have to solve that on your own. As I've said in the introduction I assume you know how to compile programs
(including the compilation of the cross-compiler).
Build system
------------
To orchestrate compilation, we'll use GNU make. No need for cross-compiling this, as we are about to use it on the
host computer only, and not on the target machine. The reason I choosed this build system for the tutorials is that
GNU make is also required to compile the compiler, so you'll need it anyway.
Download and unpack sources
---------------------------
First of all, download binutils and gcc sources. In this example I've used the latest versions as of writing.
You are advised to check the mirrors and modify filenames accordly.
```sh
wget http://ftpmirror.gnu.org/binutils/binutils-2.29.tar.gz
wget http://ftpmirror.gnu.org/gcc/gcc-7.2.0/gcc-7.2.0.tar.gz
wget http://ftpmirror.gnu.org/mpfr/mpfr-3.1.6.tar.gz
wget http://ftpmirror.gnu.org/gmp/gmp-6.1.2.tar.bz2
wget http://ftpmirror.gnu.org/mpc/mpc-1.0.3.tar.gz
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.18.tar.bz2
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/cloog-0.18.1.tar.gz
```
Once the download finished, unpack the tarballs with these commands:
```sh
for i in *.tar.gz; do tar -xzf $i; done
for i in *.tar.bz2; do tar -xjf $i; done
```
You'll need some symbolic links before you could start the compilation, so let's create them:
```sh
cd binutils-*
ln -s ../isl-* isl
cd ..
cd gcc-*
ln -s ../mpfr-* mpfr
ln -s ../gmp-* gmp
ln -s ../mpc-* mpc
ln -s ../cloog-* cloog
cd ..
```
Compiling the sources
---------------------
Okay, now we have to build two packages. One is called *binutils*, which includes linker, assembler and other
useful commands.
```sh
cd binutils-*
configure --prefix=/usr/local/cross-compiler --target=aarch64-elf \
--enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit \
--disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-plugin \
--disable-linker-build-id --enable-lto --enable-install-libiberty --with-linker-hash-style=gnu --with-gnu-ld\
--enable-gnu-indirect-function --disable-multilib --disable-werror --enable-checking=release --enable-default-pie \
--enable-default-ssp --enable-gnu-unique-object
make -j4
make install
```
The first argument tells the configure script to install the build in `/usr/local/cross-compiler`. The second
specifies the target architecture, for which we want the tools to be compiled. The other arguments turn specific
options on and off, don't bother. It's enough to know they are appropriately tweeked for an embedded system compiler.
And the second package, of course we'll need the *gcc compiler* itself.
```sh
cd gcc-*
configure --prefix=/usr/local/cross-compiler --target=aarch64-elf --enable-languages=c \
--enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit \
--disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-plugin \
--disable-linker-build-id --enable-lto --enable-install-libiberty --with-linker-hash-style=gnu --with-gnu-ld\
--enable-gnu-indirect-function --disable-multilib --disable-werror --enable-checking=release --enable-default-pie \
--enable-default-ssp --enable-gnu-unique-object
make -j4 all-gcc
make install-gcc
```
Here we specify the same directory and architecture as before. We also tell to compile only the C compiler, as gcc
otherwise would support tons of languages we don't need. This reduces the compilation time significantly. The remaining
arguments are the same as with binutils.
Now check `bin` folder in your `/usr/local/cross-compiler` directory. You should see a lot of executables there. You
probably also want to add this directory to your PATH environment variable.
```sh
$ ls /usr/local/cross-compiler/bin
aarch64-elf-addr2line aarch64-elf-elfedit aarch64-elf-gcc-ranlib aarch64-elf-ld aarch64-elf-ranlib
aarch64-elf-ar aarch64-elf-gcc aarch64-elf-gcov aarch64-elf-ld.bfd aarch64-elf-readelf
aarch64-elf-as aarch64-elf-gcc-7.2.0 aarch64-elf-gcov-dump aarch64-elf-nm aarch64-elf-size
aarch64-elf-c++filt aarch64-elf-gcc-ar aarch64-elf-gcov-tool aarch64-elf-objcopy aarch64-elf-strings
aarch64-elf-cpp aarch64-elf-gcc-nm aarch64-elf-gprof aarch64-elf-objdump aarch64-elf-strip
```
The executables we are interested in:
- aarch64-elf-as - the assembler
- aarch64-elf-gcc - the C compiler
- aarch64-elf-ld - the linker
- aarch64-elf-objcopy - to convert ELF executable into IMG format
- aarch64-elf-objdump - utility to disassemble executables (for debugging)
- aarch64-elf-readelf - an useful utility to dump sections and segments in executables (for debugging)
If you have all of the above six executables and you can also run them without error messages, congrats!
You have all the tools needed, you can start to work with my tutorials!

1
.gitignore vendored

@ -1 +0,0 @@
**/dockcross-linux-aarch64

@ -24,21 +24,14 @@
TARGET = aarch64-raspi3-none-elf
CROSS_CONTAINER = ./dockcross-linux-aarch64
CROSS_CONTAINER_ROOT = /usr/xcc/aarch64-unknown-linux-gnueabi/bin
CROSS_CONTAINER_OBJCOPY = $(CROSS_CONTAINER_ROOT)/aarch64-unknown-linux-gnueabi-objcopy
OBJCOPY = cargo objcopy --
OBJCOPY_PARAMS = --strip-all -O binary
UTILS_CONTAINER = andrerichter/raspi3-utils
DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work
QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img
all: clean cross_cont_download kernel8.img
cross_cont_download:
ifeq (,$(wildcard $(CROSS_CONTAINER)))
docker run --rm dockcross/linux-arm64 > $(CROSS_CONTAINER)
chmod +x $(CROSS_CONTAINER)
endif
all: clean kernel8.img
target/$(TARGET)/debug/kernel8: src/main.rs
RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET)
@ -55,7 +48,7 @@ kernel8: target/$(TARGET)/release/kernel8
endif
kernel8.img: kernel8
$(CROSS_CONTAINER) $(CROSS_CONTAINER_OBJCOPY) -O binary -S $< kernel8.img
$(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img
qemu:
$(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -d in_asm

@ -24,21 +24,14 @@
TARGET = aarch64-raspi3-none-elf
CROSS_CONTAINER = ./dockcross-linux-aarch64
CROSS_CONTAINER_ROOT = /usr/xcc/aarch64-unknown-linux-gnueabi/bin
CROSS_CONTAINER_OBJCOPY = $(CROSS_CONTAINER_ROOT)/aarch64-unknown-linux-gnueabi-objcopy
OBJCOPY = cargo objcopy --
OBJCOPY_PARAMS = --strip-all -O binary
UTILS_CONTAINER = andrerichter/raspi3-utils
DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work
QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img
all: clean cross_cont_download kernel8.img
cross_cont_download:
ifeq (,$(wildcard $(CROSS_CONTAINER)))
docker run --rm dockcross/linux-arm64 > $(CROSS_CONTAINER)
chmod +x $(CROSS_CONTAINER)
endif
all: clean kernel8.img
target/$(TARGET)/debug/kernel8: src/main.rs
RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET)
@ -55,7 +48,7 @@ kernel8: target/$(TARGET)/release/kernel8
endif
kernel8.img: kernel8
$(CROSS_CONTAINER) $(CROSS_CONTAINER_OBJCOPY) -O binary -S $< kernel8.img
$(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img
qemu:
$(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -d in_asm

@ -24,21 +24,14 @@
TARGET = aarch64-raspi3-none-elf
CROSS_CONTAINER = ./dockcross-linux-aarch64
CROSS_CONTAINER_ROOT = /usr/xcc/aarch64-unknown-linux-gnueabi/bin
CROSS_CONTAINER_OBJCOPY = $(CROSS_CONTAINER_ROOT)/aarch64-unknown-linux-gnueabi-objcopy
OBJCOPY = cargo objcopy --
OBJCOPY_PARAMS = --strip-all -O binary
UTILS_CONTAINER = andrerichter/raspi3-utils
DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work
QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img
all: clean cross_cont_download kernel8.img
cross_cont_download:
ifeq (,$(wildcard $(CROSS_CONTAINER)))
docker run --rm dockcross/linux-arm64 > $(CROSS_CONTAINER)
chmod +x $(CROSS_CONTAINER)
endif
all: clean kernel8.img
target/$(TARGET)/debug/kernel8: src/main.rs
RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET)
@ -55,7 +48,7 @@ kernel8: target/$(TARGET)/release/kernel8
endif
kernel8.img: kernel8
$(CROSS_CONTAINER) $(CROSS_CONTAINER_OBJCOPY) -O binary -S $< kernel8.img
$(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img
qemu:
$(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio

@ -24,21 +24,14 @@
TARGET = aarch64-raspi3-none-elf
CROSS_CONTAINER = ./dockcross-linux-aarch64
CROSS_CONTAINER_ROOT = /usr/xcc/aarch64-unknown-linux-gnueabi/bin
CROSS_CONTAINER_OBJCOPY = $(CROSS_CONTAINER_ROOT)/aarch64-unknown-linux-gnueabi-objcopy
OBJCOPY = cargo objcopy --
OBJCOPY_PARAMS = --strip-all -O binary
UTILS_CONTAINER = andrerichter/raspi3-utils
DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work
QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img
all: clean cross_cont_download kernel8.img
cross_cont_download:
ifeq (,$(wildcard $(CROSS_CONTAINER)))
docker run --rm dockcross/linux-arm64 > $(CROSS_CONTAINER)
chmod +x $(CROSS_CONTAINER)
endif
all: clean kernel8.img
target/$(TARGET)/debug/kernel8: src/main.rs
RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET)
@ -55,7 +48,7 @@ kernel8: target/$(TARGET)/release/kernel8
endif
kernel8.img: kernel8
$(CROSS_CONTAINER) $(CROSS_CONTAINER_OBJCOPY) -O binary -S $< kernel8.img
$(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img
qemu:
$(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio

@ -24,21 +24,14 @@
TARGET = aarch64-raspi3-none-elf
CROSS_CONTAINER = ./dockcross-linux-aarch64
CROSS_CONTAINER_ROOT = /usr/xcc/aarch64-unknown-linux-gnueabi/bin
CROSS_CONTAINER_OBJCOPY = $(CROSS_CONTAINER_ROOT)/aarch64-unknown-linux-gnueabi-objcopy
OBJCOPY = cargo objcopy --
OBJCOPY_PARAMS = --strip-all -O binary
UTILS_CONTAINER = andrerichter/raspi3-utils
DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work
QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img
all: clean cross_cont_download kernel8.img
cross_cont_download:
ifeq (,$(wildcard $(CROSS_CONTAINER)))
docker run --rm dockcross/linux-arm64 > $(CROSS_CONTAINER)
chmod +x $(CROSS_CONTAINER)
endif
all: clean kernel8.img
target/$(TARGET)/debug/kernel8: src/main.rs
RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET)
@ -55,7 +48,7 @@ kernel8: target/$(TARGET)/release/kernel8
endif
kernel8.img: kernel8
$(CROSS_CONTAINER) $(CROSS_CONTAINER_OBJCOPY) -O binary -S $< kernel8.img
$(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img
qemu:
$(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio

@ -24,21 +24,14 @@
TARGET = aarch64-raspi3-none-elf
CROSS_CONTAINER = ./dockcross-linux-aarch64
CROSS_CONTAINER_ROOT = /usr/xcc/aarch64-unknown-linux-gnueabi/bin
CROSS_CONTAINER_OBJCOPY = $(CROSS_CONTAINER_ROOT)/aarch64-unknown-linux-gnueabi-objcopy
OBJCOPY = cargo objcopy --
OBJCOPY_PARAMS = --strip-all -O binary
UTILS_CONTAINER = andrerichter/raspi3-utils
DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work
QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img
all: clean cross_cont_download kernel8.img
cross_cont_download:
ifeq (,$(wildcard $(CROSS_CONTAINER)))
docker run --rm dockcross/linux-arm64 > $(CROSS_CONTAINER)
chmod +x $(CROSS_CONTAINER)
endif
all: clean kernel8.img
target/$(TARGET)/debug/kernel8: src/main.rs
RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET)
@ -55,7 +48,7 @@ kernel8: target/$(TARGET)/release/kernel8
endif
kernel8.img: kernel8
$(CROSS_CONTAINER) $(CROSS_CONTAINER_OBJCOPY) -O binary -S $< kernel8.img
$(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img
qemu:
$(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio

@ -56,7 +56,7 @@ that link address. When we're done, the memory at `0x80_000` is free to use. You
can check that with:
```sh
$ ./dockcross-linux-aarch64 aarch64-linux-gnu-nm kernel8 | grep reset
$ cargo nm -- kernel8 | grep reset
000000000007ffc0 T reset
```

@ -24,9 +24,8 @@
TARGET = aarch64-raspi3-none-elf
CROSS_CONTAINER = ./dockcross-linux-aarch64
CROSS_CONTAINER_ROOT = /usr/xcc/aarch64-unknown-linux-gnueabi/bin
CROSS_CONTAINER_OBJCOPY = $(CROSS_CONTAINER_ROOT)/aarch64-unknown-linux-gnueabi-objcopy
OBJCOPY = cargo objcopy --
OBJCOPY_PARAMS = --strip-all -O binary
UTILS_CONTAINER = andrerichter/raspi3-utils
DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work
@ -34,13 +33,7 @@ DOCKER_TTY = --privileged -v /dev:/dev
QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img
RASPBOOT_CMD = raspbootcom /dev/ttyUSB0 kernel8.img
all: clean cross_cont_download kernel8.img
cross_cont_download:
ifeq (,$(wildcard $(CROSS_CONTAINER)))
docker run --rm dockcross/linux-arm64 > $(CROSS_CONTAINER)
chmod +x $(CROSS_CONTAINER)
endif
all: clean kernel8.img
target/$(TARGET)/debug/kernel8: src/main.rs
RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET)
@ -57,7 +50,7 @@ kernel8: target/$(TARGET)/release/kernel8
endif
kernel8.img: kernel8
$(CROSS_CONTAINER) $(CROSS_CONTAINER_OBJCOPY) -O binary -S $< kernel8.img
$(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img
qemu:
$(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio

@ -80,20 +80,19 @@ should yield something like the following, where you can see that the stack
pointer is not used apart from ourselves setting it.
```bash
./dockcross-linux-aarch64 bash
[andre:/work] $ aarch64-linux-gnu-objdump -CD kernel8
[andre:/work] $ cargo objdump --target aarch64-raspi3-none-elf.json -- -disassemble -print-imm-hex kernel8
[...] (Some output omitted)
0000000000080000 <_boot_cores>:
80000: d53800a8 mrs x8, mpidr_el1
80004: f240051f tst x8, #0x3
80008: 54000060 b.eq 80014 <_boot_cores+0x14>
8000c: d503205f wfe
80010: 17ffffff b 8000c <_boot_cores+0xc>
80014: 320d03e8 orr w8, wzr, #0x80000
80018: 9100011f mov sp, x8
8001c: 9400016b bl 805c8 <raspi3_glue::reset::h2a7ad49cd9d2154d>
_boot_cores:
80000: a8 00 38 d5 mrs x8, MPIDR_EL1
80004: 1f 05 40 f2 tst x8, #0x3
80008: 60 00 00 54 b.eq #0xc
8000c: 5f 20 03 d5 wfe
80010: ff ff ff 17 b #-0x4
80014: e8 03 0d 32 orr w8, wzr, #0x80000
80018: 1f 01 00 91 mov sp, x8
8001c: 5d 01 00 94 bl #0x574
```
It is important to always manually check this, and not blindly rely on the

@ -24,9 +24,8 @@
TARGET = aarch64-raspi3-none-elf
CROSS_CONTAINER = ./dockcross-linux-aarch64
CROSS_CONTAINER_ROOT = /usr/xcc/aarch64-unknown-linux-gnueabi/bin
CROSS_CONTAINER_OBJCOPY = $(CROSS_CONTAINER_ROOT)/aarch64-unknown-linux-gnueabi-objcopy
OBJCOPY = cargo objcopy --
OBJCOPY_PARAMS = --strip-all -O binary
UTILS_CONTAINER = andrerichter/raspi3-utils
DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work
@ -34,13 +33,7 @@ DOCKER_TTY = --privileged -v /dev:/dev
QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img
RASPBOOT_CMD = raspbootcom /dev/ttyUSB0 kernel8.img
all: clean cross_cont_download kernel8.img
cross_cont_download:
ifeq (,$(wildcard $(CROSS_CONTAINER)))
docker run --rm dockcross/linux-arm64 > $(CROSS_CONTAINER)
chmod +x $(CROSS_CONTAINER)
endif
all: clean kernel8.img
target/$(TARGET)/debug/kernel8: src/main.rs
RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET)
@ -57,7 +50,7 @@ kernel8: target/$(TARGET)/release/kernel8
endif
kernel8.img: kernel8
$(CROSS_CONTAINER) $(CROSS_CONTAINER_OBJCOPY) -O binary -S $< kernel8.img
$(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img
qemu:
$(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio

@ -24,9 +24,8 @@
TARGET = aarch64-raspi3-none-elf
CROSS_CONTAINER = ./dockcross-linux-aarch64
CROSS_CONTAINER_ROOT = /usr/xcc/aarch64-unknown-linux-gnueabi/bin
CROSS_CONTAINER_OBJCOPY = $(CROSS_CONTAINER_ROOT)/aarch64-unknown-linux-gnueabi-objcopy
OBJCOPY = cargo objcopy --
OBJCOPY_PARAMS = --strip-all -O binary
UTILS_CONTAINER = andrerichter/raspi3-utils
DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work
@ -34,13 +33,7 @@ DOCKER_TTY = --privileged -v /dev:/dev
QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img
RASPBOOT_CMD = raspbootcom /dev/ttyUSB0 kernel8.img
all: clean cross_cont_download kernel8.img
cross_cont_download:
ifeq (,$(wildcard $(CROSS_CONTAINER)))
docker run --rm dockcross/linux-arm64 > $(CROSS_CONTAINER)
chmod +x $(CROSS_CONTAINER)
endif
all: clean kernel8.img
target/$(TARGET)/debug/kernel8: src/main.rs
RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET)
@ -57,7 +50,7 @@ kernel8: target/$(TARGET)/release/kernel8
endif
kernel8.img: kernel8
$(CROSS_CONTAINER) $(CROSS_CONTAINER_OBJCOPY) -O binary -S $< kernel8.img
$(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img
qemu:
$(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio

@ -24,9 +24,8 @@
TARGET = aarch64-raspi3-none-elf
CROSS_CONTAINER = ./dockcross-linux-aarch64
CROSS_CONTAINER_ROOT = /usr/xcc/aarch64-unknown-linux-gnueabi/bin
CROSS_CONTAINER_OBJCOPY = $(CROSS_CONTAINER_ROOT)/aarch64-unknown-linux-gnueabi-objcopy
OBJCOPY = cargo objcopy --
OBJCOPY_PARAMS = --strip-all -O binary
UTILS_CONTAINER = andrerichter/raspi3-utils
DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work
@ -34,13 +33,7 @@ DOCKER_TTY = --privileged -v /dev:/dev
QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img
RASPBOOT_CMD = raspbootcom /dev/ttyUSB0 kernel8.img
all: clean cross_cont_download kernel8.img
cross_cont_download:
ifeq (,$(wildcard $(CROSS_CONTAINER)))
docker run --rm dockcross/linux-arm64 > $(CROSS_CONTAINER)
chmod +x $(CROSS_CONTAINER)
endif
all: clean kernel8.img
target/$(TARGET)/debug/kernel8: src/main.rs
RUST_TARGET_PATH=$(shell pwd) xargo build --target=$(TARGET)
@ -57,7 +50,7 @@ kernel8: target/$(TARGET)/release/kernel8
endif
kernel8.img: kernel8
$(CROSS_CONTAINER) $(CROSS_CONTAINER_OBJCOPY) -O binary -S $< kernel8.img
$(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img
qemu:
$(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio

@ -24,15 +24,13 @@ This repo tries to put a focus on user friendliness. Therefore, I made some effo
Users eager to try the code should not be bothered with complicated toolchain installation/compilation steps. This is achieved by trying to use the standard Rust toolchain as much as possible, and bridge existing gaps with Docker containers. Please [install Docker for your distro].
The setup consists of the following components:
1. Compiler and linker are used from Rust nightly.
1. Compiler, linker and binutils are used from Rust nightly.
2. QEMU will be used for emulation, but RPi3 support in QEMU is very fresh and has not landed in most of the pre-packaged versions of popular distributions. [This] container will provide it ready to go.
3. aarch64 toolchain binaries that are not provided by Rust, like `objcopy`, will be provided with a container from the [dockcross] project, which does an awesome job of curating various toolchains in containers.
Please notice that you won't need to download or prepare the containers upfront. As long as you have docker installed, they will be pulled automatically the first time the Makefile needs them.
[install Docker for your distro]: https://www.docker.com/community-edition#/download
[This]: https://github.com/andre-richter/docker-raspi3-qemu
[dockcross]: https://github.com/dockcross/dockcross
For now, only a few basic tutorials are ready, but more will be ported over time.
@ -53,29 +51,14 @@ research before you continue. This tutorial is strickly about interfacing with t
I assume you have a fair GNU/Linux knowledge on how to compile programs and create disk and file system images. I
won't cover those in detail, although I'll give you a few hints about how to set up a cross-compiler for this architecture.
Why Raspberry Pi 3?
-------------------
I've choosen this board for several reasons: first of all, it's cheap and easy to get. Second, it's a 64 bit
machine. I gave up programming for 32 bit long long time ago. The 64 bit is so much more interesting, as it's
address space is increadibly huge, bigger than the storage capacity which allows us to use some interesting new
solutions. Third, uses only MMIO which makes it easy to program.
For 32 bit tutorials, I'd recommend:
- [Cambridge tutorials](http://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/) (ASM and 32 bit only),
- [David Welch's tutorials](https://github.com/dwelch67/raspberrypi) (mostly C, with some 64 bit examples),
- [Peter Lemon's tutorials](https://github.com/PeterLemon/RaspberryPi) (ASM only, also for 64 bit) and
- [Leon de Boer's tutorials](https://github.com/LdB-ECM/Raspberry-Pi) (C and ASM, also for 64 bit, more complex examples like USB and OpenGL).
Prerequisites
-------------
Before you can start, you'll need a suitable Rust toolchain.
```bash
curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly
rustup component add rust-src
cargo install xargo
rustup component add rust-src llvm-tools
cargo install xargo cargo-binutils
```
Additionally, a Micro SD card with [firmware files](https://github.com/raspberrypi/firmware/tree/master/boot) on a FAT filesystem.
@ -111,6 +94,22 @@ For that, you would have to add something like `-chardev socket,host=localhost,p
**!!!WARNING!!!** Qemu emulation is rudimentary, only the most common peripherals are emulated! **!!!WARNING!!!**
Why Raspberry Pi 3?
-------------------
I've choosen this board for several reasons: first of all, it's cheap and easy to get. Second, it's a 64 bit
machine. I gave up programming for 32 bit long long time ago. The 64 bit is so much more interesting, as it's
address space is increadibly huge, bigger than the storage capacity which allows us to use some interesting new
solutions. Third, uses only MMIO which makes it easy to program.
For 32 bit tutorials, I'd recommend:
- [Cambridge tutorials](http://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/) (ASM and 32 bit only),
- [David Welch's tutorials](https://github.com/dwelch67/raspberrypi) (mostly C, with some 64 bit examples),
- [Peter Lemon's tutorials](https://github.com/PeterLemon/RaspberryPi) (ASM only, also for 64 bit) and
- [Leon de Boer's tutorials](https://github.com/LdB-ECM/Raspberry-Pi) (C and ASM, also for 64 bit, more complex examples like USB and OpenGL).
About the hardware
------------------

@ -0,0 +1,16 @@
#!/usr/bin/env ruby
crates = Dir["**/Cargo.toml"].sort!
crates.each do |x|
next if x.include?('raspi3_glue')
x = File.dirname(x)
puts "\n\n" + x.to_s + "\n\n"
Dir.chdir(x) do
unless system('make clean')
puts "\n\nBuild failed!"
exit(1) # Exit with error code
end
end
end
Loading…
Cancel
Save