Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update and enhance to latest Raspberry Pi OS 32/64bit #16

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
152 changes: 62 additions & 90 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ The boot chain on the Raspberry Pi:

```
+-----------------+ +------------------------+
| first-stage | | Raspbian |
| first-stage | | Raspberry Pi OS |
| bootloader |------------------------------------------\| Linux Kernel |
| |------------------------------------------/| |
| (closed-source) | | (built-in TPM support) |
Expand All @@ -40,7 +40,7 @@ What we want to achieve

```
+-----------------+ +-------------------------+ +------------------------+
| first-stage | | second-stage bootloader | | Raspbian |
| first-stage | | second-stage bootloader | | Raspberry Pi OS |
| bootloader |-------\| U-Boot |-------\| Linux Kernel |
| |-------/| |-------/| |
| (closed-source) | | (built-in TPM support) | | (built-in TPM support) |
Expand All @@ -49,19 +49,25 @@ What we want to achieve

## Preparing your Raspberry Pi

Get the headless Raspbian image.
Get the Raspberry Pi OS 64bit image.

```bash
wget -O raspian_latest.zip https://downloads.raspberrypi.org/raspbian_lite_latest
unzip raspbian_lastest.zip
wget -O raspios_latest.img.xz https://downloads.raspberrypi.org/raspios_arm64_latest
```

Get the Raspberry Pi OS 32bit image.

```bash
wget -O raspios_latest.img.xz https://downloads.raspberrypi.org/raspios_armhf_latest
```

Check the character device name of your SD card with `lsblk` if needed. Plug
your SD card in, unmount its partition if necessary and flash the Raspbian image
onto the card:
your SD card in, unmount its partition if necessary and flash the Raspberry Pi OS
image onto the card:

```bash
sudo dd if=2020-02-13-raspbian-buster-lite.img of=/dev/mmcblk0 bs=4M status=progress conv=fsync
unxz -T 0 raspios_latest.img.xz
sudo dd if=raspios_latest.img of=/dev/mmcblk0 bs=4M status=progress conv=fsync
```

Done. But don't unplug your SD just yet. There should be two partitions on the
Expand All @@ -74,71 +80,26 @@ There are various options. I chose the [Lets Trust TPM](https://buyzero.de/colle

## Getting a Cross-Compiler

We are on an `ARMv8-A` processor and want to compile 64 bit software, i.e.
the architecture we want to build for is `aarch64`/`arm64`.
We are on an `ARMv8-A` processor and want to compile 64 bit or 32 bit software, i.e.
the architecture we want to build for is `aarch64`/`arm64` or `arm`/`arm32`.

This means, we need the `aarch64-linux-gnu` toolchain. You can build it yourself
and add it to your `$PATH` or [install
This means, we need the `aarch64-linux-gnu` or `arm-linux-gnu` toolchain. You can build it
yourself and add it to your `$PATH` or [install
it](https://www.archlinux.org/packages/community/x86_64/aarch64-linux-gnu-gcc/)
with your superiour Linux distro's package manager.

Check if your toolchain is working:
Check if your toolchain for 64bit is working:

``` bash
aarch64-linux-gnu-gcc --version
```

## Getting a 64 Bit Kernel

You have two options:
* Option A) Build the kernel yourself
* Option B) Update your 32 bit kernel to 64 bit

In any case we need to tell our bootloader to load the kernel in 64 bit mode.
We simply add the following line to `config.txt` on the boot partition.

```ini
arm_64bit=1
```

### Option A) Building the 64 Bit Kernel

Build the kernel on your developer machine:

```bash
git clone https://github.com/raspberrypi/linux
cd linux
make O=result ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
make O=result ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
```
Check if your toolchain for 32bit is working:

That's it! Make sure the root partition on your SD card is mounted (for me:
`/run/media/johannes/rootfs`). To copy the newly built kernel, its modules,
device tree and overlays:

```bash
sudo env PATH=$PATH make O=result ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=/run/media/johannes/rootfs modules_install

KERNEL=kernel8.img
sudo cp /run/media/johannes/boot/$KERNEL /run/media/johannes/boot/$KERNEL.bak
sudo cp result/arch/arm64/boot/Image /run/media/johannes/boot/$KERNEL
sudo cp result/arch/arm64/boot/dts/broadcom/*.dtb /run/media/johannes/boot/
sudo cp result/arch/arm64/boot/dts/overlays/*.dtb* /run/media/johannes/boot/overlays/
```

Since we still need to add U-Boot, don't unplug your card, yet.

### Option B) Updating your 32 Bit Kernel to 64 Bit

Alternatively, you can instruct your Raspberry to perform a kernel update and reboot.

