Skip to content

Commit f87d5d5

Browse files
committed
Decode additional Frameowork16 and AMD related memmap items
TODO: - [ ] Handle it better than just increasing EC_MEMMAP_SIZE*2 - [ ] Figure out all items and whether they apply to Lotus and also Azalea - [ ] Figure out Lotus and Azalea fan names Example: ``` cargo build && sudo ./target/debug/framework_tool --driver portio --expansion-bay AMD Power Slider: DC, Battery Saver (0b0001000) STT Table: 7 CBP: true ([0, 0]) DTT Temp: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] Expansion Bay Serial Struct: [0, 0, 0, 0] PD Version: [0, 0, 0, 0] GPU CTRL: 0x8 MUX Status: GPU Board Status: Present PCIe Config: 8x1 Display On: false GPU Type: AMD R23M (2) ``` Reference data: ``` Fan Module Serial Struct: [0, 0, 0, 0] Batt Manuf 2023-22-7 PD Version: [0, 0, 0, 0] GPU CTRL: 0x0 Power Slider: AC, Best Power Efficiency (0b1000000) Display On: false STT Table: 13 CBP: true ([0, 0]) GPU Type: Initializing (0) DTT Temp: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] dGPU Module Serial Struct: [0, 0, 0, 0] Batt Manuf 2023-7-22 PD Version: [0, 0, 0, 0] GPU CTRL: 0x8 Power Slider: DC, Battery Saver (0b0001000) Display On: false STT Table: 7 CBP: true ([0, 0]) GPU Type: AMD R23M (2) DTT Temp: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ``` Signed-off-by: Daniel Schaefer <[email protected]>
1 parent fb8f885 commit f87d5d5

File tree

6 files changed

+133
-3
lines changed

6 files changed

+133
-3
lines changed

framework_lib/src/chromium_ec/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -911,7 +911,7 @@ impl CrosEcDriver for CrosEc {
911911
}
912912

913913
debug!("read_memory(offset={:#X}, size={:#X})", offset, length);
914-
if offset + length > EC_MEMMAP_SIZE {
914+
if offset + length > (EC_MEMMAP_SIZE * 2) {
915915
return None;
916916
}
917917

framework_lib/src/chromium_ec/portio.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,11 @@ fn init() -> bool {
227227
let res = ioperm(EC_LPC_ADDR_HOST_DATA as u64, 1, 1);
228228
assert_eq!(res, 0);
229229

230-
let res = ioperm(NPC_MEMMAP_OFFSET as u64, super::EC_MEMMAP_SIZE as u64, 1);
230+
let res = ioperm(
231+
NPC_MEMMAP_OFFSET as u64,
232+
(super::EC_MEMMAP_SIZE * 2) as u64,
233+
1,
234+
);
231235
assert_eq!(res, 0);
232236
}
233237
}

framework_lib/src/commandline/clap_std.rs

