1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// SPDX-License-Identifier: MIT

use crate::{
    Error,
    Pmc,
    SuperIo,
    Timeout,
};

/// Run some EC commands on previous proprietary firmware
pub struct EcLegacy<T: Timeout> {
    pub pmc: Pmc<T>,
}

impl<T: Timeout> EcLegacy<T> {
    /// Probes for EC using direct hardware access. Unsafe due to no mutual exclusion
    pub unsafe fn new(primary: bool, timeout: T) -> Result<Self, Error> {
        let mut sio = SuperIo::new(if primary { 0x2E } else { 0x4E });

        let id =
            (sio.read(0x20) as u16) << 8 |
            (sio.read(0x21) as u16);

        match id {
            0x5570 | 0x8587 => (),
            _ => return Err(Error::SuperIoId(id)),
        }

        //TODO: is there a good way to probe?

        Ok(Self {
            pmc: Pmc::new(if primary { 0x62 } else { 0x68 }, timeout),
        })
    }

    /// Read the EC firmware project, which uniquely identifies the board
    pub unsafe fn project(&mut self, data: &mut [u8]) -> Result<usize, Error> {
        let mut i = 0;
        self.pmc.command(0x92)?;
        while i < data.len() {
            data[i] = self.pmc.read()?;
            if data[i] == b'$' {
                break;
            }
            i += 1;
        }
        Ok(i)
    }

    /// Read the EC firmware version
    pub unsafe fn version(&mut self, data: &mut [u8]) -> Result<usize, Error> {
        // Prepend `1.` to version string
        let mut i = 0;
        if i < data.len() {
            data[i] = b'1';
            i += 1;
        }
        if i < data.len() {
            data[i] = b'.';
            i += 1;
        }

        self.pmc.command(0x93)?;
        while i < data.len() {
            data[i] = self.pmc.read()?;
            if data[i] == b'$' {
                break;
            }
            i += 1;
        }
        Ok(i)
    }
}