Skip to content

Commit 618d95d

Browse files
committed
initial commit
0 parents  commit 618d95d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+3970
-0
lines changed

.github/dependabot.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "cargo"
4+
directory: "/"
5+
schedule:
6+
interval: "monthly"
7+
open-pull-requests-limit: 3
8+
groups:
9+
all-dependencies:
10+
patterns:
11+
- "*"
12+
13+
- package-ecosystem: "github-actions"
14+
directory: "/"
15+
schedule:
16+
interval: "monthly"

.github/workflows/ci.yml

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
name: ci
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
env:
10+
CARGO_TERM_COLOR: always
11+
12+
jobs:
13+
deny:
14+
name: cargo deny
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: checkout code
18+
uses: actions/checkout@v5
19+
20+
- name: cargo deny
21+
uses: EmbarkStudios/cargo-deny-action@v2
22+
23+
fmt:
24+
name: cargo fmt
25+
runs-on: ubuntu-latest
26+
steps:
27+
- name: checkout code
28+
uses: actions/checkout@v5
29+
30+
- name: install rust toolchain
31+
uses: dtolnay/rust-toolchain@master
32+
with:
33+
toolchain: stable
34+
components: rustfmt
35+
36+
- name: cache rust toolchain
37+
uses: Swatinem/rust-cache@v2
38+
39+
- name: cargo fmt
40+
run: cargo fmt --all -- --check
41+
42+
clippy:
43+
name: cargo clippy
44+
runs-on: ubuntu-latest
45+
strategy:
46+
fail-fast: false
47+
matrix:
48+
rust: [stable, beta, nightly, 1.80.0] # stable, beta, nightly, and MSRV
49+
steps:
50+
- name: checkout code
51+
uses: actions/checkout@v5
52+
53+
- name: install rust toolchain
54+
uses: dtolnay/rust-toolchain@master
55+
with:
56+
toolchain: ${{ matrix.rust }}
57+
components: clippy
58+
59+
- name: cache rust toolchain
60+
uses: Swatinem/rust-cache@v2
61+
62+
- name: cargo clippy
63+
run: cargo clippy --bins -- -D warnings
64+
65+
build:
66+
name: cargo build
67+
runs-on: ubuntu-latest
68+
strategy:
69+
fail-fast: false
70+
matrix:
71+
rust: [stable, beta, nightly, 1.80.0] # stable, beta, nightly, and MSRV
72+
steps:
73+
- name: checkout code
74+
uses: actions/checkout@v5
75+
76+
- name: install rust toolchain
77+
uses: dtolnay/rust-toolchain@master
78+
with:
79+
toolchain: ${{ matrix.rust }}
80+
81+
- name: cache rust toolchain
82+
uses: Swatinem/rust-cache@v2
83+
84+
- name: cargo build
85+
run: cargo build
86+
87+
88+
release:
89+
name: cargo build --release
90+
runs-on: ubuntu-latest
91+
strategy:
92+
fail-fast: false
93+
matrix:
94+
rust: [stable, beta, nightly, 1.80.0] # stable, beta, nightly, and MSRV
95+
steps:
96+
- name: checkout code
97+
uses: actions/checkout@v5
98+
99+
- name: install rust toolchain
100+
uses: dtolnay/rust-toolchain@master
101+
with:
102+
toolchain: ${{ matrix.rust }}
103+
104+
- name: cache rust toolchain
105+
uses: Swatinem/rust-cache@v2
106+
107+
- name: cargo build --release
108+
run: cargo build --release

