Skip to content

Commit 2cae019

Browse files
committed
Remove panics in GAS handling code
1 parent d2681cb commit 2cae019

File tree

1 file changed

+43
-28
lines changed

1 file changed

+43
-28
lines changed

src/address.rs

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//! in a wide range of address spaces.
33
44
use crate::{AcpiError, Handler, PhysicalMapping};
5+
use core::ptr;
56
use log::warn;
67

78
/// This is the raw form of a Generic Address Structure, and follows the layout found in the ACPI tables.
@@ -143,7 +144,7 @@ where
143144
}
144145
AddressSpace::SystemIo => Ok(MappedGas { gas, handler: handler.clone(), mapping: None }),
145146
other => {
146-
warn!("Tried to map GAS of unsupported type {:?}", other);
147+
warn!("Mapping a GAS in address space {:?} is not supported!", other);
147148
Err(AcpiError::LibUnimplemented)
148149
}
149150
}
@@ -158,25 +159,24 @@ where
158159
match self.gas.address_space {
159160
AddressSpace::SystemMemory => {
160161
let mapping = self.mapping.as_ref().unwrap();
161-
let value = match access_size_bits {
162-
8 => unsafe { core::ptr::read_volatile(mapping.virtual_start.as_ptr() as *const u8) as u64 },
163-
16 => unsafe { core::ptr::read_volatile(mapping.virtual_start.as_ptr() as *const u16) as u64 },
164-
32 => unsafe { core::ptr::read_volatile(mapping.virtual_start.as_ptr() as *const u32) as u64 },
165-
64 => unsafe { core::ptr::read_volatile(mapping.virtual_start.as_ptr() as *const u64) },
166-
_ => panic!(),
167-
};
168-
Ok(value)
162+
match access_size_bits {
163+
8 => Ok(unsafe { ptr::read_volatile(mapping.virtual_start.as_ptr() as *const u8) as u64 }),
164+
16 => Ok(unsafe { ptr::read_volatile(mapping.virtual_start.as_ptr() as *const u16) as u64 }),
165+
32 => Ok(unsafe { ptr::read_volatile(mapping.virtual_start.as_ptr() as *const u32) as u64 }),
166+
64 => Ok(unsafe { ptr::read_volatile(mapping.virtual_start.as_ptr() as *const u64) }),
167+
_ => Err(AcpiError::InvalidGenericAddress),
168+
}
169169
}
170-
AddressSpace::SystemIo => {
171-
let value = match access_size_bits {
172-
8 => self.handler.read_io_u8(self.gas.address as u16) as u64,
173-
16 => self.handler.read_io_u16(self.gas.address as u16) as u64,
174-
32 => self.handler.read_io_u32(self.gas.address as u16) as u64,
175-
_ => panic!(),
176-
};
177-
Ok(value)
170+
AddressSpace::SystemIo => match access_size_bits {
171+
8 => Ok(self.handler.read_io_u8(self.gas.address as u16) as u64),
172+
16 => Ok(self.handler.read_io_u16(self.gas.address as u16) as u64),
173+
32 => Ok(self.handler.read_io_u32(self.gas.address as u16) as u64),
174+
_ => Err(AcpiError::InvalidGenericAddress),
175+
},
176+
_ => {
177+
warn!("Read from GAS with address space {:?} is not supported. Ignored.", self.gas.address_space);
178+
Err(AcpiError::LibUnimplemented)
178179
}
179-
_ => unimplemented!(),
180180
}
181181
}
182182

@@ -188,16 +188,16 @@ where
188188
let mapping = self.mapping.as_ref().unwrap();
189189
match access_size_bits {
190190
8 => unsafe {
191-
core::ptr::write_volatile(mapping.virtual_start.as_ptr(), value as u8);
191+
ptr::write_volatile(mapping.virtual_start.as_ptr(), value as u8);
192192
},
193193
16 => unsafe {
194-
core::ptr::write_volatile(mapping.virtual_start.as_ptr() as *mut u16, value as u16);
194+
ptr::write_volatile(mapping.virtual_start.as_ptr() as *mut u16, value as u16);
195195
},
196196
32 => unsafe {
197-
core::ptr::write_volatile(mapping.virtual_start.as_ptr() as *mut u32, value as u32);
197+
ptr::write_volatile(mapping.virtual_start.as_ptr() as *mut u32, value as u32);
198198
},
199-
64 => unsafe { core::ptr::write_volatile(mapping.virtual_start.as_ptr() as *mut u64, value) },
200-
_ => panic!(),
199+
64 => unsafe { ptr::write_volatile(mapping.virtual_start.as_ptr() as *mut u64, value) },
200+
_ => return Err(AcpiError::InvalidGenericAddress),
201201
}
202202
Ok(())
203203
}
@@ -206,11 +206,14 @@ where
206206
8 => self.handler.write_io_u8(self.gas.address as u16, value as u8),
207207
16 => self.handler.write_io_u16(self.gas.address as u16, value as u16),
208208
32 => self.handler.write_io_u32(self.gas.address as u16, value as u32),
209-
_ => panic!(),
209+
_ => return Err(AcpiError::InvalidGenericAddress),
210210
}
211211
Ok(())
212212
}
213-
_ => unimplemented!(),
213+
_ => {
214+
warn!("Write to GAS with address space {:?} is not supported. Ignored.", self.gas.address_space);
215+
Err(AcpiError::LibUnimplemented)
216+
}
214217
}
215218
}
216219
}
@@ -228,7 +231,7 @@ fn gas_decode_access_bit_width(gas: GenericAddress) -> Result<u8, AcpiError> {
228231
*
229232
* We use a third method, based on the alignment of the address, for registers that have
230233
* non-zero bit offsets. These are not typically encountered in normal registers - they very
231-
* often mean the GAS has come from APEI (ACPI Platform Error Interface), and so needs speical
234+
* often mean the GAS has come from APEI (ACPI Platform Error Interface), and so needs special
232235
* handling.
233236
*/
234237
if gas.bit_offset == 0 && [8, 16, 32, 64].contains(&gas.bit_width) {
@@ -242,7 +245,19 @@ fn gas_decode_access_bit_width(gas: GenericAddress) -> Result<u8, AcpiError> {
242245
_ => Err(AcpiError::InvalidGenericAddress),
243246
}
244247
} else {
245-
// TODO: work out access size based on alignment of the address
246-
todo!()
248+
/*
249+
* Work out the access size based on the alignment of the address. We round up the total
250+
* width (`bit_offset + bit_width`) to the next power-of-two, up to 64.
251+
*/
252+
let total_width = gas.bit_offset + gas.bit_width;
253+
Ok(if total_width <= 8 {
254+
8
255+
} else if total_width <= 16 {
256+
16
257+
} else if total_width <= 32 {
258+
32
259+
} else {
260+
64
261+
})
247262
}
248263
}

0 commit comments

Comments
 (0)