@@ -5,15 +5,16 @@ use std::fs;
5
5
use camino:: Utf8Path ;
6
6
use clap:: Parser ;
7
7
use rugpi_common:: {
8
+ boot:: { uboot:: UBootEnv , BootFlow } ,
8
9
loop_dev:: LoopDevice ,
9
10
mount:: Mounted ,
10
11
partitions:: { get_disk_id, mkfs_ext4, mkfs_vfat, sfdisk_apply_layout, sfdisk_image_layout} ,
11
- patch_cmdline , patch_config, Anyhow ,
12
+ patch_boot , patch_config, Anyhow ,
12
13
} ;
13
14
use tempdir:: TempDir ;
14
15
use xscript:: { run, Run } ;
15
16
16
- use crate :: config:: load_config;
17
+ use crate :: config:: { load_config, BakeryConfig , IncludeFirmware } ;
17
18
18
19
#[ derive( Debug , Parser ) ]
19
20
pub struct BakeTask {
@@ -39,35 +40,58 @@ pub fn run(task: &BakeTask) -> Anyhow<()> {
39
40
mkfs_vfat ( loop_device. partition ( 1 ) , "CONFIG" ) ?;
40
41
mkfs_vfat ( loop_device. partition ( 2 ) , "BOOT-A" ) ?;
41
42
mkfs_ext4 ( loop_device. partition ( 5 ) , "system-a" ) ?;
42
- let temp_dir = TempDir :: new ( "rugpi" ) ?;
43
- let temp_dir_path = Utf8Path :: from_path ( temp_dir. path ( ) ) . unwrap ( ) ;
44
- {
45
- let _mounted_root = Mounted :: mount ( loop_device. partition ( 5 ) , temp_dir_path) ?;
46
- let boot_dir = temp_dir_path. join ( "boot" ) ;
47
- fs:: create_dir_all ( & boot_dir) ?;
48
- let _mounted_boot = Mounted :: mount ( loop_device. partition ( 2 ) , & boot_dir) ?;
49
- println ! ( "Writing system files..." ) ;
50
- run ! ( [ "tar" , "-x" , "-f" , & task. archive, "-C" , temp_dir_path] ) ?;
51
- println ! ( "Patching `cmdline.txt`..." ) ;
52
- patch_cmdline (
53
- boot_dir. join ( "cmdline.txt" ) ,
54
- format ! ( "PARTUUID={disk_id}-05" ) ,
55
- ) ?;
56
- println ! ( "Patching `config.txt`..." ) ;
57
- patch_config ( boot_dir. join ( "config.txt" ) ) ?;
43
+ let root_dir = TempDir :: new ( "rugpi" ) ?;
44
+ let root_dir_path = Utf8Path :: from_path ( root_dir. path ( ) ) . unwrap ( ) ;
45
+ let mounted_root = Mounted :: mount ( loop_device. partition ( 5 ) , root_dir_path) ?;
46
+ let mut boot_dir = root_dir_path. join ( "boot" ) ;
47
+ let boot_firmware_dir = boot_dir. join ( "firmware" ) ;
48
+ if boot_firmware_dir. exists ( ) {
49
+ boot_dir = boot_firmware_dir;
58
50
}
59
- {
60
- let _mounted_config = Mounted :: mount ( loop_device. partition ( 1 ) , temp_dir_path) ?;
61
- run ! ( [ "cp" , "-rTp" , "/usr/share/rugpi/files/config" , temp_dir_path] ) ?;
62
- match config. include_firmware {
63
- crate :: config:: IncludeFirmware :: None => { /* Do not include any firmware. */ }
64
- crate :: config:: IncludeFirmware :: Pi4 => include_pi4_firmware ( & temp_dir_path) ?,
65
- crate :: config:: IncludeFirmware :: Pi5 => include_pi5_firmware ( & temp_dir_path) ?,
66
- }
51
+ fs:: create_dir_all ( & boot_dir) ?;
52
+ let mounted_boot = Mounted :: mount ( loop_device. partition ( 2 ) , & boot_dir) ?;
53
+ let config_dir = TempDir :: new ( "rugpi" ) ?;
54
+ let config_dir_path = Utf8Path :: from_path ( config_dir. path ( ) ) . unwrap ( ) ;
55
+ let mounted_config = Mounted :: mount ( loop_device. partition ( 1 ) , & config_dir_path) ?;
56
+ let ctx = BakeCtx {
57
+ config,
58
+ mounted_boot,
59
+ mounted_root,
60
+ mounted_config,
61
+ } ;
62
+
63
+ run ! ( [ "tar" , "-x" , "-f" , & task. archive, "-C" , root_dir_path] ) ?;
64
+ println ! ( "Patching boot configuration..." ) ;
65
+ patch_boot ( ctx. mounted_boot . path ( ) , format ! ( "PARTUUID={disk_id}-05" ) ) ?;
66
+ println ! ( "Patching `config.txt`..." ) ;
67
+ patch_config ( boot_dir. join ( "config.txt" ) ) ?;
68
+
69
+ match ctx. config . boot_flow {
70
+ BootFlow :: Tryboot => setup_tryboot_boot_flow ( & ctx) ?,
71
+ BootFlow :: UBoot => setup_uboot_boot_flow ( & ctx) ?,
72
+ }
73
+
74
+ std:: fs:: copy (
75
+ "/usr/share/rugpi/boot/u-boot/bin/second.scr" ,
76
+ ctx. mounted_boot . path ( ) . join ( "second.scr" ) ,
77
+ ) ?;
78
+
79
+ match ctx. config . include_firmware {
80
+ IncludeFirmware :: None => { /* Do not include any firmware. */ }
81
+ IncludeFirmware :: Pi4 => include_pi4_firmware ( & root_dir_path) ?,
82
+ IncludeFirmware :: Pi5 => include_pi5_firmware ( & root_dir_path) ?,
67
83
}
68
84
Ok ( ( ) )
69
85
}
70
86
87
+ struct BakeCtx {
88
+ config : BakeryConfig ,
89
+ mounted_boot : Mounted ,
90
+ #[ allow( unused) ]
91
+ mounted_root : Mounted ,
92
+ mounted_config : Mounted ,
93
+ }
94
+
71
95
fn calculate_image_size ( archive : & Utf8Path ) -> Anyhow < u64 > {
72
96
let archive_bytes = fs:: metadata ( archive) ?. len ( ) ;
73
97
let total_bytes = archive_bytes + ( 256 + 128 + 128 ) * 1024 * 1024 ;
@@ -76,6 +100,54 @@ fn calculate_image_size(archive: &Utf8Path) -> Anyhow<u64> {
76
100
Ok ( actual_blocks * 4096 )
77
101
}
78
102
103
+ fn setup_tryboot_boot_flow ( ctx : & BakeCtx ) -> Anyhow < ( ) > {
104
+ run ! ( [
105
+ "cp" ,
106
+ "-rTp" ,
107
+ "/usr/share/rugpi/boot/tryboot" ,
108
+ ctx. mounted_config. path( )
109
+ ] ) ?;
110
+ Ok ( ( ) )
111
+ }
112
+
113
+ fn setup_uboot_boot_flow ( ctx : & BakeCtx ) -> Anyhow < ( ) > {
114
+ run ! ( [
115
+ "cp" ,
116
+ "-rTp" ,
117
+ ctx. mounted_boot. path( ) ,
118
+ ctx. mounted_config. path( )
119
+ ] ) ?;
120
+ std:: fs:: remove_file ( & ctx. mounted_config . path ( ) . join ( "kernel8.img" ) ) ?;
121
+ std:: fs:: copy (
122
+ "/usr/share/rugpi/boot/u-boot/arm64_config.txt" ,
123
+ ctx. mounted_config . path ( ) . join ( "config.txt" ) ,
124
+ ) ?;
125
+ std:: fs:: copy (
126
+ "/usr/share/rugpi/boot/u-boot/bin/u-boot-arm64.bin" ,
127
+ ctx. mounted_config . path ( ) . join ( "u-boot-arm64.bin" ) ,
128
+ ) ?;
129
+ std:: fs:: copy (
130
+ "/usr/share/rugpi/boot/u-boot/bin/boot.scr" ,
131
+ ctx. mounted_config . path ( ) . join ( "boot.scr" ) ,
132
+ ) ?;
133
+ std:: fs:: write ( ctx. mounted_config . path ( ) . join ( "cmdline.txt" ) , "" ) ?;
134
+
135
+ let mut env = UBootEnv :: new ( ) ;
136
+ env. set ( "bootpart" , "2" . to_owned ( ) ) ;
137
+ env. save ( ctx. mounted_config . path ( ) . join ( "bootpart.default.env" ) ) ?;
138
+
139
+ let mut env = UBootEnv :: new ( ) ;
140
+ env. set ( "boot_spare" , "0" . to_owned ( ) ) ;
141
+ env. save ( ctx. mounted_config . path ( ) . join ( "boot_spare.disabled.env" ) ) ?;
142
+ env. save ( ctx. mounted_config . path ( ) . join ( "boot_spare.env" ) ) ?;
143
+
144
+ let mut env = UBootEnv :: new ( ) ;
145
+ env. set ( "boot_spare" , "1" . to_owned ( ) ) ;
146
+ env. save ( ctx. mounted_config . path ( ) . join ( "boot_spare.enabled.env" ) ) ?;
147
+
148
+ Ok ( ( ) )
149
+ }
150
+
79
151
fn include_pi4_firmware ( autoboot_path : & Utf8Path ) -> Anyhow < ( ) > {
80
152
run ! ( [
81
153
"cp" ,
0 commit comments