11use core:: fmt:: { self , Display } ;
2+ use core:: ops:: Range ;
23
34use bitfield_struct:: bitfield;
45use serde:: { Deserialize , Serialize } ;
56use zerocopy:: { FromBytes , Ref } ;
67use zerocopy_derive:: { FromBytes , Immutable , IntoBytes } ;
78
9+ use crate :: Removables ;
810use crate :: dir:: man:: Manifest ;
911use crate :: meta:: get_meta_for_key;
1012
13+ // These must never be removed. They are essential for platform initialization.
14+ pub const ALWAYS_RETAIN : & [ & str ] = & [
15+ "bup" , // bringup
16+ "rbe" , //
17+ "kernel" , //
18+ "syslib" , //
19+ ] ;
20+
1121pub const CPD_MAGIC : & str = "$CPD" ;
1222pub const CPD_MAGIC_BYTES : & [ u8 ] = CPD_MAGIC . as_bytes ( ) ;
1323
24+ const FOUR_K : usize = 0x1000 ;
25+
1426// see <https://troopers.de/downloads/troopers17/TR17_ME11_Static.pdf>
1527#[ derive( IntoBytes , FromBytes , Serialize , Deserialize , Clone , Copy , Debug ) ]
1628#[ repr( C , packed) ]
@@ -152,7 +164,7 @@ impl CodePartitionDirectory {
152164 let entries = r. to_vec ( ) ;
153165
154166 let manifest = {
155- let name = format ! ( "{}.man" , name ) ;
167+ let name = format ! ( "{name }.man" ) ;
156168 if let Some ( e) = entries. iter ( ) . find ( |e| e. name ( ) == name) {
157169 let b = & data[ e. flags_and_offset . offset ( ) as usize ..] ;
158170 Manifest :: new ( b)
@@ -173,9 +185,46 @@ impl CodePartitionDirectory {
173185 Ok ( cpd)
174186 }
175187
188+ // Entries sorted by offset
176189 fn sorted_entries ( & self ) -> Vec < CPDEntry > {
177190 let mut entries = self . entries . clone ( ) ;
178191 entries. sort_by_key ( |e| e. flags_and_offset . offset ( ) ) ;
179192 entries
180193 }
181194}
195+
196+ impl Removables for CodePartitionDirectory {
197+ /// Removable ranges relative to the start of the directory
198+ fn removables ( self : & Self , retention_list : & Vec < String > ) -> Vec < Range < usize > > {
199+ use log:: info;
200+ let mut removables = vec ! [ ] ;
201+
202+ if self . size > 0 {
203+ for e in & self . entries {
204+ match & e. name ( ) {
205+ n if n. ends_with ( ".man" ) => info ! ( "Retain manifest {n}" ) ,
206+ n if n. ends_with ( ".met" ) => info ! ( "Retain metadata {n}" ) ,
207+ n if retention_list. contains ( n) => info ! ( "Retain necessary {n}" ) ,
208+ _ => {
209+ let o = e. flags_and_offset . offset ( ) as usize ;
210+ let e = o + e. size as usize ;
211+ removables. push ( o..e) ;
212+ }
213+ }
214+ }
215+ // Remaining space to free after last entry
216+ let sorted = self . sorted_entries ( ) ;
217+ let last = sorted. last ( ) . unwrap ( ) ;
218+ let end = ( last. flags_and_offset . offset ( ) + last. size ) as usize ;
219+ let o = end. next_multiple_of ( FOUR_K ) ;
220+ let e = self . size ;
221+ removables. push ( o..e) ;
222+ info ! (
223+ "Remaining space: {:08x}..{:08x}" ,
224+ o + self . offset,
225+ e + self . offset
226+ ) ;
227+ }
228+ removables
229+ }
230+ }
0 commit comments