+5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ struct ClapCli {
5252
#[arg(long)]
5353
sensors: bool,
5454

55+
/// Print expansion bay information
56+
#[arg(long)]
57+
expansion_bay: bool,
58+
5559
/// Show information about USB-C PD ports
5660
#[arg(long)]
5761
pdports: bool,
@@ -223,6 +227,7 @@ pub fn parse(args: &[String]) -> Cli {
223227
power: args.power,
224228
thermal: args.thermal,
225229
sensors: args.sensors,
230+
expansion_bay: args.expansion_bay,
226231
pdports: args.pdports,
227232
pd_info: args.pd_info,
228233
dp_hdmi_info: args.dp_hdmi_info,

framework_lib/src/commandline/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ pub struct Cli {
128128
pub power: bool,
129129
pub thermal: bool,
130130
pub sensors: bool,
131+
pub expansion_bay: bool,
131132
pub pdports: bool,
132133
pub privacy: bool,
133134
pub pd_info: bool,
@@ -790,6 +791,8 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
790791
power::print_thermal(&ec);
791792
} else if args.sensors {
792793
power::print_sensors(&ec);
794+
} else if args.expansion_bay {
795+
power::print_expansion_bay_info(&ec);
793796
} else if args.pdports {
794797
power::get_and_print_pd_info(&ec);
795798
} else if args.info {
@@ -973,6 +976,7 @@ Options:
973976
--power Show current power status (battery and AC)
974977
--thermal Print thermal information (Temperatures and Fan speed)
975978
--sensors Print sensor information (ALS, G-Sensor)
979+
--expansion-bay Print expansion bay information
976980
--pdports Show information about USB-C PD ports
977981
--info Show info from SMBIOS (Only on UEFI)
978982
--pd-info Show details about the PD controllers

framework_lib/src/commandline/uefi.rs

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ pub fn parse(args: &[String]) -> Cli {
6464
power: false,
6565
thermal: false,
6666
sensors: false,
67+
expansion_bay: false,
6768
pdports: false,
6869
pd_info: false,
6970
dp_hdmi_info: false,
@@ -141,6 +142,8 @@ pub fn parse(args: &[String]) -> Cli {
141142
found_an_option = true;
142143
} else if arg == "--sensors" {
143144
cli.sensors = true;
145+
} else if arg == "--expansion-bay" {
146+
cli.expansion_bay = true;
144147
found_an_option = true;
145148
} else if arg == "--pdports" {
146149
cli.pdports = true;

framework_lib/src/power.rs

+115-1
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,114 @@ pub fn print_sensors(ec: &CrosEc) {
202202
println!("ALS: {:>4} Lux", als_int);
203203
}
204204

205+
pub fn print_expansion_bay_info(ec: &CrosEc) {
206+
let platform = smbios::get_platform();
207+
if !matches!(
208+
platform,
209+
Some(Platform::Framework13Amd) | Some(Platform::Framework16)
210+
) {
211+
println!("Only applicable to Framework 16 and Framework AMD systems");
212+
return;
213+
}
214+
215+
println!("AMD");
216+
// TODO: This is also on Azalea?
217+
let power_slider = ec.read_memory(0x151, 0x02).unwrap()[0];
218+
let dc_ac = if power_slider <= 0b1000 { "DC" } else { "AC" };
219+
let mode = match power_slider {
220+
0b0000_0001 | 0b0001_0000 => "Best Performance",
221+
0b0000_0010 | 0b0010_0000 => "Balanced",
222+
0b0000_0100 | 0b0100_0000 => "Best Power Efficiency",
223+
0b0000_1000 => "Battery Saver",
224+
_ => "Unknown Mode",
225+
};
226+
println!(
227+
" Power Slider: {}, {} ({:#09b})",
228+
dc_ac, mode, power_slider
229+
);
230+
231+
// TODO: This is also on Azalea?
232+
let stt_table = ec.read_memory(0x154, 0x01).unwrap()[0];
233+
println!(" STT Table: {:?}", stt_table);
234+
235+
// TODO: What's this? Always [0x00, 0x00] so far
236+
// TODO: This is also on Azalea?
237+
// Core Performance Boost
238+
let cbp = ec.read_memory(0x155, 0x02).unwrap();
239+
println!(" CBP: {} ({:?})", cbp == [0x00, 0x00], cbp);
240+
241+
// TODO: When is this changed?
242+
// TODO: This is also on Azalea?
243+
let dtt_temp = ec.read_memory(0x160, 0x0F).unwrap();
244+
println!(" DTT Temp: {:?}", dtt_temp);
245+
246+
if !matches!(platform, Some(Platform::Framework16)) {
247+
return;
248+
}
249+
250+
println!("Expansion Bay");
251+
252+
// TODO: This is the serial struct in the Expansion Bay?
253+
let serial_struct = ec.read_memory(0x140, 0x04).unwrap();
254+
println!(" Serial Struct: {:?}", serial_struct);
255+
256+
// TODO: Why is this in the same namespace?
257+
// let batt_manuf_day = ec.read_memory(0x144, 0x01).unwrap()[0];
258+
// let batt_manuf_month = ec.read_memory(0x145, 0x01).unwrap()[0];
259+
// let batt_manuf_year = ec.read_memory(0x146, 0x02).unwrap();
260+
// let batt_manuf_year = u16::from_le_bytes([batt_manuf_year[0], batt_manuf_year[1]]);
261+
// println!(" Batt Manuf {:?}-{:?}-{:?}", batt_manuf_year, batt_manuf_month, batt_manuf_day);
262+
263+
// TODO: This is the PD in the dGPU module?
264+
let pd_ver = ec.read_memory(0x14C, 0x04).unwrap();
265+
println!(" PD Version: {:?}", pd_ver);
266+
267+
let gpu_ctrl = ec.read_memory(0x150, 0x01).unwrap()[0];
268+
// Unused, this is for the BIOS to set
269+
let _set_mux_status = match gpu_ctrl & 0b11 {
270+
0b00 => "EC Received and Clear",
271+
0b01 => "BIOS Set APU",
272+
0b10 => "BIOS Set GPU",
273+
_ => "Unknown",
274+
};
275+
let mux_status = if (gpu_ctrl & 0b100) > 0 { "APU" } else { "GPU" };
276+
let board_status = if (gpu_ctrl & 0b1000) > 0 {
277+
"Present"
278+
} else {
279+
"Absent"
280+
};
281+
// Unused, set by BIOS: (gpu_ctrl & 0b10000)
282+
let pcie_config = match gpu_ctrl & 0b01100000 {
283+
0b00 => "8x1",
284+
0b01 => "4x1",
285+
0b10 => "4x2",
286+
0b11 => "Disabled",
287+
_ => "Unknown",
288+
};
289+
println!(" GPU CTRL: {:#x}", gpu_ctrl);
290+
println!(" MUX Status: {}", mux_status);
291+
println!(" Board Status: {}", board_status);
292+
println!(" PCIe Config: {}", pcie_config);
293+
294+
// TODO: This seems like it's not correctly working? It's always false
295+
let display_on = ec.read_memory(0x153, 0x01).unwrap()[0];
296+
println!(" Display On: {:?}", display_on == 0x01);
297+
298+
let gpu_type = ec.read_memory(0x157, 0x01).unwrap()[0];
299+
let gpu_name = match gpu_type {
300+
0x00 => "Initializing",
301+
0x01 => "Fan Only",
302+
0x02 => "AMD R23M",
303+
0x03 => "SSD",
304+
0x04 => "PCIe Accessory",
305+
_ => "Unknown",
306+
};
307+
println!(" GPU Type: {} ({:?})", gpu_name, gpu_type);
308+
}
309+
205310
pub fn print_thermal(ec: &CrosEc) {
206311
let temps = ec.read_memory(EC_MEMMAP_TEMP_SENSOR, 0x0F).unwrap();
312+
println!("Temps: {:?}", temps);
207313
let fans = ec.read_memory(EC_MEMMAP_FAN, 0x08).unwrap();
208314

209315
let platform = smbios::get_platform();
@@ -221,6 +327,8 @@ pub fn print_thermal(ec: &CrosEc) {
221327
println!(" F75303_CPU: {:>4}", TempSensor::from(temps[1]));
222328
println!(" F75303_DDR: {:>4}", TempSensor::from(temps[2]));
223329
println!(" APU: {:>4}", TempSensor::from(temps[3]));
330+
// TODO: Only display if dGPU is present
331+
// TODO: Sometimes these show 0 even if the GPU is present. Why?
224332
if matches!(platform, Some(Platform::Framework16)) {
225333
println!(" dGPU VR: {:>4}", TempSensor::from(temps[4]));
226334
println!(" dGPU VRAM: {:>4}", TempSensor::from(temps[5]));
@@ -241,7 +349,13 @@ pub fn print_thermal(ec: &CrosEc) {
241349
}
242350

243351
let fan0 = u16::from_le_bytes([fans[0], fans[1]]);
244-
println!(" Fan Speed: {:>4} RPM", fan0);
352+
let fan1 = u16::from_le_bytes([fans[2], fans[3]]);
353+
if matches!(platform, Some(Platform::Framework16)) {
354+
println!(" Fan L Speed: {:>4} RPM", fan0);
355+
println!(" Fan R Speed: {:>4} RPM", fan1);
356+
} else {
357+
println!(" Fan Speed: {:>4} RPM", fan0);
358+
}
245359
}
246360

247361
// TODO: Use Result

0 commit comments

Comments
 (0)