```
sudo rpi-update
sudo reboot
``` bash
arm-linux-gnu-gcc --version
```

After the reboot, shut your Raspbian off and plug in the SD card to your PC.

## Building U-Boot

The Raspberry Pi talks to the TPM via SPI. Now here's the catch:
Expand All @@ -148,20 +109,26 @@ cannot use the SPI hardware controller with U-Boot. However, we can use a
software SPI driver which uses GPIO to *bit bang* the data to the TPM. Luckily
for us, U-Boot provides a ready-to-use driver exactly for that.

~~Yes, there is a second catch: this driver does not support the SPI mode 0
(CPOL=0/CPHA=0) which we need. We can work around this, but I'll come to that
later~~

### Setting up and Configuring

Clone the repository and create a the Raspberry Pi 4 default configuration.

Clone the repository
``` bash
git clone https://gitlab.denx.de/u-boot/u-boot.git
cd u-boot
```

Create the Raspberry Pi 4 default configuration for 64bit.
(Same for Raspberry Pi 3B)
``` bash
make -j$(nproc) CROSS_COMPILE=aarch64-linux-gnu- rpi_4_defconfig
```

Create the Raspberry Pi 4 default configuration for 32bit.
(Raspberry Pi 3B needs rpi_3_32b_defconfig)
``` bash
make -j$(nproc) CROSS_COMPILE=arm-linux-gnu- rpi_4_32b_defconfig
```

The configuration is saved in `.config`. Now, we need to change some things.
Similar to the Linux kernel, there is an interactive tool for configuring.

Expand Down Expand Up @@ -192,52 +159,58 @@ Save to `.config` and exit the menu.

Note: in this menu, you can also enable logging for troubleshooting.

### Patching and Building

**Update**: the patches
[[1]](https://gitlab.denx.de/u-boot/u-boot/-/commit/0e146993bb3da59d2c52515048405444f35f00ec),[[2]](https://gitlab.denx.de/u-boot/u-boot/-/commit/bedbb383e1bf5777386c885950f7fb0a21b0daa2)
were upstreamed and are part of mainline as of 2020/07/09. Thus, patching is not
necessary anymore.

~~Remember how I said that we need to work around the problem of our SPI driver
not being able to operate at SPI mode 0? Now is the time.~~

~~Secondly, there is a compile-time bug. Just apply these two patches. (If the
patches do not apply, call `git checkout 7dbafe06` first.)~~


~~`git apply /path/to/dm-spi-fix-CPHA-and-implement-CPOL-for-soft-spi.diff`~~

~~`git apply /path/to/fix_compile_time_bug.diff`~~

Now you can build U-Boot.
### Building

Raspberry Pi OS 64bit:
```bash
make -j$(nproc) CROSS_COMPILE=aarch64-linux-gnu- all
```

Raspberry Pi OS 32bit:
```bash
make -j$(nproc) CROSS_COMPILE=arm-linux-gnu- all
```

### Creating the Boot Script

The most important result is `u-boot.bin`, our second stage bootloader. However,
to tell what to do (which kernel to load etc.), we need a second script-like
file.

Raspberry Pi OS 64bit:
Copy this into a file named `boot.scr`. Note that we specify the kernel which is
to be booted by U-Boot later (`kernel8.img`).

(Same for Raspberry Pi 3B)
```
setenv kernel_comp_addr_r 0x0A000000
setenv kernel_comp_size 8194604
fdt addr ${fdt_addr} && fdt get value bootargs /chosen bootargs
fatload mmc 0:1 ${kernel_addr_r} kernel8.img
booti ${kernel_addr_r} - ${fdt_addr}
```

Raspberry Pi OS 32bit:
Copy this into a file named `boot.scr`. Note that we specify the kernel which is
to be booted by U-Boot later (`kernel7l.img`).
(On Raspberry Pi 3B U-Boot boots `kernel7.img`)
```
fdt addr ${fdt_addr} && fdt get value bootargs /chosen bootargs
fatload mmc 0:1 ${kernel_addr_r} kernel7l.img
bootz ${kernel_addr_r} - ${fdt_addr}
```

This boot script needs to be converted into a binary format which U-Boot can
parse. We call that file `boot.scr.uimg`.

Raspberry Pi OS 64bit:
```bash
./tools/mkimage -A arm64 -T script -C none -n "Boot script" -d boot.scr boot.scr.uimg
```

Raspberry Pi OS 32bit:
```bash
./tools/mkimage -A arm -T script -C none -n "Boot script" -d boot.scr boot.scr.uimg
```

### TPM Device Overlay

The last thing U-Boot needs is a description of the hardware (e.g. which pins is
Expand Down Expand Up @@ -348,8 +321,6 @@ our TPM device tree overlay and load U-Boot instead of the Linux kernel. Make
sure the following lines are in `config.txt`:

```ini
arm_64bit=1

dtparam=spi=on
dtoverlay=tpm-soft-spi

Expand All @@ -375,6 +346,7 @@ commands:
```
tpm2 init
tpm2 startup TPM2_SU_CLEAR
tpm2 info
tpm2 get_capability 0x6 0x106 0x200 2
```

Expand Down
Loading