2
2
// License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
5
- use crate :: types:: { Error , FileSystemError , PtrMut , Result } ;
5
+ use crate :: types:: { ApcbContext , Error , FileSystemError , PtrMut , Result } ;
6
6
7
7
use crate :: entry:: EntryItemBody ;
8
8
use crate :: group:: { GroupItem , GroupMutItem } ;
@@ -50,29 +50,41 @@ use std::borrow::Cow;
50
50
#[ derive( Clone ) ]
51
51
pub struct ApcbIoOptions {
52
52
pub check_checksum : bool ,
53
+ pub context : ApcbContext ,
53
54
}
54
55
55
56
impl Default for ApcbIoOptions {
56
57
fn default ( ) -> Self {
57
- Self { check_checksum : true }
58
+ Self { check_checksum : true , context : ApcbContext :: default ( ) }
58
59
}
59
60
}
60
61
61
62
impl ApcbIoOptions {
62
63
pub fn builder ( ) -> Self {
63
64
Self :: default ( )
64
65
}
66
+ pub fn check_checksum ( & self ) -> bool {
67
+ self . check_checksum
68
+ }
69
+ pub fn context ( & self ) -> ApcbContext {
70
+ self . context
71
+ }
65
72
pub fn with_check_checksum ( & mut self , value : bool ) -> & mut Self {
66
73
self . check_checksum = value;
67
74
self
68
75
}
76
+ pub fn with_context ( & mut self , value : ApcbContext ) -> & mut Self {
77
+ self . context = value;
78
+ self
79
+ }
69
80
pub fn build ( & self ) -> Self {
70
81
self . clone ( )
71
82
}
72
83
}
73
84
74
85
#[ cfg_attr( feature = "std" , derive( Clone ) ) ]
75
86
pub struct Apcb < ' a > {
87
+ context : ApcbContext ,
76
88
used_size : usize ,
77
89
pub backing_store : PtrMut < ' a , [ u8 ] > ,
78
90
}
@@ -83,6 +95,11 @@ pub struct Apcb<'a> {
83
95
#[ cfg_attr( feature = "serde" , serde( deny_unknown_fields) ) ]
84
96
#[ cfg_attr( feature = "schemars" , derive( schemars:: JsonSchema ) ) ]
85
97
pub struct SerdeApcb {
98
+ /// This field is out-of-band information. At the cost of slight redundancy
99
+ /// in user config and another extra field that isn't actually in the blob,
100
+ /// we can actually handle the out-of-band information quite natually.
101
+ #[ cfg_attr( feature = "serde" , serde( default ) ) ]
102
+ pub context : ApcbContext ,
86
103
pub version : String ,
87
104
pub header : V2_HEADER ,
88
105
pub v3_header_ext : Option < V3_HEADER_EXT > ,
@@ -110,11 +127,18 @@ impl<'a> schemars::JsonSchema for Apcb<'a> {
110
127
use core:: convert:: TryFrom ;
111
128
112
129
#[ cfg( feature = "serde" ) ]
113
- impl < ' a > TryFrom < SerdeApcb > for Apcb < ' a > {
114
- type Error = Error ;
130
+ impl < ' a > Apcb < ' a > {
131
+ pub fn context ( & self ) -> ApcbContext {
132
+ self . context
133
+ }
134
+ // type Error = Error;
115
135
fn try_from ( serde_apcb : SerdeApcb ) -> Result < Self > {
116
136
let buf = Cow :: from ( vec ! [ 0xFFu8 ; Self :: MAX_SIZE ] ) ;
117
- let mut apcb = Apcb :: create ( buf, 42 , & ApcbIoOptions :: default ( ) ) ?;
137
+ let mut apcb = Apcb :: create (
138
+ buf,
139
+ 42 ,
140
+ & ApcbIoOptions :: default ( ) . with_context ( serde_apcb. context ) . build ( ) ,
141
+ ) ?;
118
142
* apcb. header_mut ( ) ? = serde_apcb. header ;
119
143
match serde_apcb. v3_header_ext {
120
144
Some ( v3) => {
@@ -217,11 +241,13 @@ impl<'de> Deserialize<'de> for Apcb<'_> {
217
241
}
218
242
219
243
pub struct ApcbIterMut < ' a > {
244
+ context : ApcbContext ,
220
245
buf : & ' a mut [ u8 ] ,
221
246
remaining_used_size : usize ,
222
247
}
223
248
224
249
pub struct ApcbIter < ' a > {
250
+ context : ApcbContext ,
225
251
buf : & ' a [ u8 ] ,
226
252
remaining_used_size : usize ,
227
253
}
@@ -230,7 +256,10 @@ impl<'a> ApcbIterMut<'a> {
230
256
/// It's useful to have some way of NOT mutating self.buf. This is what
231
257
/// this function does. Note: The caller needs to manually decrease
232
258
/// remaining_used_size for each call if desired.
233
- fn next_item < ' b > ( buf : & mut & ' b mut [ u8 ] ) -> Result < GroupMutItem < ' b > > {
259
+ fn next_item < ' b > (
260
+ context : ApcbContext ,
261
+ buf : & mut & ' b mut [ u8 ] ,
262
+ ) -> Result < GroupMutItem < ' b > > {
234
263
if buf. is_empty ( ) {
235
264
return Err ( Error :: FileSystem (
236
265
FileSystemError :: InconsistentHeader ,
@@ -256,7 +285,7 @@ impl<'a> ApcbIterMut<'a> {
256
285
) ) ?;
257
286
let body_len = body. len ( ) ;
258
287
259
- Ok ( GroupMutItem { header, buf : body, used_size : body_len } )
288
+ Ok ( GroupMutItem { context , header, buf : body, used_size : body_len } )
260
289
}
261
290
262
291
/// Moves the point to the group with the given GROUP_ID. Returns (offset,
@@ -273,12 +302,12 @@ impl<'a> ApcbIterMut<'a> {
273
302
if buf. is_empty ( ) {
274
303
break ;
275
304
}
276
- let group = ApcbIterMut :: next_item ( & mut buf) ?;
305
+ let group = ApcbIterMut :: next_item ( self . context , & mut buf) ?;
277
306
let group_size = group. header . group_size . get ( ) ;
278
307
if group. header . group_id . get ( ) == group_id {
279
308
return Ok ( ( offset, group_size as usize ) ) ;
280
309
}
281
- let group = ApcbIterMut :: next_item ( & mut self . buf ) ?;
310
+ let group = ApcbIterMut :: next_item ( self . context , & mut self . buf ) ?;
282
311
let group_size = group. header . group_size . get ( ) as usize ;
283
312
offset = offset
284
313
. checked_add ( group_size)
@@ -295,7 +324,7 @@ impl<'a> ApcbIterMut<'a> {
295
324
296
325
pub ( crate ) fn next1 ( & mut self ) -> Result < GroupMutItem < ' a > > {
297
326
assert ! ( self . remaining_used_size != 0 , "Internal error" ) ;
298
- let item = Self :: next_item ( & mut self . buf ) ?;
327
+ let item = Self :: next_item ( self . context , & mut self . buf ) ?;
299
328
let group_size = item. header . group_size . get ( ) as usize ;
300
329
if group_size <= self . remaining_used_size {
301
330
self . remaining_used_size -= group_size;
@@ -324,7 +353,10 @@ impl<'a> ApcbIter<'a> {
324
353
/// It's useful to have some way of NOT mutating self.buf. This is what
325
354
/// this function does. Note: The caller needs to manually decrease
326
355
/// remaining_used_size for each call if desired.
327
- fn next_item < ' b > ( buf : & mut & ' b [ u8 ] ) -> Result < GroupItem < ' b > > {
356
+ fn next_item < ' b > (
357
+ context : ApcbContext ,
358
+ buf : & mut & ' b [ u8 ] ,
359
+ ) -> Result < GroupItem < ' b > > {
328
360
if buf. is_empty ( ) {
329
361
return Err ( Error :: FileSystem (
330
362
FileSystemError :: InconsistentHeader ,
@@ -351,12 +383,12 @@ impl<'a> ApcbIter<'a> {
351
383
352
384
let body_len = body. len ( ) ;
353
385
354
- Ok ( GroupItem { header, buf : body, used_size : body_len } )
386
+ Ok ( GroupItem { context , header, buf : body, used_size : body_len } )
355
387
}
356
388
357
389
pub ( crate ) fn next1 ( & mut self ) -> Result < GroupItem < ' a > > {
358
390
assert ! ( self . remaining_used_size != 0 , "Internal error" ) ;
359
- let item = Self :: next_item ( & mut self . buf ) ?;
391
+ let item = Self :: next_item ( self . context , & mut self . buf ) ?;
360
392
let group_size = item. header . group_size . get ( ) as usize ;
361
393
if group_size <= self . remaining_used_size {
362
394
self . remaining_used_size -= group_size;
@@ -369,7 +401,7 @@ impl<'a> ApcbIter<'a> {
369
401
}
370
402
}
371
403
/// Validates the entries (recursively). Also consumes iterator.
372
- pub ( crate ) fn validate ( mut self ) -> Result < ( ) > {
404
+ pub ( crate ) fn validate ( mut self , context : ApcbContext ) -> Result < ( ) > {
373
405
while self . remaining_used_size > 0 {
374
406
let item = self . next1 ( ) ?;
375
407
GroupId :: from_u16 ( item. header . group_id . get ( ) ) . ok_or (
@@ -509,6 +541,7 @@ impl<'a> Apcb<'a> {
509
541
510
542
pub fn groups ( & self ) -> Result < ApcbIter < ' _ > > {
511
543
Ok ( ApcbIter {
544
+ context : self . context ,
512
545
buf : self . beginning_of_groups ( ) ?,
513
546
remaining_used_size : self . used_size ,
514
547
} )
@@ -522,13 +555,14 @@ impl<'a> Apcb<'a> {
522
555
/// If ABL0_VERSION is Some, also validates against that AGESA
523
556
/// bootloader version.
524
557
pub fn validate ( & self , abl0_version : Option < u32 > ) -> Result < ( ) > {
525
- self . groups ( ) ?. validate ( ) ?;
558
+ self . groups ( ) ?. validate ( self . context ) ?;
526
559
self . ensure_abl0_compatibility ( abl0_version)
527
560
}
528
561
529
562
pub fn groups_mut ( & mut self ) -> Result < ApcbIterMut < ' _ > > {
530
563
let used_size = self . used_size ;
531
564
Ok ( ApcbIterMut {
565
+ context : self . context ,
532
566
buf : & mut * self . beginning_of_groups_mut ( ) ?,
533
567
remaining_used_size : used_size,
534
568
} )
@@ -1030,6 +1064,7 @@ impl<'a> Apcb<'a> {
1030
1064
signature : [ u8 ; 4 ] ,
1031
1065
) -> Result < GroupMutItem < ' _ > > {
1032
1066
// TODO: insert sorted.
1067
+ let context = self . context ;
1033
1068
1034
1069
if !match group_id {
1035
1070
GroupId :: Psp => signature == * b"PSPG" ,
@@ -1090,7 +1125,7 @@ impl<'a> Apcb<'a> {
1090
1125
) ) ?;
1091
1126
let body_len = body. len ( ) ;
1092
1127
1093
- Ok ( GroupMutItem { header, buf : body, used_size : body_len } )
1128
+ Ok ( GroupMutItem { context , header, buf : body, used_size : body_len } )
1094
1129
}
1095
1130
1096
1131
pub ( crate ) fn calculate_checksum (
@@ -1263,9 +1298,11 @@ impl<'a> Apcb<'a> {
1263
1298
) ) ;
1264
1299
}
1265
1300
}
1266
- let result = Self { backing_store : bs, used_size } ;
1301
+ let result =
1302
+ Self { context : options. context ( ) , backing_store : bs, used_size } ;
1267
1303
1268
- match result. groups ( ) ?. validate ( ) {
1304
+ let context = options. context ( ) ;
1305
+ match result. groups ( ) ?. validate ( context) {
1269
1306
Ok ( _) => { }
1270
1307
Err ( e) => {
1271
1308
return Err ( e) ;
0 commit comments