1use alloc::collections::BTreeMap;
2use alloc::string::String;
3use alloc::vec::Vec;
4
5use gibblox_pipeline::bin::PipelineSourceBin;
6
7use serde::{Deserialize, Serialize};
8
9use crate::{
10 Boot, BootProfile, BootProfileArtifactPathSource, BootProfileArtifactSource, BootProfileDevice,
11 BootProfileDeviceStage0, BootProfileRootfs, BootProfileRootfsErofsSource,
12 BootProfileRootfsExt4Source, BootProfileRootfsFatSource, BootProfileRootfsFilesystemSource,
13 BootProfileRootfsOstreeSource, BootProfileStage0, DeviceProfile, ExistsFlag, FastbootGetvarEq,
14 FastbootGetvarExists, FastbootGetvarNotEq, FastbootGetvarNotExists, FastbootGetvarStartsWith,
15 InjectMac, MatchRule, NotExistsFlag, ProbeStep,
16};
17
18pub const BOOT_PROFILE_BIN_FORMAT_V0: u16 = 0;
20pub const BOOT_PROFILE_BIN_V0_MAGIC: [u8; 8] = *b"FBOOPROF";
21pub const BOOT_PROFILE_BIN_V0_HEADER_LEN: usize = 10;
22
23pub const DEV_PROFILE_BIN_FORMAT_V0: u16 = 0;
25pub const DEV_PROFILE_BIN_V0_MAGIC: [u8; 8] = *b"FBOODEVP";
26pub const DEV_PROFILE_BIN_V0_HEADER_LEN: usize = 10;
27
28#[derive(Clone, Debug, Deserialize, Serialize)]
29pub struct BootProfileBin {
30 pub id: String,
31 pub display_name: Option<String>,
32 pub rootfs: BootProfileRootfsBin,
33 pub kernel: Option<BootProfileArtifactPathSourceBin>,
34 pub dtbs: Option<BootProfileArtifactPathSourceBin>,
35 pub dt_overlays: Vec<Vec<u8>>,
36 pub extra_cmdline: Option<String>,
37 pub stage0: BootProfileStage0Bin,
38}
39
40#[derive(Clone, Debug, Deserialize, Serialize)]
41pub struct BootProfileArtifactPathSourceBin {
42 pub path: String,
43 pub source: BootProfileRootfsBin,
44}
45
46#[derive(Clone, Debug, Deserialize, Serialize)]
47pub enum BootProfileRootfsBin {
48 Ostree {
49 source: BootProfileRootfsFilesystemBin,
50 },
51 Erofs {
52 source: PipelineSourceBin,
53 },
54 Ext4 {
55 source: PipelineSourceBin,
56 },
57 Fat {
58 source: PipelineSourceBin,
59 },
60}
61
62#[derive(Clone, Debug, Deserialize, Serialize)]
63pub enum BootProfileRootfsFilesystemBin {
64 Erofs { source: PipelineSourceBin },
65 Ext4 { source: PipelineSourceBin },
66 Fat { source: PipelineSourceBin },
67}
68
69#[derive(Clone, Debug, Deserialize, Serialize)]
70pub struct BootProfileStage0Bin {
71 pub kernel_modules: Vec<String>,
72 pub devices: BTreeMap<String, BootProfileDeviceBin>,
73}
74
75#[derive(Clone, Debug, Deserialize, Serialize)]
76pub struct BootProfileDeviceBin {
77 pub dt_overlays: Vec<Vec<u8>>,
78 pub extra_cmdline: Option<String>,
79 pub stage0: BootProfileDeviceStage0Bin,
80}
81
82#[derive(Clone, Debug, Deserialize, Serialize)]
83pub struct BootProfileDeviceStage0Bin {
84 pub kernel_modules: Vec<String>,
85 pub inject_mac: Option<InjectMacBin>,
86}
87
88#[derive(Clone, Debug, Deserialize, Serialize)]
89pub struct DeviceProfileBin {
90 pub id: String,
91 pub display_name: Option<String>,
92 pub devicetree_name: String,
93 pub r#match: Vec<MatchRule>,
94 pub probe: Vec<ProbeStepBin>,
95 pub boot: Boot,
96}
97
98#[derive(Clone, Debug, Deserialize, Serialize)]
99pub enum ProbeStepBin {
100 FastbootGetvarEq { name: String, equals: String },
101 FastbootGetvarStartsWith { name: String, starts_with: String },
102 FastbootGetvarNotEq { name: String, not_equals: String },
103 FastbootGetvarExists { name: String },
104 FastbootGetvarNotExists { name: String },
105}
106
107#[derive(Clone, Debug, Deserialize, Serialize)]
108pub struct InjectMacBin {
109 pub wifi: Option<String>,
110 pub bluetooth: Option<String>,
111}
112
113impl From<DeviceProfile> for DeviceProfileBin {
114 fn from(profile: DeviceProfile) -> Self {
115 Self {
116 id: profile.id,
117 display_name: profile.display_name,
118 devicetree_name: profile.devicetree_name,
119 r#match: profile.r#match,
120 probe: profile.probe.into_iter().map(ProbeStepBin::from).collect(),
121 boot: profile.boot,
122 }
123 }
124}
125
126impl From<DeviceProfileBin> for DeviceProfile {
127 fn from(profile: DeviceProfileBin) -> Self {
128 Self {
129 id: profile.id,
130 display_name: profile.display_name,
131 devicetree_name: profile.devicetree_name,
132 r#match: profile.r#match,
133 probe: profile.probe.into_iter().map(ProbeStep::from).collect(),
134 boot: profile.boot,
135 }
136 }
137}
138
139impl From<ProbeStep> for ProbeStepBin {
140 fn from(step: ProbeStep) -> Self {
141 match step {
142 ProbeStep::FastbootGetvarEq(FastbootGetvarEq { name, equals }) => {
143 ProbeStepBin::FastbootGetvarEq { name, equals }
144 }
145 ProbeStep::FastbootGetvarStartsWith(FastbootGetvarStartsWith { name, starts_with }) => {
146 ProbeStepBin::FastbootGetvarStartsWith { name, starts_with }
147 }
148 ProbeStep::FastbootGetvarNotEq(FastbootGetvarNotEq { name, not_equals }) => {
149 ProbeStepBin::FastbootGetvarNotEq { name, not_equals }
150 }
151 ProbeStep::FastbootGetvarExists(FastbootGetvarExists { name, .. }) => {
152 ProbeStepBin::FastbootGetvarExists { name }
153 }
154 ProbeStep::FastbootGetvarNotExists(FastbootGetvarNotExists { name, .. }) => {
155 ProbeStepBin::FastbootGetvarNotExists { name }
156 }
157 }
158 }
159}
160
161impl From<ProbeStepBin> for ProbeStep {
162 fn from(step: ProbeStepBin) -> Self {
163 match step {
164 ProbeStepBin::FastbootGetvarEq { name, equals } => {
165 ProbeStep::FastbootGetvarEq(FastbootGetvarEq { name, equals })
166 }
167 ProbeStepBin::FastbootGetvarStartsWith { name, starts_with } => {
168 ProbeStep::FastbootGetvarStartsWith(FastbootGetvarStartsWith { name, starts_with })
169 }
170 ProbeStepBin::FastbootGetvarNotEq { name, not_equals } => {
171 ProbeStep::FastbootGetvarNotEq(FastbootGetvarNotEq { name, not_equals })
172 }
173 ProbeStepBin::FastbootGetvarExists { name } => {
174 ProbeStep::FastbootGetvarExists(FastbootGetvarExists {
175 name,
176 exists: Some(ExistsFlag),
177 })
178 }
179 ProbeStepBin::FastbootGetvarNotExists { name } => {
180 ProbeStep::FastbootGetvarNotExists(FastbootGetvarNotExists {
181 name,
182 not_exists: Some(NotExistsFlag),
183 })
184 }
185 }
186 }
187}
188
189impl From<InjectMac> for InjectMacBin {
190 fn from(mac: InjectMac) -> Self {
191 Self {
192 wifi: mac.wifi,
193 bluetooth: mac.bluetooth,
194 }
195 }
196}
197
198impl From<InjectMacBin> for InjectMac {
199 fn from(mac: InjectMacBin) -> Self {
200 Self {
201 wifi: mac.wifi,
202 bluetooth: mac.bluetooth,
203 }
204 }
205}
206
207impl From<BootProfile> for BootProfileBin {
208 fn from(profile: BootProfile) -> Self {
209 Self {
210 id: profile.id,
211 display_name: profile.display_name,
212 rootfs: BootProfileRootfsBin::from(profile.rootfs),
213 kernel: profile.kernel.map(BootProfileArtifactPathSourceBin::from),
214 dtbs: profile.dtbs.map(BootProfileArtifactPathSourceBin::from),
215 dt_overlays: profile.dt_overlays,
216 extra_cmdline: profile.extra_cmdline,
217 stage0: BootProfileStage0Bin::from(profile.stage0),
218 }
219 }
220}
221
222impl From<BootProfileBin> for BootProfile {
223 fn from(profile: BootProfileBin) -> Self {
224 Self {
225 id: profile.id,
226 display_name: profile.display_name,
227 rootfs: BootProfileRootfs::from(profile.rootfs),
228 kernel: profile.kernel.map(BootProfileArtifactPathSource::from),
229 dtbs: profile.dtbs.map(BootProfileArtifactPathSource::from),
230 dt_overlays: profile.dt_overlays,
231 extra_cmdline: profile.extra_cmdline,
232 stage0: BootProfileStage0::from(profile.stage0),
233 }
234 }
235}
236
237impl From<BootProfileArtifactPathSource> for BootProfileArtifactPathSourceBin {
238 fn from(source: BootProfileArtifactPathSource) -> Self {
239 Self {
240 path: source.path,
241 source: BootProfileRootfsBin::from(source.source),
242 }
243 }
244}
245
246impl From<BootProfileArtifactPathSourceBin> for BootProfileArtifactPathSource {
247 fn from(source: BootProfileArtifactPathSourceBin) -> Self {
248 Self {
249 path: source.path,
250 source: BootProfileRootfs::from(source.source),
251 }
252 }
253}
254
255impl From<BootProfileRootfs> for BootProfileRootfsBin {
256 fn from(rootfs: BootProfileRootfs) -> Self {
257 match rootfs {
258 BootProfileRootfs::Ostree(BootProfileRootfsOstreeSource { ostree }) => Self::Ostree {
259 source: BootProfileRootfsFilesystemBin::from(ostree),
260 },
261 BootProfileRootfs::Erofs(BootProfileRootfsErofsSource { erofs }) => Self::Erofs {
262 source: PipelineSourceBin::from(erofs),
263 },
264 BootProfileRootfs::Ext4(BootProfileRootfsExt4Source { ext4 }) => Self::Ext4 {
265 source: PipelineSourceBin::from(ext4),
266 },
267 BootProfileRootfs::Fat(BootProfileRootfsFatSource { fat }) => Self::Fat {
268 source: PipelineSourceBin::from(fat),
269 },
270 }
271 }
272}
273
274impl From<BootProfileRootfsBin> for BootProfileRootfs {
275 fn from(rootfs: BootProfileRootfsBin) -> Self {
276 match rootfs {
277 BootProfileRootfsBin::Ostree { source } => {
278 Self::Ostree(BootProfileRootfsOstreeSource {
279 ostree: BootProfileRootfsFilesystemSource::from(source),
280 })
281 }
282 BootProfileRootfsBin::Erofs { source } => Self::Erofs(BootProfileRootfsErofsSource {
283 erofs: BootProfileArtifactSource::from(source),
284 }),
285 BootProfileRootfsBin::Ext4 { source } => Self::Ext4(BootProfileRootfsExt4Source {
286 ext4: BootProfileArtifactSource::from(source),
287 }),
288 BootProfileRootfsBin::Fat { source } => Self::Fat(BootProfileRootfsFatSource {
289 fat: BootProfileArtifactSource::from(source),
290 }),
291 }
292 }
293}
294
295impl From<BootProfileRootfsFilesystemSource> for BootProfileRootfsFilesystemBin {
296 fn from(source: BootProfileRootfsFilesystemSource) -> Self {
297 match source {
298 BootProfileRootfsFilesystemSource::Erofs(BootProfileRootfsErofsSource { erofs }) => {
299 Self::Erofs {
300 source: PipelineSourceBin::from(erofs),
301 }
302 }
303 BootProfileRootfsFilesystemSource::Ext4(BootProfileRootfsExt4Source { ext4 }) => {
304 Self::Ext4 {
305 source: PipelineSourceBin::from(ext4),
306 }
307 }
308 BootProfileRootfsFilesystemSource::Fat(BootProfileRootfsFatSource { fat }) => {
309 Self::Fat {
310 source: PipelineSourceBin::from(fat),
311 }
312 }
313 }
314 }
315}
316
317impl From<BootProfileRootfsFilesystemBin> for BootProfileRootfsFilesystemSource {
318 fn from(source: BootProfileRootfsFilesystemBin) -> Self {
319 match source {
320 BootProfileRootfsFilesystemBin::Erofs { source } => {
321 Self::Erofs(BootProfileRootfsErofsSource {
322 erofs: BootProfileArtifactSource::from(source),
323 })
324 }
325 BootProfileRootfsFilesystemBin::Ext4 { source } => {
326 Self::Ext4(BootProfileRootfsExt4Source {
327 ext4: BootProfileArtifactSource::from(source),
328 })
329 }
330 BootProfileRootfsFilesystemBin::Fat { source } => {
331 Self::Fat(BootProfileRootfsFatSource {
332 fat: BootProfileArtifactSource::from(source),
333 })
334 }
335 }
336 }
337}
338
339impl From<BootProfileStage0> for BootProfileStage0Bin {
340 fn from(stage0: BootProfileStage0) -> Self {
341 Self {
342 kernel_modules: stage0.kernel_modules,
343 devices: stage0
344 .devices
345 .into_iter()
346 .map(|(device_id, device)| (device_id, BootProfileDeviceBin::from(device)))
347 .collect(),
348 }
349 }
350}
351
352impl From<BootProfileStage0Bin> for BootProfileStage0 {
353 fn from(stage0: BootProfileStage0Bin) -> Self {
354 Self {
355 kernel_modules: stage0.kernel_modules,
356 devices: stage0
357 .devices
358 .into_iter()
359 .map(|(device_id, device)| (device_id, BootProfileDevice::from(device)))
360 .collect(),
361 }
362 }
363}
364
365impl From<BootProfileDevice> for BootProfileDeviceBin {
366 fn from(device: BootProfileDevice) -> Self {
367 Self {
368 dt_overlays: device.dt_overlays,
369 extra_cmdline: device.extra_cmdline,
370 stage0: BootProfileDeviceStage0Bin::from(device.stage0),
371 }
372 }
373}
374
375impl From<BootProfileDeviceBin> for BootProfileDevice {
376 fn from(device: BootProfileDeviceBin) -> Self {
377 Self {
378 dt_overlays: device.dt_overlays,
379 extra_cmdline: device.extra_cmdline,
380 stage0: BootProfileDeviceStage0::from(device.stage0),
381 }
382 }
383}
384
385impl From<BootProfileDeviceStage0> for BootProfileDeviceStage0Bin {
386 fn from(stage0: BootProfileDeviceStage0) -> Self {
387 Self {
388 kernel_modules: stage0.kernel_modules,
389 inject_mac: stage0.inject_mac.map(InjectMacBin::from),
390 }
391 }
392}
393
394impl From<BootProfileDeviceStage0Bin> for BootProfileDeviceStage0 {
395 fn from(stage0: BootProfileDeviceStage0Bin) -> Self {
396 Self {
397 kernel_modules: stage0.kernel_modules,
398 inject_mac: stage0.inject_mac.map(InjectMac::from),
399 }
400 }
401}