Skip to content

Commit 3ddf6f5

Browse files
committed
TRYBOOT WIP
1 parent 15acc8d commit 3ddf6f5

File tree

3 files changed

+115
-107
lines changed

3 files changed

+115
-107
lines changed

fwup-ops.conf

+39-63
Original file line numberDiff line numberDiff line change
@@ -21,48 +21,6 @@ require-fwup-version="1.0.0"
2121

2222
include("${NERVES_SDK_IMAGES:-.}/fwup_include/fwup-common.conf")
2323

24-
mbr mbr-a {
25-
partition 0 {
26-
block-offset = ${BOOT_A_PART_OFFSET}
27-
block-count = ${BOOT_A_PART_COUNT}
28-
type = 0xc # FAT32
29-
boot = true
30-
}
31-
partition 1 {
32-
block-offset = ${ROOTFS_A_PART_OFFSET}
33-
block-count = ${ROOTFS_A_PART_COUNT}
34-
type = 0x83 # Linux
35-
}
36-
partition 2 {
37-
block-offset = ${APP_PART_OFFSET}
38-
block-count = ${APP_PART_COUNT}
39-
type = 0x83 # Linux
40-
expand = true
41-
}
42-
# partition 3 is unused
43-
}
44-
45-
mbr mbr-b {
46-
partition 0 {
47-
block-offset = ${BOOT_B_PART_OFFSET}
48-
block-count = ${BOOT_B_PART_COUNT}
49-
type = 0xc # FAT32
50-
boot = true
51-
}
52-
partition 1 {
53-
block-offset = ${ROOTFS_B_PART_OFFSET}
54-
block-count = ${ROOTFS_B_PART_COUNT}
55-
type = 0x83 # Linux
56-
}
57-
partition 2 {
58-
block-offset = ${APP_PART_OFFSET}
59-
block-count = ${APP_PART_COUNT}
60-
type = 0x83 # Linux
61-
expand = true
62-
}
63-
# partition 3 is unused
64-
}
65-
6624
# Location where installed firmware information is stored.
6725
# While this is called "u-boot", u-boot isn't involved in this
6826
# setup. It just provides a convenient key/value store format.
@@ -90,28 +48,31 @@ task factory-reset {
9048
##
9149
task prevent-revert.a {
9250
# Check that we're running on B
93-
require-partition-offset(0, ${BOOT_B_PART_OFFSET})
94-
require-partition-offset(1, ${ROOTFS_B_PART_OFFSET})
9551
require-uboot-variable(uboot-env, "nerves_fw_active", "b")
9652

97-
on-init {
53+
on-resource autoboot-b.txt {
9854
info("Preventing reverts to partition A")
55+
# Ensure that autoboot is booting the B partition
56+
fat_write(${AUTOBOOT_PART_OFFSET}, "autoboot.txt")
57+
uboot_setenv(uboot-env, "nerves_fw_validated", "1")
9958
# Remove U-Boot variables that fwup uses to allow reverting images
10059
uboot_unsetenv(uboot-env, "a.nerves_fw_platform")
10160
uboot_unsetenv(uboot-env, "a.nerves_fw_architecture")
61+
uboot_setenv(uboot-env, "nerves_fw_validated", "1")
10262
# Clear out the old image using TRIM. This requires --enable-trim
10363
trim(${ROOTFS_A_PART_OFFSET}, ${ROOTFS_A_PART_COUNT})
10464
trim(${BOOT_A_PART_OFFSET}, ${BOOT_A_PART_COUNT})
10565
}
10666
}
10767
task prevent-revert.b {
10868
# Check that we're running on A
109-
require-partition-offset(0, ${BOOT_A_PART_OFFSET})
110-
require-partition-offset(1, ${ROOTFS_A_PART_OFFSET})
11169
require-uboot-variable(uboot-env, "nerves_fw_active", "a")
11270

113-
on-init {
71+
on-resource autoboot-a.txt {
11472
info("Preventing reverts to partition B")
73+
# Ensure that autoboot is booting the A partition
74+
fat_write(${AUTOBOOT_PART_OFFSET}, "autoboot.txt")
75+
uboot_setenv(uboot-env, "nerves_fw_validated", "1")
11576
# Remove U-Boot variables that fwup uses to allow reverting images
11677
uboot_unsetenv(uboot-env, "b.nerves_fw_platform")
11778
uboot_unsetenv(uboot-env, "b.nerves_fw_architecture")
@@ -131,39 +92,37 @@ task prevent-revert.fail {
13192
##
13293
task revert.a {
13394
# This task reverts to the A partition, so check that we're running on B
134-
require-partition-offset(0, ${BOOT_B_PART_OFFSET})
13595
require-partition-offset(1, ${ROOTFS_B_PART_OFFSET})
13696
require-uboot-variable(uboot-env, "nerves_fw_active", "b")
13797

13898
# Verify that partition A has the expected platform/architecture
13999
require-uboot-variable(uboot-env, "a.nerves_fw_platform", "${NERVES_FW_PLATFORM}")
140100
require-uboot-variable(uboot-env, "a.nerves_fw_architecture", "${NERVES_FW_ARCHITECTURE}")
141101

142-
on-init {
102+
on-resource autoboot-a.txt {
143103
info("Reverting to partition A")
144-
145-
# Switch over
104+
# Update the autoboot first and then the tracking U-Boot variables
105+
fat_write(${AUTOBOOT_PART_OFFSET}, "autoboot.txt")
146106
uboot_setenv(uboot-env, "nerves_fw_active", "a")
147-
mbr_write(mbr-a)
107+
uboot_setenv(uboot-env, "nerves_fw_validated", "1")
148108
}
149109
}
150110

151111
task revert.b {
152112
# This task reverts to the B partition, so check that we're running on A
153-
require-partition-offset(0, ${BOOT_A_PART_OFFSET})
154-
require-partition-offset(1, ${ROOTFS_A_PART_OFFSET})
113+
require-path-at-offset("/", ${ROOTFS_A_PART_OFFSET})
155114
require-uboot-variable(uboot-env, "nerves_fw_active", "a")
156115

157116
# Verify that partition B has the expected platform/architecture
158117
require-uboot-variable(uboot-env, "b.nerves_fw_platform", "${NERVES_FW_PLATFORM}")
159118
require-uboot-variable(uboot-env, "b.nerves_fw_architecture", "${NERVES_FW_ARCHITECTURE}")
160119

161-
on-init {
120+
on-resource autoboot-b.txt {
162121
info("Reverting to partition B")
163-
164-
# Switch over
122+
# Update the autoboot first and then the tracking U-Boot variables
123+
fat_write(${AUTOBOOT_PART_OFFSET}, "autoboot.txt")
165124
uboot_setenv(uboot-env, "nerves_fw_active", "b")
166-
mbr_write(mbr-b)
125+
uboot_setenv(uboot-env, "nerves_fw_validated", "1")
167126
}
168127
}
169128

@@ -222,11 +181,28 @@ task status.fail {
222181
##
223182
# validate
224183
#
225-
# The fwup configuration for this device always validates, so this doesn't do anything.
184+
# Update the autoboot.txt file to unconditionally boot the active partition.
226185
##
227-
task validate {
228-
on-init {
229-
info("Validate")
186+
task validate.a {
187+
require-path-at-offset("/", ${ROOTFS_A_PART_OFFSET})
188+
require-uboot-variable(uboot-env, "nerves_fw_active", "a")
189+
190+
on-resource autoboot-a.txt {
191+
info("Validate A")
192+
fat_write(${AUTOBOOT_PART_OFFSET}, "autoboot.txt")
193+
uboot_setenv(uboot-env, "nerves_fw_validated", "1")
194+
}
195+
}
196+
task validate.b {
197+
require-path-at-offset("/", ${ROOTFS_B_PART_OFFSET})
198+
require-uboot-variable(uboot-env, "nerves_fw_active", "b")
199+
200+
on-resource autoboot-b.txt {
201+
info("Validate B")
202+
fat_write(${AUTOBOOT_PART_OFFSET}, "autoboot.txt")
230203
uboot_setenv(uboot-env, "nerves_fw_validated", "1")
231204
}
232205
}
206+
task validate.fail {
207+
on-init { error("Can't validate unless running from active partition") }
208+
}

fwup.conf

+36-28
Original file line numberDiff line numberDiff line change
@@ -75,46 +75,45 @@ file-resource hifiberry-dac.dtbo {
7575
host-path = "${NERVES_SYSTEM}/images/rpi-firmware/overlays/hifiberry-dac.dtbo"
7676
}
7777

78-
mbr mbr-a {
78+
mbr mbr {
7979
partition 0 {
80-
block-offset = ${BOOT_A_PART_OFFSET}
81-
block-count = ${BOOT_A_PART_COUNT}
80+
block-offset = ${AUTOBOOT_PART_OFFSET}
81+
block-count = ${AUTOBOOT_PART_COUNT}
8282
type = 0xc # FAT32
8383
boot = true
8484
}
8585
partition 1 {
86-
block-offset = ${ROOTFS_A_PART_OFFSET}
87-
block-count = ${ROOTFS_A_PART_COUNT}
88-
type = 0x83 # Linux
86+
block-offset = ${BOOT_A_PART_OFFSET}
87+
block-count = ${BOOT_A_PART_COUNT}
88+
type = 0xc # FAT32
89+
boot = true
8990
}
9091
partition 2 {
91-
block-offset = ${APP_PART_OFFSET}
92-
block-count = ${APP_PART_COUNT}
93-
type = 0x83 # Linux
94-
expand = true
95-
}
96-
# partition 3 is unused
97-
}
98-
99-
mbr mbr-b {
100-
partition 0 {
10192
block-offset = ${BOOT_B_PART_OFFSET}
10293
block-count = ${BOOT_B_PART_COUNT}
10394
type = 0xc # FAT32
10495
boot = true
10596
}
106-
partition 1 {
97+
partition 3 {
98+
type = 0xf # Extended partition
99+
block-offset = ${EXTENDED_PART_OFFSET}
100+
}
101+
partition 4 {
102+
block-offset = ${ROOTFS_A_PART_OFFSET}
103+
block-count = ${ROOTFS_A_PART_COUNT}
104+
type = 0x83 # Linux
105+
}
106+
partition 5 {
107107
block-offset = ${ROOTFS_B_PART_OFFSET}
108108
block-count = ${ROOTFS_B_PART_COUNT}
109109
type = 0x83 # Linux
110110
}
111-
partition 2 {
111+
partition 6 {
112112
block-offset = ${APP_PART_OFFSET}
113113
block-count = ${APP_PART_COUNT}
114114
type = 0x83 # Linux
115115
expand = true
116116
}
117-
# partition 3 is unused
118117
}
119118

120119
# Location where installed firmware information is stored.
@@ -131,7 +130,7 @@ task complete {
131130
require-unmounted-destination = true
132131

133132
on-init {
134-
mbr_write(mbr-a)
133+
mbr_write(mbr)
135134

136135
fat_mkfs(${BOOT_A_PART_OFFSET}, ${BOOT_A_PART_COUNT})
137136
fat_setlabel(${BOOT_A_PART_OFFSET}, "BOOT-A")
@@ -157,6 +156,11 @@ task complete {
157156
uboot_setenv(uboot-env, "a.nerves_fw_uuid", "\${FWUP_META_UUID}")
158157
}
159158

159+
on-resource autoboot-a.txt {
160+
fat_mkfs(${AUTOBOOT_PART_OFFSET}, ${AUTOBOOT_PART_COUNT})
161+
fat_setlabel(${AUTOBOOT_PART_OFFSET}, "AUTOBOOT")
162+
fat_write(${AUTOBOOT_PART_OFFSET}, "autoboot.txt")
163+
}
160164
on-resource config.txt { fat_write(${BOOT_A_PART_OFFSET}, "config.txt") }
161165
on-resource cmdline.txt { fat_write(${BOOT_A_PART_OFFSET}, "cmdline.txt") }
162166
on-resource bootcode.bin { fat_write(${BOOT_A_PART_OFFSET}, "bootcode.bin") }
@@ -200,7 +204,11 @@ task complete {
200204

201205
task upgrade.a {
202206
# This task upgrades the A partition
203-
require-partition-offset(1, ${ROOTFS_B_PART_OFFSET})
207+
require-uboot-variable(uboot-env, "nerves_fw_active", "b")
208+
209+
# Require that the running version of firmware has been validated.
210+
# If it has not, then failing back is not guaranteed to work.
211+
require-uboot-variable(uboot-env, "nerves_fw_validated", "1")
204212

205213
# Verify the expected platform/architecture
206214
require-uboot-variable(uboot-env, "b.nerves_fw_platform", "${NERVES_FW_PLATFORM}")
@@ -226,9 +234,7 @@ task upgrade.a {
226234
trim(${ROOTFS_A_PART_OFFSET}, ${ROOTFS_A_PART_COUNT})
227235
}
228236

229-
# Write the new boot partition files and rootfs. The MBR still points
230-
# to the B partition, so an error or power failure during this part
231-
# won't hurt anything.
237+
# Write the new boot partition files and rootfs.
232238
on-resource config.txt { fat_write(${BOOT_A_PART_OFFSET}, "config.txt") }
233239
on-resource cmdline.txt { fat_write(${BOOT_A_PART_OFFSET}, "cmdline.txt") }
234240
on-resource bootcode.bin { fat_write(${BOOT_A_PART_OFFSET}, "bootcode.bin") }
@@ -273,16 +279,19 @@ task upgrade.a {
273279

274280
# Switch over to boot the new firmware
275281
uboot_setenv(uboot-env, "nerves_fw_active", "a")
276-
mbr_write(mbr-a)
277282
}
278283

279284
on-error {
280285
}
281286
}
282287

283288
task upgrade.b {
284-
# This task upgrades the B partition
285-
require-partition-offset(1, ${ROOTFS_A_PART_OFFSET})
289+
# This task upgrades the A partition
290+
require-uboot-variable(uboot-env, "nerves_fw_active", "a")
291+
292+
# Require that the running version of firmware has been validated.
293+
# If it has not, then failing back is not guaranteed to work.
294+
require-uboot-variable(uboot-env, "nerves_fw_validated", "1")
286295

287296
# Verify the expected platform/architecture
288297
require-uboot-variable(uboot-env, "a.nerves_fw_platform", "${NERVES_FW_PLATFORM}")
@@ -353,7 +362,6 @@ task upgrade.b {
353362

354363
# Switch over to boot the new firmware
355364
uboot_setenv(uboot-env, "nerves_fw_active", "b")
356-
mbr_write(mbr-b)
357365
}
358366

359367
on-error {

fwup_include/fwup-common.conf

+40-16
Original file line numberDiff line numberDiff line change
@@ -33,41 +33,46 @@ define(ROOTFS, "${NERVES_SYSTEM}/images/rootfs.squashfs")
3333
# | Firmware configuration data|
3434
# | (formatted as uboot env) |
3535
# +----------------------------+
36-
# | p0*: Boot A (FAT32) |
36+
# | p0: Autoboot (FAT32) |
37+
# +----------------------------+
38+
# | p1: Boot A (FAT32) |
3739
# | zImage, bootcode.bin, |
3840
# | config.txt, etc. |
3941
# +----------------------------+
40-
# | p0*: Boot B (FAT32) |
42+
# | p2: Boot B (FAT32) |
4143
# +----------------------------+
42-
# | p1*: Rootfs A (squashfs) |
44+
# | p3: Extended partition |
4345
# +----------------------------+
44-
# | p1*: Rootfs B (squashfs) |
46+
# | p4: Rootfs A (squashfs) |
4547
# +----------------------------+
46-
# | p2: Application (ext4) |
48+
# | p5: Rootfs B (squashfs) |
49+
# +----------------------------+
50+
# | p6: Application (ext4) |
4751
# +----------------------------+
48-
#
49-
# The p0/p1 partition points to whichever of configurations A or B that is
50-
# active.
5152
#
5253
# The image is sized to be less than 1 GB so that it fits on nearly any SDCard
5354
# around. If you have a larger SDCard and need more space, feel free to bump
5455
# the partition sizes below.
5556

56-
# The Raspberry Pi is incredibly picky on the partition sizes and in ways that
57-
# I don't understand. Test changes one at a time to make sure that they boot.
58-
# (Sizes are in 512 byte blocks)
5957
define(UBOOT_ENV_OFFSET, 16)
6058
define(UBOOT_ENV_COUNT, 16) # 8 KB
6159

62-
define(BOOT_A_PART_OFFSET, 63)
63-
define(BOOT_A_PART_COUNT, 38630)
60+
# Even though non-FAT32 partitions appear to work, make sure all partitions are
61+
# at least 65,525 blocks long to force FAT32. See
62+
# https://forums.raspberrypi.com/viewtopic.php?p=1505893&hilit=genimage#p1506378..
63+
define(AUTOBOOT_PART_OFFSET, 128)
64+
define(AUTOBOOT_PART_COUNT, 65536)
65+
66+
define-eval(BOOT_A_PART_OFFSET, "${AUTOBOOT_PART_OFFSET} + ${AUTOBOOT_PART_COUNT}")
67+
define(BOOT_A_PART_COUNT, 65536)
6468
define-eval(BOOT_B_PART_OFFSET, "${BOOT_A_PART_OFFSET} + ${BOOT_A_PART_COUNT}")
6569
define(BOOT_B_PART_COUNT, ${BOOT_A_PART_COUNT})
70+
define-eval(EXTENDED_PART_OFFSET, "${BOOT_B_PART_OFFSET} + ${BOOT_B_PART_COUNT}")
6671

67-
# Let the rootfs have room to grow up to 128 MiB and align it to the nearest 1
72+
# Let the rootfs have room to grow up to 256 MiB and align it to the nearest 1
6873
# MB boundary
69-
define(ROOTFS_A_PART_OFFSET, 77324)
70-
define(ROOTFS_A_PART_COUNT, 289044)
74+
define(ROOTFS_A_PART_OFFSET, 198656)
75+
define(ROOTFS_A_PART_COUNT, 524288)
7176
define-eval(ROOTFS_B_PART_OFFSET, "${ROOTFS_A_PART_OFFSET} + ${ROOTFS_A_PART_COUNT}")
7277
define(ROOTFS_B_PART_COUNT, ${ROOTFS_A_PART_COUNT})
7378

@@ -85,3 +90,22 @@ meta-architecture = ${NERVES_FW_ARCHITECTURE}
8590
meta-author = ${NERVES_FW_AUTHOR}
8691
meta-vcs-identifier = ${NERVES_FW_VCS_IDENTIFIER}
8792
meta-misc = ${NERVES_FW_MISC}
93+
94+
file-resource autoboot-a.txt {
95+
contents = "\
96+
[all]\n\
97+
tryboot_a_b=1\n\
98+
boot_partition=2\n\
99+
[tryboot]\n\
100+
boot_partition=3\n\
101+
\n"
102+
}
103+
file-resource autoboot-b.txt {
104+
contents = "\
105+
[all]\n\
106+
tryboot_a_b=1\n\
107+
boot_partition=3\n\
108+
[tryboot]\n\
109+
boot_partition=2\n\
110+
\n"
111+
}

0 commit comments

Comments
 (0)