Skip to content

Commit f5bd38e

Browse files
committed
Allow customizing platform if not matched
If the platform couldnd't be matched by SMBIOS, now you can select the platform config manually on the commandline. This is not usually needed, just for advanced users. For example: ``` framework_tool --test --driver portio --pd-addrs 8 64 --pd-ports 6 6 --has-mec true framework_tool --test --driver portio --pd-addrs 8 64 --pd-ports 6 7 --has-mec true framework_tool --test --driver portio --pd-addrs 66 64 --pd-ports 1 2 --has-mec false ``` Signed-off-by: Daniel Schaefer <[email protected]>
1 parent b96a342 commit f5bd38e

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)