8000 Merge #39 · rust-osdev/acpi@ef13e64 · GitHub
[go: up one dir, main page]

Skip to content

Commit ef13e64

Browse files
bors[bot]IsaacWoods
andcommitted
Merge #39
39: Get a release out r=IsaacWoods a=IsaacWoods This crate's been a little neglected, so this is an attempt to sanitise some stuff and get a MVP release out so the crate is actually of use One of the major changes I hope to make here is to split the static table discovery and AML parsing: the latter step is much less complete and you may not even want to do them at the same time (e.g. in Pebble, I want to find all the tables in the bootloader, and then parse AML in a safer environment in a userspace process). This enables that, without much trouble for people who want to parse it all at once. Co-authored-by: Isaac Woods <isaacwoods.home@gmail.com>
2 parents a955ebd + 41adc7b commit ef13e64

21 files changed

+239
-930
lines changed

Cargo.toml

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,2 @@
1-
[package]
2-
name = "acpi"
3-
version = "0.1.0"
4-
authors = ["Isaac Woods <isaacwoods.home@gmail.com>"]
5-
repository = "https://github.com/rust-osdev/acpi"
6-
description = "Library for parsing ACPI tables and AML"
7-
readme = "README.md"
8-
license = "MIT/Apache-2.0"
9-
edition = "2018"
10-
11-
[dependencies]
12-
log = "0.*"
13-
bit_field = "0.9.0"
1+
[workspace]
2+
members = ["acpi", "aml_parser"]

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22
[![Build Status](https://travis-ci.org/rust-osdev/acpi.svg?branch=master)](https://travis-ci.org/rust-osdev/acpi)
33
[![Version](https://img.shields.io/crates/v/acpi.svg?style=rounded-square)](https://crates.io/crates/acpi/)
44

5-
A library to parse ACPI tables and AML, written in Rust. Designed to be easy to use from inside a
6-
kernel written in Rust, and fully tested.
7-
**Acpi is currently very early in development, will be highly unstable and is next to useless for
8-
actually parsing ACPI or AML.**
5+
### [Documentation (`acpi`)](https://docs.rs/acpi)
6+
### [Documentation (`aml_parser`)](https://docs.rs/aml_parser)
97

10-
## Using
11-
`acpi` uses the nightly channel, and currently builds on `rustc 1.27.0-nightly (7925ff4e 2018-04-19)`.
12-
If `acpi` fails to build on a later nightly, please file an issue!
8+
A library to parse ACPI tables and AML, written in pure Rust. Designed to be easy to use from Rust bootloaders and kernels. The library is split into two crates:
9+
- `acpi` parses the static tables (useful but not feature-complete)
10+
- `aml_parser` parses the AML tables (still a work-in-progress, not that useful yet)
1311

1412
## Contributing
1513
Contributions are more than welcome! You can:
1614
- Write code - the ACPI spec is huge and there are bound to be things we don't support yet!
15+
- Documentation
16+
- Using the crates within your kernel and file bug reports and feature requests!
1717

18-
## Resources
18+
Useful resources for contributing are:
1919
- [The ACPI specification](http://www.uefi.org/sites/default/files/resources/ACPI%206_2_A_Sept29.pdf)
2020
- [OSDev Wiki](https://wiki.osdev.org/ACPI)
2121

acpi/Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "acpi"
3+
version = "0.2.1"
4+
authors = ["Isaac Woods"]
5+
repository = "https://github.com/rust-osdev/acpi"
6+
description = "Library for parsing ACPI tables"
7+
categories = ["hardware-support", "no-std"]
8+
readme = "../README.md"
9+
license = "MIT/Apache-2.0"
< A3D4 /code>
10+
edition = "2018"
11+
12+
[dependencies]
13+
log = "0.4"
14+
bit_field = "0.9"

src/fadt.rs renamed to acpi/src/fadt.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
use crate::aml::{parse_aml_table, AmlTable};
2-
use crate::sdt;
3-
use crate::sdt::SdtHeader;
4-
use crate::{Acpi, AcpiError, AcpiHandler, GenericAddress, PhysicalMapping};
1+
use crate::{sdt::SdtHeader, Acpi, AcpiError, AcpiHandler, GenericAddress, PhysicalMapping};
52

63
/// Represents the Fixed ACPI Description Table (FADT). This table contains various fixed hardware
74
/// details, such as the addresses of the hardware register blocks. It also contains a pointer to
@@ -86,20 +83,11 @@ where
8683
fadt.header.validate(b"FACP")?;
8784

8885
// TODO more generic typesafe way of accessing the x_ fields
89-
let dsdt_physical_address: usize = if fadt.header.revision() > 1 && fadt.x_dsdt_address != 0 {
86+
acpi.dsdt_address = Some(if fadt.header.revision() > 1 && fadt.x_dsdt_address != 0 {
9087
fadt.x_dsdt_address as usize
9188
} else {
9289
fadt.dsdt_address as usize
93-
};
94-
95-
// Parse the DSDT
96-
let dsdt_header = sdt::peek_at_sdt_header(handler, dsdt_physical_address);
97-
let dsdt_mapping = handler
98-
.map_physical_region::<AmlTable>(dsdt_physical_address, dsdt_header.length() as usize);
99-
if let Err(error) = parse_aml_table(acpi, handler, &dsdt_mapping, b"DSDT") {
100-
error!("Failed to parse DSDT: {:?}. At this stage, this is expected, but should be fatal in the future", error);
101-
}
102-
handler.unmap_physical_region(dsdt_mapping);
90+
});
10391

10492
Ok(())
10593
}

acpi/src/handler.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use core::{ops::Deref, ptr::NonNull};
2+
3+
/// Describes a physical mapping created by `AcpiHandler::map_physical_region` and unmapped by
4+
/// `AcpiHandler::unmap_physical_region`. The region mapped must be at least `size_of::<T>()`
5+
/// bytes, but may be bigger.
6+
pub struct PhysicalMapping<T> {
7+
pub physical_start: usize,
8+
pub virtual_start: NonNull<T>,
9+
pub region_length: usize, // Can be equal or larger than size_of::<T>()
10+
pub mapped_length: usize, // Differs from `region_length` if padding is added for alignment
11+
}
12+
13+
impl<T> Deref for PhysicalMapping<T> {
14+
type Target = T;
15+
16+
fn deref(&self) -> &T {
17+
unsafe { self.virtual_start.as_ref() }
18+
}
19+
}
20+
21+
/// An implementation of this trait must be provided to allow `acpi` to access platform-specific
22+
/// functionality, such as mapping regions of physical memory. You are free to implement these
23+
/// however you please, as long as they conform to the documentation of each function.
24+
pub trait AcpiHandler {
25+
/// Given a starting physical address and a size, map a region of physical memory that contains
26+
/// a `T` (but may be bigger than `size_of::<T>()`). The address doesn't have to be
27+
/// page-aligned, so the implementation may have to add padding to either end. The given
28+
/// size must be greater or equal to the size of a `T`. The virtual address the memory is
29+
/// mapped to does not matter, as long as it is accessible from `acpi`.
30+
fn map_physical_region<T>(
31+
&mut self,
32+
physical_address: usize,
33+
size: usize,
34+
) -> PhysicalMapping<T>;
35+
36+
/// Unmap the given physical mapping. Safe because we consume the mapping, and so it can't be
37+
/// used after being passed to this function.
38+
fn unmap_physical_region<T>(&mut self, region: PhysicalMapping<T>);
39+
}

acpi/src/hpet.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use crate::{sdt::SdtHeader, Acpi, AcpiError, GenericAddress, PhysicalMapping};
2+
use bit_field::BitField;
3+
4+
#[derive(Debug)]
5+
pub enum PageProtection {
6+
None,
7+
/// Access to the adjacent 3KB to the base address will not generate a fault.
8+
Protected4K,
9+
/// Access to the adjacent 64KB to the base address will not generate a fault.
10+
Protected64K,
11+
Other,
12+
}
13+
14+
/// Information about the High Precision Event Timer
15+
#[derive(Debug)]
16+
pub struct HpetInfo {
17+
event_timer_block_id: u32,
18+
base_address: usize,
19+
hpet_number: u8,
20+
/// The minimum number of clock ticks that can be set without losing interrupts (for timers in
21+
/// Periodic Mode)
22+
clock_tick_unit: u16,
23+
page_protection: PageProtection,
24+
}
25+
26+
#[repr(C, packed)]
27+
pub(crate) struct HpetTable {
28+
header: SdtHeader,
29+
event_timer_block_id: u32,
30+
base_address: GenericAddress,
31+
hpet_number: u8,
32+
clock_tick_unit: u16,
33+
page_protection_oem: u8,
34+
}
35+
36+
pub(crate) fn parse_hpet(
37+
acpi: &mut Acpi,
38+
mapping: &PhysicalMapping<HpetTable>,
39+
) -> Result<(), AcpiError> {
40+
(*mapping).header.validate(b"HPET")?;
41+
let hpet = &*mapping;
42+
43+
// Make sure the HPET's in system memory
44+
assert_eq!(hpet.base_address.address_space, 0);
45+
46+
info!("HPET address: {:#?}", hpet.base_address);
47+
acpi.hpet = Some(HpetInfo {
48+
event_timer_block_id: hpet.event_timer_block_id,
49+
base_address: hpet.base_address.address as usize,
50+
hpet_number: hpet.hpet_number,
51+
clock_tick_unit: hpet.clock_tick_unit,
52+
page_protection: match hpet.page_protection_oem.get_bits(0..5) {
53+
0 => PageProtection::None,
54+
1 => PageProtection::Protected4K,
55+
2 => PageProtection::Protected64K,
56+
3..=15 => PageProtection::Other,
57+
_ => unreachable!(),
58+
},
59+
});
60+
61+
Ok(())
62+
}
File renamed without changes.

0 commit comments

Comments
 (0)
0