@@ -703,7 +703,8 @@ impl CrosEc {
703703 /// | 3C000 | 3FFFF | 04000 | Preserved |
704704 /// | 40000 | 3C000 | 39000 | RO Region |
705705 /// | 79000 | 79FFF | 01000 | Flash Flags |
706- pub fn reflash ( & self , data : & [ u8 ] , ft : EcFlashType ) -> EcResult < ( ) > {
706+ pub fn reflash ( & self , data : & [ u8 ] , ft : EcFlashType , dry_run : bool ) -> EcResult < ( ) > {
707+ let mut res = Ok ( ( ) ) ;
707708 if ft == EcFlashType :: Full || ft == EcFlashType :: Ro {
708709 if let Some ( version) = ec_binary:: read_ec_version ( data, true ) {
709710 println ! ( "EC RO Version in File: {:?}" , version. version) ;
@@ -723,9 +724,21 @@ impl CrosEc {
723724 }
724725 }
725726
726- if ft == EcFlashType :: Full || ft == EcFlashType :: Ro {
727- println ! ( "For safety reasons flashing RO firmware is disabled." ) ;
728- return Ok ( ( ) ) ;
727+ // Determine recommended flash parameters
728+ let info = EcRequestFlashInfo { } . send_command ( self ) ?;
729+
730+ // Check that our hardcoded offsets are valid for the available flash
731+ if FLASH_RO_SIZE + FLASH_RW_SIZE > info. flash_size {
732+ return Err ( EcError :: DeviceError ( format ! (
733+ "RO+RW larger than flash 0x{:X}" ,
734+ { info. flash_size }
735+ ) ) ) ;
736+ }
737+ if FLASH_RW_BASE + FLASH_RW_SIZE > info. flash_size {
738+ return Err ( EcError :: DeviceError ( format ! (
739+ "RW overruns end of flash 0x{:X}" ,
740+ { info. flash_size }
741+ ) ) ) ;
729742 }
730743
731744 println ! ( "Unlocking flash" ) ;
@@ -740,80 +753,109 @@ impl CrosEc {
740753 if ft == EcFlashType :: Full || ft == EcFlashType :: Rw {
741754 let rw_data = & data[ FLASH_RW_BASE as usize ..( FLASH_RW_BASE + FLASH_RW_SIZE ) as usize ] ;
742755
743- println ! ( "Erasing RW region" ) ;
744- self . erase_ec_flash ( FLASH_BASE + FLASH_RW_BASE , FLASH_RW_SIZE ) ?;
745-
746- println ! ( "Writing RW region" ) ;
747- self . write_ec_flash ( FLASH_BASE + FLASH_RW_BASE , rw_data) ?;
756+ println ! (
757+ "Erasing RW region{}" ,
758+ if dry_run { " (DRY RUN)" } else { "" }
759+ ) ;
760+ self . erase_ec_flash (
761+ FLASH_BASE + FLASH_RW_BASE ,
762+ FLASH_RW_SIZE ,
763+ dry_run,
764+ info. erase_block_size ,
765+ ) ?;
766+ println ! ( " Done" ) ;
767+
768+ println ! (
769+ "Writing RW region{}" ,
770+ if dry_run { " (DRY RUN)" } else { "" }
771+ ) ;
772+ self . write_ec_flash ( FLASH_BASE + FLASH_RW_BASE , rw_data, dry_run) ?;
773+ println ! ( " Done" ) ;
748774
749775 println ! ( "Verifying RW region" ) ;
750776 let flash_rw_data = self . read_ec_flash ( FLASH_BASE + FLASH_RW_BASE , FLASH_RW_SIZE ) ?;
751777 if rw_data == flash_rw_data {
752- println ! ( "RW verify success" ) ;
778+ println ! ( " RW verify success" ) ;
753779 } else {
754- println ! ( "RW verify fail" ) ;
780+ error ! ( "RW verify fail!" ) ;
781+ res = Err ( EcError :: DeviceError ( "RW verify fail!" . to_string ( ) ) ) ;
755782 }
756783 }
757784
758785 if ft == EcFlashType :: Full || ft == EcFlashType :: Ro {
759786 let ro_data = & data[ FLASH_RO_BASE as usize ..( FLASH_RO_BASE + FLASH_RO_SIZE ) as usize ] ;
760787
761788 println ! ( "Erasing RO region" ) ;
762- self . erase_ec_flash ( FLASH_BASE + FLASH_RO_BASE , FLASH_RO_SIZE ) ?;
789+ self . erase_ec_flash (
790+ FLASH_BASE + FLASH_RO_BASE ,
791+ FLASH_RO_SIZE ,
792+ dry_run,
793+ info. erase_block_size ,
794+ ) ?;
795+ println ! ( " Done" ) ;
763796
764797 println ! ( "Writing RO region" ) ;
765- self . write_ec_flash ( FLASH_BASE + FLASH_RO_BASE , ro_data) ?;
798+ self . write_ec_flash ( FLASH_BASE + FLASH_RO_BASE , ro_data, dry_run) ?;
799+ println ! ( " Done" ) ;
766800
767801 println ! ( "Verifying RO region" ) ;
768802 let flash_ro_data = self . read_ec_flash ( FLASH_BASE + FLASH_RO_BASE , FLASH_RO_SIZE ) ?;
769803 if ro_data == flash_ro_data {
770- println ! ( "RO verify success" ) ;
804+ println ! ( " RO verify success" ) ;
771805 } else {
772- println ! ( "RO verify fail" ) ;
806+ error ! ( "RO verify fail!" ) ;
807+ res = Err ( EcError :: DeviceError ( "RW verify fail!" . to_string ( ) ) ) ;
773808 }
774809 }
775810
776811 println ! ( "Locking flash" ) ;
777812 self . flash_notify ( MecFlashNotify :: AccessSpiDone ) ?;
778813 self . flash_notify ( MecFlashNotify :: FirmwareDone ) ?;
779814
780- println ! ( "Flashing EC done. You can reboot the EC now" ) ;
781- // TODO: Should we force a reboot if currently running one was reflashed?
815+ if res. is_ok ( ) {
816+ println ! ( "Flashing EC done. You can reboot the EC now" ) ;
817+ }
782818
783- Ok ( ( ) )
819+ res
784820 }
785821
786822 /// Write a big section of EC flash. Must be unlocked already
787- fn write_ec_flash ( & self , addr : u32 , data : & [ u8 ] ) -> EcResult < ( ) > {
788- let info = EcRequestFlashInfo { } . send_command ( self ) ? ;
789- println ! ( "Flash info: {:?}" , info ) ;
823+ fn write_ec_flash ( & self , addr : u32 , data : & [ u8 ] , dry_run : bool ) -> EcResult < ( ) > {
824+ // TODO: Use flash info to help guide ideal chunk size
825+ // let info = EcRequestFlashInfo {}.send_command(self)? ;
790826 //let chunk_size = ((0x80 / info.write_ideal_size) * info.write_ideal_size) as usize;
827+
791828 let chunk_size = 0x80 ;
792829
793830 let chunks = data. len ( ) / chunk_size;
831+ println ! (
832+ " Will write flash from 0x{:X} to 0x{:X} in {}*{}B chunks" ,
833+ addr,
834+ data. len( ) ,
835+ chunks,
836+ chunk_size
837+ ) ;
794838 for chunk_no in 0 ..chunks {
795839 let offset = chunk_no * chunk_size;
796840 // Current chunk might be smaller if it's the last
797841 let cur_chunk_size = std:: cmp:: min ( chunk_size, data. len ( ) - chunk_no * chunk_size) ;
798842
799843 if chunk_no % 100 == 0 {
800- println ! ( ) ;
801- print ! (
802- "Writing chunk {:>4}/{:>4} ({:>6}/{:>6}): X" ,
803- chunk_no,
804- chunks,
805- offset,
806- cur_chunk_size * chunks
807- ) ;
844+ if chunk_no != 0 {
845+ println ! ( ) ;
846+ }
847+ print ! ( " Chunk {:>4}: X" , chunk_no) ;
808848 } else {
809849 print ! ( "X" ) ;
810850 }
811851
812852 let chunk = & data[ offset..offset + cur_chunk_size] ;
813- let res = self . write_ec_flash_chunk ( addr + offset as u32 , chunk) ;
814- if let Err ( err) = res {
815- println ! ( " Failed to write chunk: {:?}" , err) ;
816- return Err ( err) ;
853+ if !dry_run {
854+ let res = self . write_ec_flash_chunk ( addr + offset as u32 , chunk) ;
855+ if let Err ( err) = res {
856+ println ! ( " Failed to write chunk: {:?}" , err) ;
857+ return Err ( err) ;
858+ }
817859 }
818860 }
819861 println ! ( ) ;
@@ -831,8 +873,38 @@ impl CrosEc {
831873 . send_command_extra ( self , data)
832874 }
833875
834- fn erase_ec_flash ( & self , offset : u32 , size : u32 ) -> EcResult < ( ) > {
835- EcRequestFlashErase { offset, size } . send_command ( self )
876+ fn erase_ec_flash (
877+ & self ,
878+ offset : u32 ,
879+ size : u32 ,
880+ dry_run : bool ,
881+ chunk_size : u32 ,
882+ ) -> EcResult < ( ) > {
883+ // Erasing a big section takes too long sometimes and the linux kernel driver times out, so
884+ // split it up into chunks.
885+ let mut cur_offset = offset;
886+
887+ while cur_offset < offset + size {
888+ let rem_size = offset + size - cur_offset;
889+ let cur_size = if rem_size < chunk_size {
890+ rem_size
891+ } else {
892+ chunk_size
893+ } ;
894+ debug ! (
895+ "EcRequestFlashErase (0x{:05X}, 0x{:05X})" ,
896+ cur_offset, cur_size
897+ ) ;
898+ if !dry_run {
899+ EcRequestFlashErase {
900+ offset : cur_offset,
901+ size : cur_size,
902+ }
903+ . send_command ( self ) ?;
904+ }
905+ cur_offset += chunk_size;
906+ }
907+ Ok ( ( ) )
836908 }
837909
838910 pub fn flash_notify ( & self , flag : MecFlashNotify ) -> EcResult < ( ) > {
0 commit comments