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,15 @@ 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
+ // type Error = Error;
115
132
fn try_from ( serde_apcb : SerdeApcb ) -> Result < Self > {
116
133
let buf = Cow :: from ( vec ! [ 0xFFu8 ; Self :: MAX_SIZE ] ) ;
117
- let mut apcb = Apcb :: create ( buf, 42 , & ApcbIoOptions :: default ( ) ) ?;
134
+ let mut apcb = Apcb :: create (
135
+ buf,
136
+ 42 ,
137
+ & ApcbIoOptions :: default ( ) . with_context ( serde_apcb. context ) . build ( ) ,
138
+ ) ?;
118
139
* apcb. header_mut ( ) ? = serde_apcb. header ;
119
140
match serde_apcb. v3_header_ext {
120
141
Some ( v3) => {
@@ -217,11 +238,13 @@ impl<'de> Deserialize<'de> for Apcb<'_> {
217
238
}
218
239
219
240
pub struct ApcbIterMut < ' a > {
241
+ context : ApcbContext ,
220
242
buf : & ' a mut [ u8 ] ,
221
243
remaining_used_size : usize ,
222
244
}
223
245
224
246
pub struct ApcbIter < ' a > {
247
+ context : ApcbContext ,
225
248
buf : & ' a [ u8 ] ,
226
249
remaining_used_size : usize ,
227
250
}
@@ -230,7 +253,10 @@ impl<'a> ApcbIterMut<'a> {
230
253
/// It's useful to have some way of NOT mutating self.buf. This is what
231
254
/// this function does. Note: The caller needs to manually decrease
232
255
/// remaining_used_size for each call if desired.
233
- fn next_item < ' b > ( buf : & mut & ' b mut [ u8 ] ) -> Result < GroupMutItem < ' b > > {
256
+ fn next_item < ' b > (
257
+ context : ApcbContext ,
258
+ buf : & mut & ' b mut [ u8 ] ,
259
+ ) -> Result < GroupMutItem < ' b > > {
234
260
if buf. is_empty ( ) {
235
261
return Err ( Error :: FileSystem (
236
262
FileSystemError :: InconsistentHeader ,
@@ -256,7 +282,7 @@ impl<'a> ApcbIterMut<'a> {
256
282
) ) ?;
257
283
let body_len = body. len ( ) ;
258
284
259
- Ok ( GroupMutItem { header, buf : body, used_size : body_len } )
285
+ Ok ( GroupMutItem { context , header, buf : body, used_size : body_len } )
260
286
}
261
287
262
288
/// Moves the point to the group with the given GROUP_ID. Returns (offset,
@@ -273,12 +299,12 @@ impl<'a> ApcbIterMut<'a> {
273
299
if buf. is_empty ( ) {
274
300
break ;
275
301
}
276
- let group = ApcbIterMut :: next_item ( & mut buf) ?;
302
+ let group = ApcbIterMut :: next_item ( self . context , & mut buf) ?;
277
303
let group_size = group. header . group_size . get ( ) ;
278
304
if group. header . group_id . get ( ) == group_id {
279
305
return Ok ( ( offset, group_size as usize ) ) ;
280
306
}
281
- let group = ApcbIterMut :: next_item ( & mut self . buf ) ?;
307
+ let group = ApcbIterMut :: next_item ( self . context , & mut self . buf ) ?;
282
308
let group_size = group. header . group_size . get ( ) as usize ;
283
309
offset = offset
284
310
. checked_add ( group_size)
@@ -295,7 +321,7 @@ impl<'a> ApcbIterMut<'a> {
295
321
296
322
pub ( crate ) fn next1 ( & mut self ) -> Result < GroupMutItem < ' a > > {
297
323
assert ! ( self . remaining_used_size != 0 , "Internal error" ) ;
298
- let item = Self :: next_item ( & mut self . buf ) ?;
324
+ let item = Self :: next_item ( self . context , & mut self . buf ) ?;
299
325
let group_size = item. header . group_size . get ( ) as usize ;
300
326
if group_size <= self . remaining_used_size {
301
327
self . remaining_used_size -= group_size;
@@ -324,7 +350,10 @@ impl<'a> ApcbIter<'a> {
324
350
/// It's useful to have some way of NOT mutating self.buf. This is what
325
351
/// this function does. Note: The caller needs to manually decrease
326
352
/// remaining_used_size for each call if desired.
327
- fn next_item < ' b > ( buf : & mut & ' b [ u8 ] ) -> Result < GroupItem < ' b > > {
353
+ fn next_item < ' b > (
354
+ context : ApcbContext ,
355
+ buf : & mut & ' b [ u8 ] ,
356
+ ) -> Result < GroupItem < ' b > > {
328
357
if buf. is_empty ( ) {
329
358
return Err ( Error :: FileSystem (
330
359
FileSystemError :: InconsistentHeader ,
@@ -351,12 +380,12 @@ impl<'a> ApcbIter<'a> {
351
380
352
381
let body_len = body. len ( ) ;
353
382
354
- Ok ( GroupItem { header, buf : body, used_size : body_len } )
383
+ Ok ( GroupItem { context , header, buf : body, used_size : body_len } )
355
384
}
356
385
357
386
pub ( crate ) fn next1 ( & mut self ) -> Result < GroupItem < ' a > > {
358
387
assert ! ( self . remaining_used_size != 0 , "Internal error" ) ;
359
- let item = Self :: next_item ( & mut self . buf ) ?;
388
+ let item = Self :: next_item ( self . context , & mut self . buf ) ?;
360
389
let group_size = item. header . group_size . get ( ) as usize ;
361
390
if group_size <= self . remaining_used_size {
362
391
self . remaining_used_size -= group_size;
@@ -369,7 +398,7 @@ impl<'a> ApcbIter<'a> {
369
398
}
370
399
}
371
400
/// Validates the entries (recursively). Also consumes iterator.
372
- pub ( crate ) fn validate ( mut self ) -> Result < ( ) > {
401
+ pub ( crate ) fn validate ( mut self , context : ApcbContext ) -> Result < ( ) > {
373
402
while self . remaining_used_size > 0 {
374
403
let item = self . next1 ( ) ?;
375
404
GroupId :: from_u16 ( item. header . group_id . get ( ) ) . ok_or (
@@ -509,6 +538,7 @@ impl<'a> Apcb<'a> {
509
538
510
539
pub fn groups ( & self ) -> Result < ApcbIter < ' _ > > {
511
540
Ok ( ApcbIter {
541
+ context : self . context ,
512
542
buf : self . beginning_of_groups ( ) ?,
513
543
remaining_used_size : self . used_size ,
514
544
} )
@@ -522,13 +552,14 @@ impl<'a> Apcb<'a> {
522
552
/// If ABL0_VERSION is Some, also validates against that AGESA
523
553
/// bootloader version.
524
554
pub fn validate ( & self , abl0_version : Option < u32 > ) -> Result < ( ) > {
525
- self . groups ( ) ?. validate ( ) ?;
555
+ self . groups ( ) ?. validate ( self . context ) ?;
526
556
self . ensure_abl0_compatibility ( abl0_version)
527
557
}
528
558
529
559
pub fn groups_mut ( & mut self ) -> Result < ApcbIterMut < ' _ > > {
530
560
let used_size = self . used_size ;
531
561
Ok ( ApcbIterMut {
562
+ context : self . context ,
532
563
buf : & mut * self . beginning_of_groups_mut ( ) ?,
533
564
remaining_used_size : used_size,
534
565
} )
@@ -1030,6 +1061,7 @@ impl<'a> Apcb<'a> {
1030
1061
signature : [ u8 ; 4 ] ,
1031
1062
) -> Result < GroupMutItem < ' _ > > {
1032
1063
// TODO: insert sorted.
1064
+ let context = self . context ;
1033
1065
1034
1066
if !match group_id {
1035
1067
GroupId :: Psp => signature == * b"PSPG" ,
@@ -1090,7 +1122,7 @@ impl<'a> Apcb<'a> {
1090
1122
) ) ?;
1091
1123
let body_len = body. len ( ) ;
1092
1124
1093
- Ok ( GroupMutItem { header, buf : body, used_size : body_len } )
1125
+ Ok ( GroupMutItem { context , header, buf : body, used_size : body_len } )
1094
1126
}
1095
1127
1096
1128
pub ( crate ) fn calculate_checksum (
@@ -1263,9 +1295,11 @@ impl<'a> Apcb<'a> {
1263
1295
) ) ;
1264
1296
}
1265
1297
}
1266
- let result = Self { backing_store : bs, used_size } ;
1298
+ let result =
1299
+ Self { context : options. context ( ) , backing_store : bs, used_size } ;
1267
1300
1268
- match result. groups ( ) ?. validate ( ) {
1301
+ let context = options. context ( ) ;
1302
+ match result. groups ( ) ?. validate ( context) {
1269
1303
Ok ( _) => { }
1270
1304
Err ( e) => {
1271
1305
return Err ( e) ;
0 commit comments