@@ -12,7 +12,7 @@ use crate::os_specific;
12
12
use crate :: smbios;
13
13
#[ cfg( feature = "uefi" ) ]
14
14
use crate :: uefi:: shell_get_execution_break_flag;
15
- use crate :: util:: assert_win_len ;
15
+ use crate :: util:: { self , Platform } ;
16
16
17
17
use log:: Level ;
18
18
use num_derive:: FromPrimitive ;
@@ -57,6 +57,8 @@ const FLASH_RO_BASE: u32 = 0x0;
57
57
const FLASH_RO_SIZE : u32 = 0x3C000 ;
58
58
const FLASH_RW_BASE : u32 = 0x40000 ;
59
59
const FLASH_RW_SIZE : u32 = 0x39000 ;
60
+ const MEC_FLASH_FLAGS : u32 = 0x80000 ;
61
+ const NPC_FLASH_FLAGS : u32 = 0x7F000 ;
60
62
const FLASH_PROGRAM_OFFSET : u32 = 0x1000 ;
61
63
62
64
#[ derive( Clone , Debug , PartialEq ) ]
@@ -116,6 +118,13 @@ pub enum EcResponseStatus {
116
118
Busy = 16 ,
117
119
}
118
120
121
+ pub fn has_mec ( ) -> bool {
122
+ !matches ! (
123
+ smbios:: get_platform( ) . unwrap( ) ,
124
+ Platform :: Framework13Amd | Platform :: Framework16
125
+ )
126
+ }
127
+
119
128
pub trait CrosEcDriver {
120
129
fn read_memory ( & self , offset : u16 , length : u16 ) -> Option < Vec < u8 > > ;
121
130
fn send_command ( & self , command : u16 , command_version : u8 , data : & [ u8 ] ) -> EcResult < Vec < u8 > > ;
@@ -270,7 +279,7 @@ impl CrosEc {
270
279
let limits = & [ ChargeLimitControlModes :: Set as u8 , max, min] ;
271
280
let data = self . send_command ( EcCommands :: ChargeLimitControl as u16 , 0 , limits) ?;
272
281
273
- assert_win_len ( data. len ( ) , 0 ) ;
282
+ util :: assert_win_len ( data. len ( ) , 0 ) ;
274
283
275
284
Ok ( ( ) )
276
285
}
@@ -298,7 +307,7 @@ impl CrosEc {
298
307
let limits = & [ level as u8 , 0x00 ] ;
299
308
let data = self . send_command ( EcCommands :: FpLedLevelControl as u16 , 0 , limits) ?;
300
309
301
- assert_win_len ( data. len ( ) , 0 ) ;
310
+ util :: assert_win_len ( data. len ( ) , 0 ) ;
302
311
303
312
Ok ( ( ) )
304
313
}
@@ -594,39 +603,122 @@ impl CrosEc {
594
603
}
595
604
596
605
pub fn test_ec_flash_read ( & self ) -> EcResult < ( ) > {
606
+ let mut res = Ok ( ( ) ) ;
597
607
// TODO: Perhaps we could have some more global flag to avoid setting and unsetting that ever time
598
608
self . flash_notify ( MecFlashNotify :: AccessSpi ) ?;
599
609
600
- println ! ( " EC Test" ) ;
601
- println ! ( " Read first row of flash." ) ;
602
- // Make sure we can read a full flash row
610
+ // ===== Test 1 =====
611
+ // Read the first row of flash.
612
+ // It's the beginning of RO firmware
613
+ println ! ( " Read first row of flash (RO FW)" ) ;
603
614
let data = self . read_ec_flash ( 0 , 0x80 ) . unwrap ( ) ;
604
- if data[ 0 ..4 ] != [ 0x10 , 0x00 , 0x00 , 0xF7 ] {
615
+
616
+ debug ! ( "{:02X?}" , data) ;
617
+ println ! ( " {:02X?}" , & data[ ..8 ] ) ;
618
+ if data. iter ( ) . all ( |x| * x == 0xFF ) {
619
+ println ! ( " Erased!" ) ;
620
+ }
621
+
622
+ // 4 magic bytes at the beginning
623
+ let legacy_start = [ 0x10 , 0x00 , 0x00 , 0xF7 ] ;
624
+ // TODO: Does zephyr always start like this?
625
+ let zephyr_start = [ 0x5E , 0x4D , 0x3B , 0x2A ] ;
626
+ if data[ 0 ..4 ] != legacy_start && data[ 0 ..4 ] != zephyr_start {
605
627
println ! ( " INVALID start" ) ;
606
- return Err ( EcError :: DeviceError ( "INVALID start" . to_string ( ) ) ) ;
628
+ res = Err ( EcError :: DeviceError ( "INVALID start" . to_string ( ) ) ) ;
607
629
}
608
- if !data[ 4 ..] . iter ( ) . all ( |x| * x == 0xFF ) {
630
+ // Legacy EC is all 0xFF until the end of the row
631
+ // Zephyr EC I'm not quite sure but it has a section of 0x00
632
+ let legacy_comp = !data[ 4 ..] . iter ( ) . all ( |x| * x == 0xFF ) ;
633
+ let zephyr_comp = !data[ 0x20 ..0x40 ] . iter ( ) . all ( |x| * x == 0x00 ) ;
634
+ if legacy_comp && zephyr_comp {
609
635
println ! ( " INVALID end" ) ;
610
- return Err ( EcError :: DeviceError ( "INVALID end" . to_string ( ) ) ) ;
636
+ res = Err ( EcError :: DeviceError ( "INVALID end" . to_string ( ) ) ) ;
637
+ }
638
+
639
+ // ===== Test 2 =====
640
+ // DISABLED
641
+ // TODO: Haven't figure out a pattern yet
642
+ //
643
+ // Read the first row of the second half of flash
644
+ // It's the beginning of RW firmware
645
+ println ! ( " Read first row of RW FW" ) ;
646
+ let data = self . read_ec_flash ( 0x40000 , 0x80 ) . unwrap ( ) ;
647
+
648
+ println ! ( " {:02X?}" , & data[ ..8 ] ) ;
649
+ if data. iter ( ) . all ( |x| * x == 0xFF ) {
650
+ println ! ( " Erased!" ) ;
651
+ res = Err ( EcError :: DeviceError ( "RW Erased" . to_string ( ) ) ) ;
652
+ }
653
+
654
+ // TODO: How can we identify if the RO image is valid?
655
+ // //debug!("Expected TODO and rest all FF");
656
+ // debug!("Expecting 80 7D 0C 20 and 0x20-0x2C all 00");
657
+ // let legacy_start = []; // TODO
658
+ // let zephyr_start = [0x80, 0x7D, 0x0C, 0x20];
659
+ // if data[0..4] != legacy_start && data[0..4] != zephyr_start {
660
+ // println!(" INVALID start");
661
+ // res = Err(EcError::DeviceError("INVALID start".to_string()));
662
+ // }
663
+ // let legacy_comp = !data[4..].iter().all(|x| *x == 0xFF);
664
+ // let zephyr_comp = !data[0x20..0x2C].iter().all(|x| *x == 0x00);
665
+ // if legacy_comp && zephyr_comp {
666
+ // println!(" INVALID end");
667
+ // res = Err(EcError::DeviceError("INVALID end".to_string()));
668
+ // }
669
+
670
+ // ===== Test 3 =====
671
+ //
672
+ // MEC EC has program code at 0x1000 with magic bytes that spell
673
+ // MCHP (Microchip) in ASCII backwards.
674
+ // Everything before is probably a header.
675
+ // TODO: I don't think there are magic bytes on zephyr firmware
676
+ //
677
+ if has_mec ( ) {
678
+ println ! ( " Check MCHP magic byte at start of firmware code." ) ;
679
+ // Make sure we can read at an offset and with arbitrary length
680
+ let data = self . read_ec_flash ( FLASH_PROGRAM_OFFSET , 16 ) . unwrap ( ) ;
681
+ debug ! ( "Expecting beginning with 50 48 43 4D ('PHCM' in ASCII)" ) ;
682
+ debug ! ( "{:02X?}" , data) ;
683
+ println ! (
684
+ " {:02X?} ASCII:{:?}" ,
685
+ & data[ ..4 ] ,
686
+ core:: str :: from_utf8( & data[ ..4 ] )
687
+ ) ;
688
+
689
+ if data[ 0 ..4 ] != [ 0x50 , 0x48 , 0x43 , 0x4D ] {
690
+ println ! ( " INVALID: {:02X?}" , & data[ 0 ..3 ] ) ;
691
+ res = Err ( EcError :: DeviceError ( format ! (
692
+ "INVALID: {:02X?}" ,
693
+ & data[ 0 ..3 ]
694
+ ) ) ) ;
695
+ }
611
696
}
612
- debug ! ( "Expected 10 00 00 F7 and rest all FF" ) ;
613
- debug ! ( "{:02X?}" , data) ;
614
697
615
- println ! ( " Read first 16 bytes of firmware." ) ;
616
- // Make sure we can read at an offset and with arbitrary length
617
- let data = self . read_ec_flash ( FLASH_PROGRAM_OFFSET , 16 ) . unwrap ( ) ;
618
- if data[ 0 ..4 ] != [ 0x50 , 0x48 , 0x43 , 0x4D ] {
619
- println ! ( " INVALID: {:02X?}" , & data[ 0 ..3 ] ) ;
620
- return Err ( EcError :: DeviceError ( format ! (
621
- "INVALID: {:02X?}" ,
622
- & data[ 0 ..3 ]
623
- ) ) ) ;
624
- }
625
- debug ! ( "Expected beginning with 50 48 43 4D ('PHCM' in ASCII)" ) ;
626
- debug ! ( "{:02X?}" , data) ;
698
+ // ===== Test 4 =====
699
+ println ! ( " Read flash flags" ) ;
700
+ let data = if has_mec ( ) {
701
+ self . read_ec_flash ( MEC_FLASH_FLAGS , 0x80 ) . unwrap ( )
702
+ } else {
703
+ self . read_ec_flash ( NPC_FLASH_FLAGS , 0x80 ) . unwrap ( )
704
+ } ;
705
+ let flash_flags_magic = [ 0xA3 , 0xF1 , 0x00 , 0x00 ] ;
706
+ let flash_flags_ver = [ 0x01 , 0x0 , 0x00 , 0x00 ] ;
707
+ // All 0xFF if just reflashed and not reinitialized by EC
708
+ if data[ 0 ..4 ] == flash_flags_magic && data[ 8 ..12 ] == flash_flags_ver {
709
+ println ! ( " Valid flash flags" ) ;
710
+ } else if data. iter ( ) . all ( |x| * x == 0xFF ) {
711
+ println ! ( " Erased flash flags" ) ;
712
+ res = Err ( EcError :: DeviceError ( "Erased flash flags" . to_string ( ) ) ) ;
713
+ } else {
714
+ println ! ( " INVALID flash flags: {:02X?}" , & data[ 0 ..12 ] ) ;
715
+ // TODO: Disable error until I confirm flash flags on MEC
716
+ // res = Err(EcError::DeviceError("INVALID flash flags".to_string()));
717
+ }
627
718
628
719
self . flash_notify ( MecFlashNotify :: AccessSpiDone ) ?;
629
- Ok ( ( ) )
720
+
721
+ res
630
722
}
631
723
632
724
/// Requests recent console output from EC and constantly asks for more
0 commit comments