Skip to content

Commit 8c73cdc

Browse files
martin-hughesIsaacWoods
authored andcommitted
Use correct offset for PCI I/O
1 parent d2681cb commit 8c73cdc

2 files changed

Lines changed: 189 additions & 6 deletions

File tree

src/aml/mod.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,10 +2527,11 @@ where
25272527
}),
25282528
RegionSpace::PciConfig => {
25292529
let address = self.pci_address_for_device(&region.parent_device_path)?;
2530+
let offset = region.base as u16 + offset as u16;
25302531
match length {
2531-
1 => Ok(self.handler.read_pci_u8(address, offset as u16) as u64),
2532-
2 => Ok(self.handler.read_pci_u16(address, offset as u16) as u64),
2533-
4 => Ok(self.handler.read_pci_u32(address, offset as u16) as u64),
2532+
1 => Ok(self.handler.read_pci_u8(address, offset) as u64),
2533+
2 => Ok(self.handler.read_pci_u16(address, offset) as u64),
2534+
4 => Ok(self.handler.read_pci_u32(address, offset) as u64),
25342535
_ => panic!(),
25352536
}
25362537
}
@@ -2593,10 +2594,11 @@ where
25932594
}
25942595
RegionSpace::PciConfig => {
25952596
let address = self.pci_address_for_device(&region.parent_device_path)?;
2597+
let offset = region.base as u16 + offset as u16;
25962598
match length {
2597-
1 => self.handler.write_pci_u8(address, offset as u16, value as u8),
2598-
2 => self.handler.write_pci_u16(address, offset as u16, value as u16),
2599-
4 => self.handler.write_pci_u32(address, offset as u16, value as u32),
2599+
1 => self.handler.write_pci_u8(address, offset, value as u8),
2600+
2 => self.handler.write_pci_u16(address, offset, value as u16),
2601+
4 => self.handler.write_pci_u32(address, offset, value as u32),
26002602
_ => panic!(),
26012603
}
26022604
Ok(())

tests/operation_region.rs

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
use aml_test_tools::handlers::std_test_handler::{Command, construct_std_handler, create_mutex, read_u8, write_pci_u8, write_u8, read_pci_u8};
2+
use pci_types::PciAddress;
3+
4+
mod test_infra;
5+
6+
#[test]
7+
fn test_region_in_top_level() {
8+
const AML: &str = r#"DefinitionBlock("", "DSDT", 1, "RSACPI", "OPREG", 1) {
9+
OperationRegion(MEM, SystemMemory, 0x40000, 0x1000)
10+
Field(MEM, ByteAcc, NoLock, Preserve) {
11+
DATA, 8
12+
}
13+
14+
Method(RDWR, 0, NotSerialized) {
15+
DATA = 0xA5
16+
Return (DATA)
17+
}
18+
19+
Method(MAIN, 0, NotSerialized) {
20+
Local0 = RDWR()
21+
// Remember that returning zero indicates success.
22+
Return (Local0 != 0xA5)
23+
}
24+
}
25+
"#;
26+
27+
const EXPECTED_COMMANDS: &[Command] = &[
28+
create_mutex(),
29+
// DATA = 0xA5
30+
write_u8(0x40000, 0xA5),
31+
read_u8(0x40000, 0xA5),
32+
];
33+
34+
let handler = construct_std_handler(EXPECTED_COMMANDS.to_vec());
35+
test_infra::run_aml_test(AML, handler);
36+
}
37+
38+
#[test]
39+
fn test_region_in_device() {
40+
const AML: &str = r#"DefinitionBlock("", "DSDT", 1, "RSACPI", "OPREG", 1) {
41+
Device(TEST) {
42+
Name (_HID, EisaId ("PNP0C01")) // Arbitrary choice.
43+
44+
OperationRegion(MEM, SystemMemory, 0x40000, 0x1000)
45+
Field(MEM, ByteAcc, NoLock, Preserve) {
46+
DATA, 8
47+
}
48+
49+
Method(RDWR, 0, NotSerialized) {
50+
DATA = 0xA5
51+
Return (DATA)
52+
}
53+
}
54+
55+
Method(MAIN, 0, NotSerialized) {
56+
Local0 = ^TEST.RDWR()
57+
// Remember that returning zero indicates success.
58+
Return (Local0 != 0xA5)
59+
}
60+
}
61+
"#;
62+
63+
const EXPECTED_COMMANDS: &[Command] = &[
64+
create_mutex(),
65+
// DATA = 0xA5
66+
write_u8(0x40000, 0xA5),
67+
read_u8(0x40000, 0xA5),
68+
];
69+
70+
let handler = construct_std_handler(EXPECTED_COMMANDS.to_vec());
71+
test_infra::run_aml_test(AML, handler);
72+
}
73+
74+
#[test]
75+
fn test_region_in_method() {
76+
const AML: &str = r#"DefinitionBlock("", "DSDT", 1, "RSACPI", "OPREG", 1) {
77+
78+
// `iasl` is not a fan of this function - it generates a bunch of warnings, which for testing
79+
// purposes can be ignored.
80+
Method(RDWR, 1, NotSerialized) {
81+
OperationRegion(MEM, SystemMemory, Arg0, 0x1000)
82+
Field(MEM, ByteAcc, NoLock, Preserve) {
83+
DATA, 8
84+
}
85+
86+
DATA = 0xA5
87+
Return (DATA)
88+
}
89+
90+
Method(MAIN, 0, NotSerialized) {
91+
Local0 = RDWR(0x40000)
92+
// Remember that returning zero indicates success.
93+
if (Local0 != 0xA5) {
94+
Return (One)
95+
}
96+
97+
Local0 = RDWR(0x50000)
98+
Return (Local0 != 0xA5)
99+
}
100+
}
101+
"#;
102+
103+
const EXPECTED_COMMANDS: &[Command] = &[
104+
create_mutex(),
105+
// Base set to 0x40000
106+
write_u8(0x40000, 0xA5),
107+
read_u8(0x40000, 0xA5),
108+
// Base set to 0x50000
109+
write_u8(0x50000, 0xA5),
110+
read_u8(0x50000, 0xA5),
111+
];
112+
113+
let handler = construct_std_handler(EXPECTED_COMMANDS.to_vec());
114+
test_infra::run_aml_test(AML, handler);
115+
}
116+
117+
#[test]
118+
#[ignore]
119+
fn test_buffer_field_implicit_conv() {
120+
// This test covers https://github.com/rust-osdev/acpi/issues/273
121+
const AML: &str = r#"DefinitionBlock ("", "SSDT", 2, "AMD", "AmdTable", 0x00000002)
122+
{
123+
Name (ADAT, Buffer (0x0010)
124+
{
125+
/* 0000 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
126+
/* 0008 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
127+
128+
})
129+
OperationRegion (A053, SystemMemory, (DerefOf (ADAT [(0x04)])), 0x1000) // <--- this line failed
130+
Field (A053, ByteAcc, NoLock, Preserve)
131+
{
132+
Offset (0x18),
133+
A, 8
134+
}
135+
}"#;
136+
137+
const EXPECTED_COMMANDS: &[Command] = &[create_mutex()];
138+
139+
let handler = construct_std_handler(EXPECTED_COMMANDS.to_vec());
140+
test_infra::run_aml_test(AML, handler);
141+
}
142+
143+
#[test]
144+
fn test_region_in_pci_device() {
145+
const AML: &str = r#"DefinitionBlock("", "DSDT", 1, "RSACPI", "OPREG", 1) {
146+
Device(TEST) {
147+
Name (_ADR, 0x00020001) // Arbitrary choice.
148+
Name (_BBN, 3)
149+
Name (_SEG, 4)
150+
151+
OperationRegion(MEM, PCI_Config, 0x40, 0x20)
152+
Field(MEM, ByteAcc, NoLock, Preserve) {
153+
Offset (0x10),
154+
DATA, 8
155+
}
156+
157+
Method(RDWR, 0, NotSerialized) {
158+
DATA = 0xA5
159+
Return (DATA)
160+
}
161+
}
162+
163+
Method(MAIN, 0, NotSerialized) {
164+
Local0 = ^TEST.RDWR()
165+
// Remember that returning zero indicates success.
166+
Return (Local0 != 0xA5)
167+
}
168+
}
169+
"#;
170+
171+
let address: PciAddress = PciAddress::new(4, 3, 2, 1);
172+
let expected_commands: &[Command] = &[
173+
create_mutex(),
174+
// DATA = 0xA5
175+
write_pci_u8(address, 0x50, 0xA5),
176+
read_pci_u8(address, 0x50, 0xA5),
177+
];
178+
179+
let handler = construct_std_handler(expected_commands.to_vec());
180+
test_infra::run_aml_test(AML, handler);
181+
}

0 commit comments

Comments
 (0)