Skip to content

Commit 72e0acb

Browse files
Merge pull request #31 from FrameworkComputer/custom-platform
Allow customizing platform if not matched
2 parents ac83be8 + f5bd38e commit 72e0acb

File tree

7 files changed

+188
-21
lines changed

7 files changed

+188
-21
lines changed

framework_lib/src/ccgx/device.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! Communicate with CCGX (CCG5, CCG6) PD controllers
1+
//! Communicate with CCGX (CCG5, CCG6, CCG8) PD controllers
22
//!
33
//! The current implementation talks to them by tunneling I2C through EC host commands.
44
@@ -41,9 +41,12 @@ impl PdPort {
4141
let platform = &(*config).as_ref().unwrap().platform;
4242

4343
match (platform, self) {
44+
(Platform::GenericFramework((left, _), _, _), PdPort::Left01) => *left,
45+
(Platform::GenericFramework((_, right), _, _), PdPort::Right23) => *right,
46+
// Framework AMD Platforms (CCG8)
4447
(Platform::Framework13Amd | Platform::Framework16, PdPort::Left01) => 0x42,
4548
(Platform::Framework13Amd | Platform::Framework16, PdPort::Right23) => 0x40,
46-
// Intel Platforms
49+
// Framework Intel Platforms (CCG5 and CCG6)
4750
(_, PdPort::Left01) => 0x08,
4851
(_, PdPort::Right23) => 0x40,
4952
}
@@ -55,11 +58,11 @@ impl PdPort {
5558
let platform = &(*config).as_ref().unwrap().platform;
5659

5760
Ok(match (platform, self) {
61+
(Platform::GenericFramework(_, (left, _), _), PdPort::Left01) => *left,
62+
(Platform::GenericFramework(_, (_, right), _), PdPort::Right23) => *right,
5863
(Platform::IntelGen11, _) => 6,
59-
(Platform::IntelGen12, PdPort::Left01) => 6,
60-
(Platform::IntelGen12, PdPort::Right23) => 7,
61-
(Platform::IntelGen13, PdPort::Left01) => 6,
62-
(Platform::IntelGen13, PdPort::Right23) => 7,
64+
(Platform::IntelGen12 | Platform::IntelGen13, PdPort::Left01) => 6,
65+
(Platform::IntelGen12 | Platform::IntelGen13, PdPort::Right23) => 7,
6366
(Platform::Framework13Amd | Platform::Framework16, PdPort::Left01) => 1,
6467
(Platform::Framework13Amd | Platform::Framework16, PdPort::Right23) => 2,
6568
// (_, _) => Err(EcError::DeviceError(format!(

framework_lib/src/chromium_ec/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ pub enum EcResponseStatus {
120120
}
121121

122122
pub fn has_mec() -> bool {
123+
let platform = smbios::get_platform().unwrap();
124+
if let Platform::GenericFramework(_, _, has_mec) = platform {
125+
return has_mec;
126+
}
127+
123128
!matches!(
124129
smbios::get_platform().unwrap(),
125130
Platform::Framework13Amd | Platform::Framework16

framework_lib/src/commandline/clap_std.rs

+43
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,21 @@ struct ClapCli {
140140
#[arg(long)]
141141
driver: Option<CrosEcDriverType>,
142142

143+
/// Specify I2C addresses of the PD chips (Advanced)
144+
#[clap(number_of_values = 2, requires("pd_ports"), requires("has_mec"))]
145+
#[arg(long)]
146+
pd_addrs: Vec<u16>,
147+
148+
/// Specify I2C ports of the PD chips (Advanced)
149+
#[clap(number_of_values = 2, requires("pd_addrs"), requires("has_mec"))]
150+
#[arg(long)]
151+
pd_ports: Vec<u8>,
152+
153+
/// Specify the type of EC chip (MEC/MCHP or other)
154+
#[clap(requires("pd_addrs"), requires("pd_ports"))]
155+
#[arg(long)]
156+
has_mec: Option<bool>,
157+
143158
/// Run self-test to check if interaction with EC is possible
144159
#[arg(long, short)]
145160
test: bool,
@@ -149,6 +164,31 @@ struct ClapCli {
149164
pub fn parse(args: &[String]) -> Cli {
150165
let args = ClapCli::parse_from(args);
151166

167+
let pd_addrs = match args.pd_addrs.len() {
168+
2 => Some((args.pd_addrs[0], args.pd_addrs[1])),
169+
0 => None,
170+
_ => {
171+
// Actually unreachable, checked by clap
172+
println!(
173+
"Must provide exactly to PD Addresses. Provided: {:?}",
174+
args.pd_addrs
175+
);
176+
std::process::exit(1);
177+
}
178+
};
179+
let pd_ports = match args.pd_ports.len() {
180+
2 => Some((args.pd_ports[0], args.pd_ports[1])),
181+
0 => None,
182+
_ => {
183+
// Actually unreachable, checked by clap
184+
println!(
185+
"Must provide exactly to PD Ports. Provided: {:?}",
186+
args.pd_ports
187+
);
188+
std::process::exit(1);
189+
}
190+
};
191+
152192
Cli {
153193
verbosity: args.verbosity.log_level_filter(),
154194
versions: args.versions,
@@ -199,6 +239,9 @@ pub fn parse(args: &[String]) -> Cli {
199239
reboot_ec: args.reboot_ec,
200240
hash: args.hash.map(|x| x.into_os_string().into_string().unwrap()),
201241
driver: args.driver,
242+
pd_addrs,
243+
pd_ports,
244+
has_mec: args.has_mec,
202245
test: args.test,
203246
// TODO: Set help. Not very important because Clap handles this by itself
204247
help: false,

framework_lib/src/commandline/mod.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ use crate::smbios::{dmidecode_string_val, get_smbios, is_framework};
4747
#[cfg(feature = "uefi")]
4848
use crate::uefi::enable_page_break;
4949
use crate::util;
50+
use crate::util::Config;
5051
#[cfg(not(feature = "uefi"))]
5152
use hidapi::HidApi;
5253
use sha2::{Digest, Sha256, Sha384, Sha512};
@@ -147,6 +148,9 @@ pub struct Cli {
147148
pub console: Option<ConsoleArg>,
148149
pub reboot_ec: Option<RebootEcArg>,
149150
pub hash: Option<String>,
151+
pub pd_addrs: Option<(u16, u16)>,
152+
pub pd_ports: Option<(u8, u8)>,
153+
pub has_mec: Option<bool>,
150154
pub help: bool,
151155
pub info: bool,
152156
// UEFI only
@@ -469,6 +473,16 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
469473
.init();
470474
}
471475

476+
// Must be run before any application code to set the config
477+
if args.pd_addrs.is_some() && args.pd_ports.is_some() && args.has_mec.is_some() {
478+
let platform = util::Platform::GenericFramework(
479+
args.pd_addrs.unwrap(),
480+
args.pd_ports.unwrap(),
481+
args.has_mec.unwrap(),
482+
);
483+
Config::set(platform);
484+
}
485+
472486
let ec = if let Some(driver) = args.driver {
473487
if let Some(driver) = CrosEc::with(driver) {
474488
driver
@@ -836,11 +850,14 @@ fn hash(data: &[u8]) {
836850
}
837851

838852
fn selftest(ec: &CrosEc) -> Option<()> {
839-
println!(
840-
" SMBIOS Platform: {:?}",
841-
smbios::get_platform().unwrap()
842-
);
843-
println!(" SMBIOS is_framework: {}", smbios::is_framework());
853+
if let Some(platform) = smbios::get_platform() {
854+
println!(" SMBIOS Platform: {:?}", platform);
855+
} else {
856+
println!(" SMBIOS Platform: Unknown");
857+
println!();
858+
println!("Specify custom platform parameters with --pd-ports --pd-addrs --has-mec");
859+
return None;
860+
};
844861

845862
println!(" Dump EC memory region");
846863
if let Some(mem) = ec.dump_mem_region() {

framework_lib/src/commandline/uefi.rs

+65-1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ pub fn parse(args: &[String]) -> Cli {
8686
hash: None,
8787
// This is the only driver that works on UEFI
8888
driver: Some(CrosEcDriverType::Portio),
89+
pd_addrs: None,
90+
pd_ports: None,
91+
has_mec: None,
8992
test: false,
9093
help: false,
9194
allupdate: false,
@@ -169,7 +172,7 @@ pub fn parse(args: &[String]) -> Cli {
169172
Some(Some(percent))
170173
} else {
171174
println!(
172-
"Invalid value for --charge_limit: '{}'. Must be integer < 100.",
175+
"Invalid value for --charge-limit: '{}'. Must be integer < 100.",
173176
args[i + 1]
174177
);
175178
None
@@ -340,11 +343,72 @@ pub fn parse(args: &[String]) -> Cli {
340343
None
341344
};
342345
found_an_option = true;
346+
} else if arg == "--pd-addrs" {
347+
cli.pd_addrs = if args.len() > i + 2 {
348+
let left = args[i + 1].parse::<u16>();
349+
let right = args[i + 2].parse::<u16>();
350+
if left.is_ok() && right.is_ok() {
351+
Some((left.unwrap(), right.unwrap()))
352+
} else {
353+
println!(
354+
"Invalid values for --pd-addrs: '{} {}'. Must be u16 integers.",
355+
args[i + 1],
356+
args[i + 2]
357+
);
358+
None
359+
}
360+
} else {
361+
println!("--pd-addrs requires two arguments, one for each address");
362+
None
363+
};
364+
found_an_option = true;
365+
} else if arg == "--pd-ports" {
366+
cli.pd_ports = if args.len() > i + 2 {
367+
let left = args[i + 1].parse::<u8>();
368+
let right = args[i + 2].parse::<u8>();
369+
if left.is_ok() && right.is_ok() {
370+
Some((left.unwrap(), right.unwrap()))
371+
} else {
372+
println!(
373+
"Invalid values for --pd-ports: '{} {}'. Must be u16 integers.",
374+
args[i + 1],
375+
args[i + 2]
376+
);
377+
None
378+
}
379+
} else {
380+
println!("--pd-ports requires two arguments, one for each port");
381+
None
382+
};
383+
found_an_option = true;
384+
} else if arg == "--has-mec" {
385+
cli.has_mec = if args.len() > i + 1 {
386+
if let Ok(b) = args[i + 1].parse::<bool>() {
387+
Some(b)
388+
} else {
389+
println!(
390+
"Invalid value for --has-mec: '{}'. Must be 'true' or 'false'.",
391+
args[i + 1]
392+
);
393+
None
394+
}
395+
} else {
396+
println!("--has-mec requires extra boolean argument.");
397+
None
398+
};
399+
found_an_option = true;
343400
} else if arg == "--raw-command" {
344401
cli.raw_command = args[1..].to_vec();
345402
}
346403
}
347404

405+
let custom_platform = cli.pd_addrs.is_some() && cli.pd_ports.is_some() && cli.has_mec.is_some();
406+
let no_customization =
407+
cli.pd_addrs.is_none() && cli.pd_ports.is_none() && cli.has_mec.is_none();
408+
if !(custom_platform || no_customization) {
409+
println!("To customize the platform you need to provide all of --pd-addrs, --pd-ports and --has-mec");
410+
}
411+
348412
if args.len() == 1 && cli.paginate {
349413
cli.help = true;
350414
found_an_option = true;

framework_lib/src/smbios.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::prelude::v1::*;
55
#[cfg(not(feature = "uefi"))]
66
use std::io::ErrorKind;
77

8-
use crate::util::Platform;
8+
use crate::util::{Config, Platform};
99
use num_derive::FromPrimitive;
1010
use smbioslib::*;
1111
#[cfg(feature = "uefi")]
@@ -40,6 +40,12 @@ pub enum ConfigDigit0 {
4040

4141
/// Check whether the manufacturer in the SMBIOS says Framework
4242
pub fn is_framework() -> bool {
43+
if matches!(
44+
get_platform(),
45+
Some(Platform::GenericFramework((_, _), (_, _), _))
46+
) {
47+
return true;
48+
}
4349
let smbios = if let Some(smbios) = get_smbios() {
4450
smbios
4551
} else {
@@ -104,6 +110,16 @@ pub fn get_platform() -> Option<Platform> {
104110
return platform;
105111
}
106112

113+
if Config::is_set() {
114+
// Config::get() recursively calls get_platform.
115+
// Except if it's a GenericFramework platform
116+
let config = Config::get();
117+
let platform = &(*config).as_ref().unwrap().platform;
118+
if matches!(platform, Platform::GenericFramework((_, _), (_, _), _)) {
119+
return Some(*platform);
120+
}
121+
}
122+
107123
let smbios = get_smbios();
108124
if smbios.is_none() {
109125
println!("Failed to find SMBIOS");
@@ -123,7 +139,7 @@ pub fn get_platform() -> Option<Platform> {
123139
}
124140
}
125141
if let Some(family) = dmidecode_string_val(&data.family()) {
126-
// Actually "Laptop" and "16in Laptop"
142+
// Actually "Laptop", "13in Laptop", and "16in Laptop"
127143
match family.as_str() {
128144
// TGL Mainboard (I don't this ever appears in family)
129145
"FRANBMCP" => return Some(Platform::IntelGen11),

framework_lib/src/util.rs

+26-7
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ pub enum Platform {
2727
Framework13Amd,
2828
/// Framework 16
2929
Framework16,
30+
/// Generic Framework device
31+
/// pd_addrs, pd_ports, has_mec
32+
GenericFramework((u16, u16), (u8, u8), bool),
3033
}
3134

3235
#[derive(Debug)]
@@ -36,12 +39,27 @@ pub struct Config {
3639
}
3740

3841
impl Config {
39-
fn new() -> Self {
40-
Config {
41-
verbose: false,
42-
platform: Platform::IntelGen11,
42+
pub fn set(platform: Platform) {
43+
#[cfg(feature = "std")]
44+
let mut config = CONFIG.lock().unwrap();
45+
#[cfg(not(feature = "std"))]
46+
let mut config = CONFIG.lock();
47+
48+
if (*config).is_none() {
49+
*config = Some(Config {
50+
verbose: false,
51+
platform,
52+
});
4353
}
4454
}
55+
pub fn is_set() -> bool {
56+
#[cfg(feature = "std")]
57+
let config = CONFIG.lock().unwrap();
58+
#[cfg(not(feature = "std"))]
59+
let config = CONFIG.lock();
60+
61+
(*config).is_some()
62+
}
4563

4664
pub fn get() -> MutexGuard<'static, Option<Self>> {
4765
#[cfg(feature = "std")]
@@ -50,12 +68,13 @@ impl Config {
5068
let mut config = CONFIG.lock();
5169

5270
if (*config).is_none() {
53-
let mut cfg = Config::new();
5471
if let Some(platform) = smbios::get_platform() {
5572
// TODO: Perhaps add Qemu or NonFramework as a platform
56-
cfg.platform = platform;
73+
*config = Some(Config {
74+
verbose: false,
75+
platform,
76+
});
5777
}
58-
*config = Some(cfg);
5978
}
6079

6180
// TODO: See if we can map the Option::unwrap before returning

0 commit comments

Comments
 (0)