.github/workflows/release.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
release:
13+
name: release
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: checkout code
17+
uses: actions/checkout@v5
18+
19+
- name: install rust toolchain
20+
uses: dtolnay/rust-toolchain@stable
21+
with:
22+
targets: x86_64-unknown-linux-musl
23+
24+
- name: cache rust toolchain
25+
uses: Swatinem/rust-cache@v2
26+
27+
- name: install musl-tools
28+
run: sudo apt-get update && sudo apt-get install -y musl-tools
29+
30+
- name: cargo build
31+
run: cargo build --release --target x86_64-unknown-linux-musl
32+
33+
- name: create release
34+
env:
35+
GH_TOKEN: ${{ github.token }}
36+
run: |
37+
gh release delete --yes ${{ github.ref_name }} || true
38+
gh release create --generate-notes ${{ github.ref_name }} target/x86_64-unknown-linux-musl/release/beacon

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
target/

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "devpath"
3+
version = "0.1.0"
4+
edition = "2021"
5+
description = "UEFI Device Path parsing library"
6+
license = "MIT OR Apache-2.0"
7+
repository = "https://github.com/AMDEPYC/snpcert"
8+
readme = "README.md"
9+
keywords = ["uefi", "device-path", "firmware", "boot", "efi"]
10+
categories = ["embedded", "hardware-support", "parsing"]
11+
rust-version = "1.80"

STYLE.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Code Style Guide
2+
3+
## Module Organization
4+
5+
- **Module names**: Shortened, clear (e.g., `bluetooth_le``btle`, `device_logical_unit``dlu`)
6+
- **Module structure**: One primary struct per sub-type, implementation in same file
7+
- **File naming**: Match shortened module names
8+
9+
## Import Grouping
10+
11+
```rust
12+
// 1. External crates (if any)
13+
use core::net::Ipv4Addr;
14+
15+
// 2. Internal crate imports
16+
use crate::{Error, Head};
17+
use crate::parser::{ByteOrder, Parser};
18+
19+
// 3. Relative imports
20+
use super::ipv4::Protocol;
21+
```
22+
23+
## Field Naming
24+
25+
- **Brief names**: `vendor_id``vid`, `mac_address``mac`, `baud_rate``baud`
26+
- **Documentation**: Add doc comments for any ambiguous shortened names
27+
- **Standard abbreviations**: `nsid`, `lun`, `wwn`, `eui`, `vid`, `pid`, `hba_port`, `pm_port`
28+
29+
## Data Types
30+
31+
### String Handling
32+
- **UTF-8 strings**: Use `&CStr` for null-terminated UTF-8 strings
33+
- **UTF-16 strings**: Use `String` for UTF-16 strings (converted from parser)
34+
- **Raw strings**: Use `&str` for non-null-terminated UTF-8 strings (rare)
35+
36+
### Newtypes
37+
- **Single field structs**: Use newtype pattern
38+
```rust
39+
pub struct Vlan(pub u16);
40+
pub struct Protocol(pub u16);
41+
```
42+
43+
### Enums
44+
- **Small known value sets**: Use proper enums (no repr guarantees)
45+
- **Parser trait**: Implement for validation
46+
```rust
47+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
48+
pub enum Origin {
49+
Manual = 0x00,
50+
StatelessAutoConfiguration = 0x01,
51+
}
52+
```
53+
54+
### Structs
55+
- **Multi-field types**: Regular structs with brief field names
56+
- **Derive**: Always include `Debug, Clone, Copy, PartialEq, Eq, Hash`
57+
58+
## Reserved Fields
59+
60+
- **Storage**: Do NOT store reserved fields in structs
61+
- **Validation**: Parse and validate in `TryFrom` implementation
62+
- **Pattern**: `let _reserved: u32 = node.data.parse(ByteOrder::Little)?;`
63+
64+
## Error Handling
65+
66+
- **Invalid values**: Return `Error::Invalid` for spec violations
67+
- **Validation**: Check reserved field values, invalid NSIDs, etc.
68+
69+
## Documentation
70+
71+
- **Struct docs**: Include UEFI sub-type number and byte length
72+
- **Field docs**: Required for abbreviated field names
73+
- **Example**:
74+
```rust
75+
/// SATA Device Path (SubType 0x12)
76+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
77+
pub struct Sata {
78+
/// HBA port number
79+
pub hba_port: u16,
80+
/// Port multiplier port number
81+
pub pm_port: u16,
82+
pub lun: u16,
83+
}
84+
```
85+
86+
## Implementation Patterns
87+
88+
### Parse Order
89+
- **Last field**: Always use `finish()` method to guarantee end of data
90+
- **Earlier fields**: Use regular `parse()` method
91+
92+
### TryFrom Implementation
93+
```rust
94+
impl<'a> TryFrom<Head<'a>> for TypeName<'a> {
95+
type Error = Error;
96+
97+
fn try_from(mut node: Head<'a>) -> Result<Self, Self::Error> {
98+
// Parse reserved fields (don't store)
99+
let _reserved: u32 = node.data.parse(ByteOrder::Little)?;
100+
101+
// Parse fields (use finish() for last field)
102+
let field1 = node.data.parse(ByteOrder::Little)?;
103+
let utf8_string = node.data.finish(())?; // &CStr for UTF-8
104+
105+
Ok(TypeName { field1, utf8_string })
106+
}
107+
}
108+
```
109+
110+
### Byte Order
111+
- **Multi-byte integers**: Always specify `ByteOrder::Little`
112+
- **Single bytes**: Use `()` argument
113+
- **Arrays**: Use `()` argument
114+
115+
## Constants
116+
117+
- **Protocol numbers**: Define as associated constants
118+
- **Magic values**: Use descriptive constant names
119+
- **Grouping**: Related constants together with docs

