@@ -2,7 +2,7 @@ use anyhow::{anyhow, Context};
2
2
use argh:: FromArgs ;
3
3
use bootloader:: disk_image:: create_disk_image;
4
4
use std:: {
5
- fs,
5
+ fs, io ,
6
6
path:: { Path , PathBuf } ,
7
7
process:: Command ,
8
8
str:: FromStr ,
@@ -66,14 +66,30 @@ impl FromStr for Firmware {
66
66
}
67
67
}
68
68
69
+ impl Firmware {
70
+ fn uefi ( & self ) -> bool {
71
+ match self {
72
+ Firmware :: Bios => false ,
73
+ Firmware :: Uefi | Firmware :: All => true ,
74
+ }
75
+ }
76
+
77
+ fn bios ( & self ) -> bool {
78
+ match self {
79
+ Firmware :: Bios | Firmware :: All => true ,
80
+ Firmware :: Uefi => false ,
81
+ }
82
+ }
83
+ }
84
+
69
85
/// Firmware must be one of `uefi`, `bios`, or `all`.
70
86
#[ derive( Debug , displaydoc:: Display , Eq , PartialEq , Copy , Clone ) ]
71
87
struct FirmwareParseError ;
72
88
73
89
fn main ( ) -> anyhow:: Result < ( ) > {
74
90
let args: BuildArguments = argh:: from_env ( ) ;
75
91
76
- if args. firmware == Firmware :: Uefi || args . firmware == Firmware :: All {
92
+ if args. firmware . uefi ( ) {
77
93
let build_or_run = if args. run { "run" } else { "build" } ;
78
94
let mut cmd = Command :: new ( env ! ( "CARGO" ) ) ;
79
95
cmd. arg ( build_or_run) . arg ( "--bin" ) . arg ( "uefi" ) ;
@@ -91,9 +107,81 @@ fn main() -> anyhow::Result<()> {
91
107
cmd. env ( "KERNEL" , & args. kernel_binary ) ;
92
108
cmd. env ( "KERNEL_MANIFEST" , & args. kernel_manifest ) ;
93
109
assert ! ( cmd. status( ) ?. success( ) ) ;
110
+
111
+ // Retrieve binary paths
112
+ cmd. arg ( "--message-format" ) . arg ( "json" ) ;
113
+ let output = cmd
114
+ . output ( )
115
+ . context ( "failed to execute kernel build with json output" ) ?;
116
+ if !output. status . success ( ) {
117
+ return Err ( anyhow ! ( "{}" , String :: from_utf8_lossy( & output. stderr) ) ) ;
118
+ }
119
+ let mut executables = Vec :: new ( ) ;
120
+ for line in String :: from_utf8 ( output. stdout )
121
+ . context ( "build JSON output is not valid UTF-8" ) ?
122
+ . lines ( )
123
+ {
124
+ let mut artifact = json:: parse ( line) . context ( "build JSON output is not valid JSON" ) ?;
125
+ if let Some ( executable) = artifact[ "executable" ] . take_string ( ) {
126
+ executables. push ( PathBuf :: from ( executable) ) ;
127
+ }
128
+ }
129
+
130
+ assert_eq ! ( executables. len( ) , 1 ) ;
131
+ let executable_path = executables. pop ( ) . unwrap ( ) ;
132
+ let executable_name = executable_path. file_stem ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
133
+ let kernel_name = args. kernel_binary . file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
134
+
135
+ if let Some ( out_dir) = & args. out_dir {
136
+ let efi_file =
137
+ out_dir. join ( format ! ( "bootimage-{}-{}.efi" , executable_name, kernel_name) ) ;
138
+ fs:: copy ( & executable_path, & efi_file) . context ( "failed to copy efi file to out dir" ) ?;
139
+
140
+ let efi_size = fs:: metadata ( & efi_file)
141
+ . context ( "failed to read metadata of efi file" ) ?
142
+ . len ( ) ;
143
+
144
+ // create fat partition
145
+ {
146
+ const MB : u64 = 1024 * 1024 ;
147
+
148
+ let fat_path = efi_file. with_extension ( "fat" ) ;
149
+ dbg ! ( & fat_path) ;
150
+ let fat_file = fs:: OpenOptions :: new ( )
151
+ . read ( true )
152
+ . write ( true )
153
+ . create ( true )
154
+ . truncate ( true )
155
+ . open ( & fat_path)
156
+ . context ( "Failed to create UEFI FAT file" ) ?;
157
+ let efi_size_rounded = ( ( efi_size - 1 ) / MB + 1 ) * MB ;
158
+ fat_file
159
+ . set_len ( dbg ! ( efi_size_rounded) )
160
+ . context ( "failed to set UEFI FAT file length" ) ?;
161
+
162
+ // create new FAT partition
163
+ fatfs:: format_volume ( & fat_file, fatfs:: FormatVolumeOptions :: new ( ) )
164
+ . context ( "Failed to format UEFI FAT file" ) ?;
165
+
166
+ // copy EFI file to FAT filesystem
167
+ let partition = fatfs:: FileSystem :: new ( & fat_file, fatfs:: FsOptions :: new ( ) )
168
+ . context ( "Failed to open FAT file system of UEFI FAT file" ) ?;
169
+ let root_dir = partition. root_dir ( ) ;
170
+ root_dir. create_dir ( "efi" ) ?;
171
+ root_dir. create_dir ( "efi/boot" ) ?;
172
+ let mut bootx64 = root_dir. create_file ( "efi/boot/bootx64.efi" ) ?;
173
+ bootx64. truncate ( ) ?;
174
+ io:: copy ( & mut fs:: File :: open ( & executable_path) ?, & mut bootx64) ?;
175
+ }
176
+
177
+ // create gpt disk
178
+ {
179
+ //todo!()
180
+ }
181
+ }
94
182
}
95
183
96
- if args. firmware == Firmware :: Bios || args . firmware == Firmware :: All {
184
+ if args. firmware . bios ( ) {
97
185
let mut cmd = Command :: new ( env ! ( "CARGO" ) ) ;
98
186
cmd. arg ( "build" ) . arg ( "--bin" ) . arg ( "bios" ) ;
99
187
cmd. arg ( "--profile" ) . arg ( "release" ) ;
0 commit comments