@@ -12,6 +12,7 @@ use crate::dir::{
1212 gen2:: Directory as Gen2Directory ,
1313 gen3:: { CPD_MAGIC_BYTES , CodePartitionDirectory } ,
1414} ;
15+ use crate :: part:: gen2:: Gen2Partition ;
1516use crate :: part:: {
1617 fpt:: { FPT , MIN_FPT_SIZE } ,
1718 partitions:: Partitions ,
@@ -63,6 +64,67 @@ impl FPTArea {
6364 }
6465 }
6566
67+ pub fn relocate_partitions ( & mut self ) -> Result < ( ) , String > {
68+ let sorted_parts = & self . partitions . get_sorted ( ) ;
69+ let first = sorted_parts
70+ . into_iter ( )
71+ . filter ( |p| p. entry ( ) . size ( ) > 0 )
72+ . nth ( 0 ) ;
73+ if let Some ( p) = first {
74+ let e = p. entry ( ) ;
75+ let n = e. name ( ) ;
76+ let min_offset = MIN_FPT_SIZE ;
77+ let new_offset = match & self . partitions {
78+ Partitions :: Gen2 ( parts) => {
79+ // Find a Directory partition to calculate the offset.
80+ let dir_part = parts. iter ( ) . find ( |p| matches ! ( p, Gen2Partition :: Dir ( _) ) ) ;
81+ match dir_part {
82+ Some ( Gen2Partition :: Dir ( d) ) => d. dir . calc_new_offset ( min_offset as u32 ) ?,
83+ _ => return Err ( "no directory partition found" . into ( ) ) ,
84+ }
85+ }
86+ Partitions :: Gen3 ( _) => e. offset ( ) . min ( min_offset) as u32 ,
87+ _ => todo ! ( ) ,
88+ } ;
89+
90+ let old_offset = e. offset ( ) ;
91+ println ! ( "old offset: {old_offset:08x}" ) ;
92+ println ! ( "new offset: {new_offset:08x}" ) ;
93+
94+ if let Err ( e) = self . partitions . relocate ( & n, new_offset) {
95+ return Err ( format ! ( "Cannot relocate partitions: {e}" ) ) ;
96+ }
97+
98+ let offset = new_offset as usize ;
99+ // It may happen that some part of the FPT area had not been covered
100+ // by an FPT entry, but it contained data that can now be overwritten
101+ // when relocating partitions.
102+ let mut non_covered = vec ! [ ] ;
103+ let r = offset..offset + e. size ( ) ;
104+ for nc in & self . non_covered {
105+ let o = nc. offset ;
106+ let e = o + nc. data . len ( ) ;
107+ if r. contains ( & o) || r. contains ( & e) {
108+ println ! ( "Drop data not covered by FPT and now overlapping: {o:08x}..{e:08x}" ) ;
109+ } else {
110+ non_covered. push ( nc. clone ( ) ) ;
111+ }
112+ }
113+ self . non_covered = non_covered;
114+
115+ // Update partition table entry
116+ for e in & mut self . fpt . entries {
117+ if e. name ( ) == n {
118+ e. set_offset ( offset as u32 ) ;
119+ }
120+ }
121+
122+ Ok ( ( ) )
123+ } else {
124+ Err ( "no FPT partitions found" . into ( ) )
125+ }
126+ }
127+
66128 /// Clear out fully removable partitions and adjust FPT
67129 pub fn to_vec ( & self ) -> Vec < u8 > {
68130 let debug = true ;
0 commit comments