deny.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[licenses]
2+
confidence-threshold = 0.8
3+
allow = [
4+
"MIT",
5+
"Apache-2.0",
6+
]
7+
8+
[bans]
9+
multiple-versions = "warn"
10+
11+
[sources]
12+
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
13+
unknown-registry = "deny"
14+
unknown-git = "deny"

src/acpi/adr.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//! ACPI Device Path address (`_ADR`) implementation
2+
//!
3+
//! This module implements the ACPI `_ADR` device path as defined in UEFI 2.11 specification.
4+
//! Used for identifying video output devices using ACPI `_ADR` values.
5+
6+
use crate::parser::{ByteOrder, Parser};
7+
use crate::{Error, Head};
8+
9+
use alloc::vec::Vec;
10+
11+
/// ACPI `_ADR` Device Path (SubType 0x03) - for video output devices
12+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
13+
pub struct Adr {
14+
adrs: Vec<u32>,
15+
}
16+
17+
impl TryFrom<Head<'_>> for Adr {
18+
type Error = Error;
19+
20+
fn try_from(mut node: Head<'_>) -> Result<Self, Self::Error> {
21+
let mut values = Vec::new();
22+
23+
while node.data.len() >= 4 {
24+
let value: u32 = node.data.parse(ByteOrder::Little)?;
25+
values.push(value);
26+
}
27+
28+
if !node.data.is_empty() {
29+
return Err(Error::Invalid);
30+
}
31+
32+
Ok(Self { adrs: values })
33+
}
34+
}

src/acpi/expanded.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//! ACPI Device Path expanded format implementation
2+
//!
3+
//! This module implements the expanded ACPI device path format as defined in UEFI 2.11
4+
//! specification. The expanded format includes additional string-based identifiers.
5+
6+
use crate::parser::{ByteOrder, Format, Parser};
7+
use crate::{Error, Head};
8+
9+
/// Helper struct for ACPI device identifiers
10+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11+
pub struct Id(pub u32, pub String);
12+
13+
/// Expanded ACPI Device Path (SubType 0x02)
14+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15+
pub struct Expanded {
16+
/// Hardware ID - identifies the device's Plug and Play ID
17+
pub hid: Id,
18+
19+
/// Unique ID - distinguishes multiple instances of the same device
20+
pub uid: Id,
21+
22+
/// Compatible ID - identifies devices compatible with this device
23+
pub cid: Id,
24+
}
25+
26+
impl TryFrom<Head<'_>> for Expanded {
27+
type Error = Error;
28+
29+
fn try_from(mut node: Head<'_>) -> Result<Self, Self::Error> {
30+
let hid = node.data.parse(ByteOrder::Little)?;
31+
let uid = node.data.parse(ByteOrder::Little)?;
32+
let cid = node.data.parse(ByteOrder::Little)?;
33+
34+
Ok(Self {
35+
hid: Id(hid, node.data.parse(Format::Utf8(None))?),
36+
uid: Id(uid, node.data.parse(Format::Utf8(None))?),
37+
cid: Id(cid, node.data.finish(Format::Utf8(None))?),
38+
})
39+
}
40+
}

0 commit comments

Comments
 (0)