@@ -16,9 +16,11 @@ pub(crate) struct MenuentryBody<'a> {
16
16
/// Kernel modules to load
17
17
pub ( crate ) insmod : Vec < & ' a str > ,
18
18
/// Chainloader path (optional)
19
- pub ( crate ) chainloader : Option < & ' a str > ,
19
+ pub ( crate ) chainloader : String ,
20
20
/// Search command (optional)
21
- pub ( crate ) search : Option < & ' a str > ,
21
+ pub ( crate ) search : & ' a str ,
22
+ /// The version
23
+ pub ( crate ) version : u8 ,
22
24
/// Additional commands
23
25
pub ( crate ) extra : Vec < ( & ' a str , & ' a str ) > ,
24
26
}
@@ -29,13 +31,8 @@ impl<'a> Display for MenuentryBody<'a> {
29
31
writeln ! ( f, "insmod {}" , insmod) ?;
30
32
}
31
33
32
- if let Some ( search) = self . search {
33
- writeln ! ( f, "search {}" , search) ?;
34
- }
35
-
36
- if let Some ( chainloader) = self . chainloader {
37
- writeln ! ( f, "chainloader {}" , chainloader) ?;
38
- }
34
+ writeln ! ( f, "search {}" , self . search) ?;
35
+ writeln ! ( f, "chainloader {}" , self . chainloader) ?;
39
36
40
37
for ( k, v) in & self . extra {
41
38
writeln ! ( f, "{k} {v}" ) ?;
@@ -49,17 +46,17 @@ impl<'a> From<Vec<(&'a str, &'a str)>> for MenuentryBody<'a> {
49
46
fn from ( vec : Vec < ( & ' a str , & ' a str ) > ) -> Self {
50
47
let mut entry = Self {
51
48
insmod : vec ! [ ] ,
52
- chainloader : None ,
53
- search : None ,
49
+ chainloader : "" . into ( ) ,
50
+ search : "" ,
51
+ version : 0 ,
54
52
extra : vec ! [ ] ,
55
53
} ;
56
54
57
55
for ( key, value) in vec {
58
56
match key {
59
57
"insmod" => entry. insmod . push ( value) ,
60
- "chainloader" => entry. chainloader = Some ( value) ,
61
- "search" => entry. search = Some ( value) ,
62
- // Skip 'set' commands as they are typically variable assignments
58
+ "chainloader" => entry. chainloader = value. into ( ) ,
59
+ "search" => entry. search = value,
63
60
"set" => { }
64
61
_ => entry. extra . push ( ( key, value) ) ,
65
62
}
@@ -74,7 +71,7 @@ impl<'a> From<Vec<(&'a str, &'a str)>> for MenuentryBody<'a> {
74
71
#[ allow( dead_code) ]
75
72
pub ( crate ) struct MenuEntry < ' a > {
76
73
/// Display title (supports escaped quotes)
77
- pub ( crate ) title : & ' a str ,
74
+ pub ( crate ) title : String ,
78
75
/// Commands within the menuentry block
79
76
pub ( crate ) body : MenuentryBody < ' a > ,
80
77
}
@@ -87,6 +84,22 @@ impl<'a> Display for MenuEntry<'a> {
87
84
}
88
85
}
89
86
87
+ impl < ' a > MenuEntry < ' a > {
88
+ #[ allow( dead_code) ]
89
+ pub ( crate ) fn new ( boot_label : & str , uki_id : & str ) -> Self {
90
+ Self {
91
+ title : format ! ( "{boot_label}: ({uki_id})" ) ,
92
+ body : MenuentryBody {
93
+ insmod : vec ! [ "fat" , "chain" ] ,
94
+ chainloader : format ! ( "/EFI/Linux/{uki_id}.efi" ) ,
95
+ search : "--no-floppy --set=root --fs-uuid \" ${EFI_PART_UUID}\" " ,
96
+ version : 0 ,
97
+ extra : vec ! [ ] ,
98
+ } ,
99
+ }
100
+ }
101
+ }
102
+
90
103
/// Parser that takes content until balanced brackets, handling nested brackets and escapes.
91
104
#[ allow( dead_code) ]
92
105
pub fn take_until_balanced_allow_nested (
@@ -183,7 +196,7 @@ fn parse_menuentry(input: &str) -> IResult<&str, MenuEntry> {
183
196
Ok ( (
184
197
input,
185
198
MenuEntry {
186
- title,
199
+ title : title . to_string ( ) ,
187
200
body : MenuentryBody :: from ( map) ,
188
201
} ,
189
202
) )
@@ -278,20 +291,22 @@ mod test {
278
291
279
292
let expected = vec ! [
280
293
MenuEntry {
281
- title: "Fedora 42: (Verity-42)" ,
294
+ title: "Fedora 42: (Verity-42)" . into ( ) ,
282
295
body: MenuentryBody {
283
296
insmod: vec![ "fat" , "chain" ] ,
284
- search: Some ( "--no-floppy --set=root --fs-uuid \" ${EFI_PART_UUID}\" " ) ,
285
- chainloader: Some ( "/EFI/Linux/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6.efi" ) ,
297
+ search: "--no-floppy --set=root --fs-uuid \" ${EFI_PART_UUID}\" " ,
298
+ chainloader: "/EFI/Linux/7e11ac46e3e022053e7226a20104ac656bf72d1a84e3a398b7cce70e9df188b6.efi" . into( ) ,
299
+ version: 0 ,
286
300
extra: vec![ ] ,
287
301
} ,
288
302
} ,
289
303
MenuEntry {
290
- title: "Fedora 43: (Verity-43)" ,
304
+ title: "Fedora 43: (Verity-43)" . into ( ) ,
291
305
body: MenuentryBody {
292
306
insmod: vec![ "fat" , "chain" ] ,
293
- search: Some ( "--no-floppy --set=root --fs-uuid \" ${EFI_PART_UUID}\" " ) ,
294
- chainloader: Some ( "/EFI/Linux/uki.efi" ) ,
307
+ search: "--no-floppy --set=root --fs-uuid \" ${EFI_PART_UUID}\" " ,
308
+ chainloader: "/EFI/Linux/uki.efi" . into( ) ,
309
+ version: 0 ,
295
310
extra: vec![
296
311
( "extra_field1" , "this is extra" ) ,
297
312
( "extra_field2" , "this is also extra" )
@@ -318,7 +333,7 @@ mod test {
318
333
319
334
assert_eq ! ( result. len( ) , 1 ) ;
320
335
assert_eq ! ( result[ 0 ] . title, "Title with \\ \" escaped quotes\\ \" inside" ) ;
321
- assert_eq ! ( result[ 0 ] . body. chainloader, Some ( "/EFI/Linux/test.efi" ) ) ;
336
+ assert_eq ! ( result[ 0 ] . body. chainloader, "/EFI/Linux/test.efi" ) ;
322
337
}
323
338
324
339
#[ test]
@@ -367,8 +382,8 @@ mod test {
367
382
assert_eq ! ( result. len( ) , 1 ) ;
368
383
assert_eq ! ( result[ 0 ] . title, "Minimal Entry" ) ;
369
384
assert_eq ! ( result[ 0 ] . body. insmod. len( ) , 0 ) ;
370
- assert_eq ! ( result[ 0 ] . body. chainloader, None ) ;
371
- assert_eq ! ( result[ 0 ] . body. search, None ) ;
385
+ assert_eq ! ( result[ 0 ] . body. chainloader, "" ) ;
386
+ assert_eq ! ( result[ 0 ] . body. search, "" ) ;
372
387
assert_eq ! ( result[ 0 ] . body. extra. len( ) , 0 ) ;
373
388
}
374
389
@@ -386,8 +401,8 @@ mod test {
386
401
387
402
assert_eq ! ( result. len( ) , 1 ) ;
388
403
assert_eq ! ( result[ 0 ] . body. insmod, vec![ "fat" , "chain" , "ext2" ] ) ;
389
- assert_eq ! ( result[ 0 ] . body. chainloader, None ) ;
390
- assert_eq ! ( result[ 0 ] . body. search, None ) ;
404
+ assert_eq ! ( result[ 0 ] . body. chainloader, "" ) ;
405
+ assert_eq ! ( result[ 0 ] . body. search, "" ) ;
391
406
}
392
407
393
408
#[ test]
@@ -405,7 +420,7 @@ mod test {
405
420
406
421
assert_eq ! ( result. len( ) , 1 ) ;
407
422
assert_eq ! ( result[ 0 ] . body. insmod, vec![ "fat" ] ) ;
408
- assert_eq ! ( result[ 0 ] . body. chainloader, Some ( "/EFI/Linux/test.efi" ) ) ;
423
+ assert_eq ! ( result[ 0 ] . body. chainloader, "/EFI/Linux/test.efi" ) ;
409
424
// set commands should be ignored
410
425
assert ! ( !result[ 0 ] . body. extra. iter( ) . any( |( k, _) | k == & "set" ) ) ;
411
426
}
@@ -427,7 +442,7 @@ mod test {
427
442
assert_eq ! ( result. len( ) , 1 ) ;
428
443
assert_eq ! ( result[ 0 ] . title, "Nested Braces" ) ;
429
444
assert_eq ! ( result[ 0 ] . body. insmod, vec![ "fat" ] ) ;
430
- assert_eq ! ( result[ 0 ] . body. chainloader, Some ( "/EFI/Linux/test.efi" ) ) ;
445
+ assert_eq ! ( result[ 0 ] . body. chainloader, "/EFI/Linux/test.efi" ) ;
431
446
// The if/fi block should be captured as extra commands
432
447
assert ! ( result[ 0 ] . body. extra. iter( ) . any( |( k, _) | k == & "if" ) ) ;
433
448
}
@@ -506,12 +521,9 @@ mod test {
506
521
507
522
assert_eq ! ( result. len( ) , 2 ) ;
508
523
assert_eq ! ( result[ 0 ] . title, "First Entry" ) ;
509
- assert_eq ! ( result[ 0 ] . body. chainloader, Some ( "/EFI/Linux/first.efi" ) ) ;
524
+ assert_eq ! ( result[ 0 ] . body. chainloader, "/EFI/Linux/first.efi" ) ;
510
525
assert_eq ! ( result[ 1 ] . title, "Second Entry" ) ;
511
- assert_eq ! ( result[ 1 ] . body. chainloader, Some ( "/EFI/Linux/second.efi" ) ) ;
512
- assert_eq ! (
513
- result[ 1 ] . body. search,
514
- Some ( "--set=root --fs-uuid \" some-uuid\" " )
515
- ) ;
526
+ assert_eq ! ( result[ 1 ] . body. chainloader, "/EFI/Linux/second.efi" ) ;
527
+ assert_eq ! ( result[ 1 ] . body. search, "--set=root --fs-uuid \" some-uuid\" " ) ;
516
528
}
517
529
}
0 commit comments