11use ecflash:: { Ec , EcFile , EcFlash } ;
22use ectool:: {
33 Firmware ,
4+ Spi ,
5+ SpiRom ,
6+ SpiTarget ,
47 Timeout ,
58} ;
69use std:: {
@@ -39,6 +42,96 @@ impl Timeout for UefiTimeout {
3942 }
4043}
4144
45+ unsafe fn flash_read < S : Spi > ( spi : & mut SpiRom < S , UefiTimeout > , rom : & mut [ u8 ] , sector_size : usize ) -> core:: result:: Result < ( ) , ectool:: Error > {
46+ let mut address = 0 ;
47+ while address < rom. len ( ) {
48+ print ! ( "\r SPI Read {}K" , address / 1024 ) ;
49+ let next_address = address + sector_size;
50+ let count = spi. read_at ( address as u32 , & mut rom[ address..next_address] ) ?;
51+ if count != sector_size {
52+ println ! ( "\n count {} did not match sector size {}" , count, sector_size) ;
53+ return Err ( ectool:: Error :: Verify ) ;
54+ }
55+ address = next_address;
56+ }
57+ println ! ( "\r SPI Read {}K" , address / 1024 ) ;
58+ Ok ( ( ) )
59+ }
60+
61+ unsafe fn flash_inner ( ec : & mut ectool:: Ec < UefiTimeout > , firmware : & Firmware , target : SpiTarget , scratch : bool ) -> core:: result:: Result < ( ) , ectool:: Error > {
62+ let rom_size = 128 * 1024 ;
63+ let sector_size = 1024 ;
64+
65+ let mut new_rom = firmware. data . to_vec ( ) ;
66+ while new_rom. len ( ) < rom_size {
67+ new_rom. push ( 0xFF ) ;
68+ }
69+
70+ let mut spi_bus = ec. spi ( target, scratch) ?;
71+ let mut spi = SpiRom :: new (
72+ & mut spi_bus,
73+ UefiTimeout :: new ( 1_000_000 )
74+ ) ;
75+
76+ let mut rom = vec ! [ 0xFF ; rom_size] ;
77+ flash_read ( & mut spi, & mut rom, sector_size) ?;
78+
79+ // Program chip, sector by sector
80+ //TODO: write signature last
81+ {
82+ let mut address = 0 ;
83+ while address < rom_size {
84+ print ! ( "\r SPI Write {}K" , address / 1024 ) ;
85+
86+ let next_address = address + sector_size;
87+
88+ let mut matches = true ;
89+ let mut erased = true ;
90+ let mut new_erased = true ;
91+ for i in address..next_address {
92+ if rom[ i] != new_rom[ i] {
93+ matches = false ;
94+ }
95+ if rom[ i] != 0xFF {
96+ erased = false ;
97+ }
98+ if new_rom[ i] != 0xFF {
99+ new_erased = false ;
100+ }
101+ }
102+
103+ if ! matches {
104+ if ! erased {
105+ spi. erase_sector ( address as u32 ) ?;
106+ }
107+ if ! new_erased {
108+ let count = spi. write_at ( address as u32 , & new_rom[ address..next_address] ) ?;
109+ if count != sector_size {
110+ println ! ( "\n Write count {} did not match sector size {}" , count, sector_size) ;
111+ return Err ( ectool:: Error :: Verify ) ;
112+ }
113+ }
114+ }
115+
116+ address = next_address;
117+ }
118+ println ! ( "\r SPI Write {}K" , address / 1024 ) ;
119+
120+ // Verify chip write
121+ flash_read ( & mut spi, & mut rom, sector_size) ?;
122+ for i in 0 ..rom. len ( ) {
123+ if rom[ i] != new_rom[ i] {
124+ println ! ( "Failed to program: {:X} is {:X} instead of {:X}" , i, rom[ i] , new_rom[ i] ) ;
125+ return Err ( ectool:: Error :: Verify ) ;
126+ }
127+ }
128+ }
129+
130+ println ! ( "Successfully programmed SPI ROM" ) ;
131+
132+ Ok ( ( ) )
133+ }
134+
42135enum EcKind {
43136 System76 ( ectool:: Ec < UefiTimeout > ) ,
44137 Legacy ( EcFlash ) ,
@@ -47,7 +140,7 @@ enum EcKind {
47140
48141impl EcKind {
49142 unsafe fn new ( primary : bool ) -> Self {
50- if let Ok ( ec) = ectool:: Ec :: new ( primary , UefiTimeout :: new ( 100_000 ) ) {
143+ if let Ok ( ec) = ectool:: Ec :: new ( UefiTimeout :: new ( 100_000 ) ) {
51144 return EcKind :: System76 ( ec) ;
52145 }
53146
@@ -98,7 +191,7 @@ impl EcKind {
98191 match self {
99192 EcKind :: System76 ( _) => {
100193 if let Some ( firmware) = Firmware :: new ( & data) {
101- if let Ok ( string) = str:: from_utf8 ( firmware. version ) {
194+ if let Ok ( string) = str:: from_utf8 ( firmware. board ) {
102195 return string. to_string ( ) ;
103196 }
104197 }
@@ -136,10 +229,61 @@ impl EcComponent {
136229 }
137230
138231 pub fn validate_data ( & self , data : Vec < u8 > ) -> bool {
232+ let firmware_model = self . ec . firmware_model ( data) ;
139233 ! self . model . is_empty ( ) &&
140234 ! self . version . is_empty ( ) &&
141- self . ec . firmware_model ( data) == self . model
235+ firmware_model == self . model
236+ }
237+ }
238+
239+ unsafe fn flash ( firmware_data : & [ u8 ] ) -> core:: result:: Result < ( ) , ectool:: Error > {
240+ let target = SpiTarget :: Main ;
241+ let scratch = true ;
242+
243+ let firmware = match Firmware :: new ( & firmware_data) {
244+ Some ( some) => some,
245+ None => {
246+ println ! ( "failed to parse firmware" ) ;
247+ return Err ( ectool:: Error :: Verify ) ;
248+ }
249+ } ;
250+ println ! ( "file board: {:?}" , str :: from_utf8( firmware. board) ) ;
251+ println ! ( "file version: {:?}" , str :: from_utf8( firmware. version) ) ;
252+
253+ let mut ec = ectool:: Ec :: new ( UefiTimeout :: new ( 1_000_000 ) ) ?;
254+
255+ {
256+ let mut data = [ 0 ; 256 ] ;
257+ let size = ec. board ( & mut data) ?;
258+
259+ let ec_board = & data[ ..size] ;
260+ println ! ( "ec board: {:?}" , str :: from_utf8( ec_board) ) ;
261+
262+ if ec_board != firmware. board {
263+ println ! ( "file board does not match ec board" ) ;
264+ return Err ( ectool:: Error :: Verify ) ;
265+ }
266+ }
267+
268+ {
269+ let mut data = [ 0 ; 256 ] ;
270+ let size = ec. version ( & mut data) ?;
271+
272+ let ec_version = & data[ ..size] ;
273+ println ! ( "ec version: {:?}" , str :: from_utf8( ec_version) ) ;
142274 }
275+
276+ let res = flash_inner ( & mut ec, & firmware, target, scratch) ;
277+ println ! ( "Result: {:X?}" , res) ;
278+
279+ if scratch {
280+ println ! ( "System will shut off in 5 seconds" ) ;
281+ let _ = ( std:: system_table ( ) . BootServices . Stall ) ( 5_000_000 ) ;
282+
283+ ec. reset ( ) ?;
284+ }
285+
286+ res
143287}
144288
145289impl Component for EcComponent {
@@ -175,8 +319,14 @@ impl Component for EcComponent {
175319 fn flash ( & self ) -> Result < ( ) > {
176320 match & self . ec {
177321 EcKind :: System76 ( _) => {
178- println ! ( "{} Failed to flash EcKind::System76" , self . name( ) ) ;
179- return Err ( Error :: DeviceError ) ;
322+ let firmware_data = load ( self . path ( ) ) ?;
323+ match unsafe { flash ( & firmware_data) } {
324+ Ok ( ( ) ) => Ok ( ( ) ) ,
325+ Err ( err) => {
326+ println ! ( "{} Flash Error: {:X?}" , self . name( ) , err) ;
327+ Err ( Error :: DeviceError )
328+ }
329+ }
180330 } ,
181331 EcKind :: Legacy ( _) => {
182332 find ( FIRMWARENSH ) ?;
@@ -188,16 +338,16 @@ impl Component for EcComponent {
188338 } ;
189339
190340 let status = shell ( & cmd) ?;
191- if status != 0 {
341+ if status == 0 {
342+ Ok ( ( ) )
343+ } else {
192344 println ! ( "{} Flash Error: {}" , self . name( ) , status) ;
193- return Err ( Error :: DeviceError ) ;
345+ Err ( Error :: DeviceError )
194346 }
195-
196- Ok ( ( ) )
197347 } ,
198348 EcKind :: Unknown => {
199349 println ! ( "{} Failed to flash EcKind::Unknown" , self . name( ) ) ;
200- return Err ( Error :: DeviceError ) ;
350+ Err ( Error :: DeviceError )
201351 } ,
202352 }
203353 }
0 commit comments