-
-
Notifications
You must be signed in to change notification settings - Fork 63
/
Copy pathREADME.md
225 lines (192 loc) · 6.97 KB
/
README.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# raspberry-pi-nix
The primary goal of this flake is to make it easy to create
working NixOS configurations for Raspberry Pi products. Specifically,
this repository aims to deliver the following benefits:
1. Configure the kernel, device tree, and boot loader in a way that is
compatible with the hardware and proprietary firmware.
2. Provide a nix interface to Raspberry Pi/device tree configuration
that will be familiar to those who have used Raspberry Pi's
[config.txt based
configuration](https://www.raspberrypi.com/documentation/computers/config_txt.html).
3. Make it easy to build an image suitable for flashing to an sd-card,
without the need to first go through an installation media.
The important modules are `overlay/default.nix`, `rpi/default.nix`,
and `rpi/config.nix`. The other modules are mostly wrappers that set
`config.txt` settings and enable required kernel modules.
## Stability note
`master` is the development branch -- if you want to avoid breaking changes, you
should pin your flake to a specific release and refer to the release notes when
upgrading.
## Example
See the `rpi-example` config in this flake for an example config built by CI.
## Using the provided cache to avoid compiling linux
This repo uses the raspberry pi linux kernel fork, and compiling linux takes a
while. CI pushes kernel builds to the nix-community cachix cache that you may
use to avoid compiling linux yourself. The cache can be found at
https://nix-community.cachix.org, and you can follow the instructions there
to use this cache.
## Building an sd-card image
Include the provided `sd-image` nixos module this flake provides, then an image
suitable for flashing to an sd-card can be found at the attribute
`config.system.build.sdImage`. For example, if you wanted to build an image for
`rpi-example` in the above configuration example you could run:
```
nix build '.#nixosConfigurations.rpi-example.config.system.build.sdImage'
```
## The firmware partition
The image produced by this package is partitioned in the same way as the aarch64
installation media from nixpkgs: There is a firmware partition that contains
necessary firmware, the kernel or u-boot, and config.txt. Then there is another
partition (labeled `NIXOS_SD`) that contains everything else. The firmware and
`config.txt` file are managed by NixOS modules defined in this
package. Additionally, a systemd service will update the firmware and
`config.txt` in the firmware partition __in place__. If uboot is enabled then
linux kernels are stored in the `NIXOS_SD` partition and will be booted by
u-boot in the firmware partition.
## `config.txt` generation
As noted, the `config.txt` file is generated by the NixOS
configuration and automatically updated on when the nix configuration
is modified.
The relevant nixos option is
`hardware.raspberry-pi.config`. Configuration is partitioned into
three sections:
1. Base device tree parameters `base-dt-params`
2. Device tree overlays `dt-overlays`
3. Firmware options `options`
Other than that, the format follows pretty closely to the config.txt
format. For example:
```nix
hardware.raspberry-pi.config = {
cm4 = {
options = {
otg_mode = {
enable = true;
value = true;
};
};
};
pi4 = {
options = {
arm_boost = {
enable = true;
value = true;
};
};
dt-overlays = {
vc4-kms-v3d = {
enable = true;
params = { cma-512 = { enable = true; }; };
};
};
};
all = {
options = {
# The firmware will start our u-boot binary rather than a
# linux kernel.
kernel = {
enable = true;
value = "u-boot-rpi-arm64.bin";
};
arm_64bit = {
enable = true;
value = true;
};
enable_uart = {
enable = true;
value = true;
};
avoid_warnings = {
enable = true;
value = true;
};
camera_auto_detect = {
enable = true;
value = true;
};
display_auto_detect = {
enable = true;
value = true;
};
disable_overscan = {
enable = true;
value = true;
};
};
dt-overlays = {
vc4-kms-v3d = {
enable = true;
params = { };
};
};
base-dt-params = {
krnbt = {
enable = true;
value = "on";
};
spi = {
enable = true;
value = "on";
};
};
};
};
```
generates the following config.txt:
```
# This is a generated file. Do not edit!
[all]
arm_64bit=1
avoid_warnings=1
camera_auto_detect=1
disable_overscan=1
display_auto_detect=1
enable_uart=1
kernel=u-boot-rpi-arm64.bin
dtparam=krnbt=on
dtparam=spi=on
dtoverlay=vc4-kms-v3d
dtoverlay=
[cm4]
otg_mode=1
[pi4]
arm_boost=1
dtoverlay=vc4-kms-v3d
dtparam=cma-512
dtoverlay=
```
If you want to preview the generated `config.txt`, you can find
it at the path `config.hardware.raspberry-pi.config-output`. For
example, if you had the above configuration then you could build the
`config.txt` file with:
```
nix build '.#nixosConfigurations.rpi-example.config.hardware.raspberry-pi.config-output'
```
## Firmware partition implementation notes
In Raspberry Pi devices the proprietary firmware manipulates the device tree in
a number of ways before handing it off to the kernel (or in our case, to
u-boot). The transformations that are performed aren't documented so well
(although I have found [this
list](https://forums.raspberrypi.com/viewtopic.php?t=329799#p1974233) ).
This manipulation makes it difficult to use the device tree configured directly
by NixOS as the proprietary firmware's manipulation must be known and
reproduced.
Even if the manipulation were successfully reproduced, some benefits would be
lost. For example, the firmware can detect connected hardware during boot and
automatically configure the device tree accordingly before passing it onto the
kernel. If this firmware device tree is ignored then a NixOS system rebuild with
a different device tree would be required when swapping connected
hardware. Examples of what I mean by hardware include: the specific Raspberry Pi
device booting the image, connected cameras, and connected displays.
So, in order to avoid the headaches associated with failing to reproduce some
firmware device tree manipulation, and to reap the benefits afforded by the
firmware device tree configuration, the bootloader is configured to use the
device tree that it is given (i.e. the one that the raspberry pi firmware loads
and manipulates). As a consequence, device tree configuration is controlled via
the [config.txt
file](https://www.raspberrypi.com/documentation/computers/config_txt.html).
Additionally, the firmware, device trees, and overlays from the `raspberrypifw`
package populate the firmware partition. This package is kept up to date by the
overlay applied by this package, so you don't need configure this. However, if
you want to use different firmware you can override that package to do so.
## What's not working?
- [ ] Pi 5 u-boot devices other than sd-cards (i.e. usb, nvme).