2018-06-04 09:04:59 +03:00
|
|
|
# How to contribute to uefi-rs
|
|
|
|
|
|
|
|
|
|
Pull requests, issues and suggestions are welcome!
|
|
|
|
|
|
2018-06-05 08:43:08 +03:00
|
|
|
The UEFI spec is huge, so there might be some omissions or some missing features.
|
|
|
|
|
You should follow the existing project structure when adding new items.
|
|
|
|
|
|
2026-08-16 12:12:59 +02:00
|
|
|
See the top-level [README](README.md) for details about the repository and
|
|
|
|
|
`cargo xtask` commands.
|
2018-10-14 10:02:00 +02:00
|
|
|
|
2026-08-16 12:12:59 +02:00
|
|
|
## Development workflow
|
2018-06-04 09:04:59 +03:00
|
|
|
|
2026-08-16 12:12:59 +02:00
|
|
|
Run the relevant checks locally before opening a pull request:
|
2018-06-04 09:04:59 +03:00
|
|
|
|
|
|
|
|
```shell
|
2026-08-16 12:12:59 +02:00
|
|
|
cargo xtask build
|
|
|
|
|
cargo xtask test # unit tests
|
|
|
|
|
cargo xtask run # integration test using QEMU
|
2018-06-04 09:04:59 +03:00
|
|
|
```
|
|
|
|
|
|
2026-08-16 12:12:59 +02:00
|
|
|
Upstream CI is the final validation.
|
2018-06-05 08:43:08 +03:00
|
|
|
|
2026-08-16 12:12:59 +02:00
|
|
|
## Code and documentation style
|
|
|
|
|
|
|
|
|
|
Write clean, maintainable code and follow the Rust style enforced by `rustfmt`
|
|
|
|
|
and Clippy. Check style with:
|
2018-10-14 10:02:00 +02:00
|
|
|
|
|
|
|
|
```shell
|
2026-08-16 12:12:59 +02:00
|
|
|
cargo xtask fmt
|
2021-12-21 15:34:13 -05:00
|
|
|
cargo xtask clippy
|
2026-08-16 12:12:59 +02:00
|
|
|
cargo xtask doc
|
2018-10-14 10:02:00 +02:00
|
|
|
```
|
|
|
|
|
|
2026-08-16 12:12:59 +02:00
|
|
|
For all new and changed code, add documentation and comments where they
|
|
|
|
|
**provide additional value**:
|
|
|
|
|
|
|
|
|
|
* **Rustdoc** explains the API to its users.
|
|
|
|
|
* **Inline comments** explain the code to the reader, especially *why* it is
|
|
|
|
|
written that way.
|
|
|
|
|
* **Commit messages** explain the broader context of a change (for more
|
|
|
|
|
information on commit messages, see below).
|
|
|
|
|
|
|
|
|
|
Before adding a helper or an external dependency, first look for an appropriate
|
|
|
|
|
solution in `core`. Avoid new external dependencies when a standard library
|
|
|
|
|
solution is suitable.
|
|
|
|
|
|
|
|
|
|
### Rustdoc
|
|
|
|
|
|
|
|
|
|
Start each rustdoc comment with a short, complete summary sentence. The summary
|
|
|
|
|
should normally fit on one line and must not exceed two lines at 80 columns.
|
|
|
|
|
Put additional explanation in a separate paragraph, if necessary.
|
|
|
|
|
|
|
|
|
|
Use standard sections for API contracts:
|
|
|
|
|
|
|
|
|
|
- Use `# Arguments` when parameters need explanation beyond their names and
|
|
|
|
|
types. Describe parameters as ``- `name`: description.``
|
|
|
|
|
- Use `# Returns` when the return value is not clear from the summary and type.
|
|
|
|
|
- Use `# Errors` for meaningful failure conditions of fallible APIs. Link to
|
|
|
|
|
specific UEFI status values where applicable.
|
|
|
|
|
- Use `# Panics` and `# Safety` for their respective contracts.
|
|
|
|
|
- Use `# Example` for one example and `# Examples` for multiple examples.
|
2018-06-04 09:04:59 +03:00
|
|
|
|
2026-08-16 12:12:59 +02:00
|
|
|
## AI-assisted contributions
|
2018-06-04 09:04:59 +03:00
|
|
|
|
2026-08-16 12:12:59 +02:00
|
|
|
If an LLM or other AI meaningfully assisted a contribution, disclose that in the
|
|
|
|
|
commit message and/or pull request description. A human contributor must review
|
|
|
|
|
and understand the submitted code and remains responsible for it. Submitting a
|
|
|
|
|
large AI-generated change without that understanding is not acceptable.
|
|
|
|
|
|
|
|
|
|
## Commits and pull requests
|
|
|
|
|
|
|
|
|
|
Write commits that form a logical, **reviewable** path from the initial state to
|
|
|
|
|
the final state. Keep the final history compact and concise: squash incidental
|
|
|
|
|
fixups and other intermediate states before opening a pull request.
|
|
|
|
|
|
|
|
|
|
Use this subject format for commits:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
component: single line description
|
|
|
|
|
|
|
|
|
|
<optional body explaining _why_ the change is needed>
|
|
|
|
|
```
|
2018-06-04 09:04:59 +03:00
|
|
|
|
2026-08-16 12:12:59 +02:00
|
|
|
Add a commit-message body that explains the important motivation when it is not
|
|
|
|
|
trivial or **why** a change is needed. In the pull request, briefly repeat your
|
|
|
|
|
motivation. It is okay to forward the reviewer to the commit messages, which
|
|
|
|
|
are the source of truth.
|
2018-10-14 10:02:00 +02:00
|
|
|
|
2026-08-16 12:12:59 +02:00
|
|
|
We highly encourage a line width limit of 72 characters for commit message, but
|
|
|
|
|
we do not enforce it.
|
2018-10-14 10:02:00 +02:00
|
|
|
|
|
|
|
|
## UEFI pitfalls
|
|
|
|
|
|
|
|
|
|
Interfacing with a foreign and unsafe API is a difficult exercise in general, and
|
|
|
|
|
UEFI is certainly no exception. This section lists some common pain points that
|
|
|
|
|
you should keep in mind while working on UEFI interfaces.
|
|
|
|
|
|
|
|
|
|
### Enums
|
|
|
|
|
|
|
|
|
|
Rust and C enums differ in many way. One safety-critical difference is that the
|
|
|
|
|
Rust compiler assumes that all variants of Rust enums are known at compile-time.
|
|
|
|
|
UEFI, on the other hand, features many C enums which can be freely extended by
|
|
|
|
|
implementations or future versions of the spec.
|
|
|
|
|
|
|
|
|
|
These enums must not be interfaced as Rust enums, as that could lead to undefined
|
|
|
|
|
behavior. Instead, integer newtypes with associated constants should be used. The
|
|
|
|
|
`newtype_enum` macro is provided by this crate to ease this exercise.
|
|
|
|
|
|
|
|
|
|
### Pointers
|
|
|
|
|
|
|
|
|
|
Pointer parameters in UEFI APIs come with many safety conditions. Some of these
|
|
|
|
|
are usually expected by unsafe Rust code, while others are more specific to the
|
|
|
|
|
low-level environment that UEFI operates in:
|
|
|
|
|
|
|
|
|
|
- Pointers must reference physical memory (no memory-mapped hardware)
|
|
|
|
|
- Pointers must be properly aligned for their target type
|
|
|
|
|
- Pointers may only be NULL where UEFI explicitly allows for it
|
|
|
|
|
- When an UEFI function fails, nothing can be assumed about the state of data
|
|
|
|
|
behind `*mut` pointers.
|
2020-06-24 11:46:21 +03:00
|
|
|
|
|
|
|
|
## Adding new protocols
|
|
|
|
|
|
2020-12-01 10:32:58 +02:00
|
|
|
You should start by [forking this repository][fork] and cloning it.
|
|
|
|
|
|
2020-06-24 11:46:21 +03:00
|
|
|
UEFI protocols are represented in memory as tables of function pointers,
|
|
|
|
|
each of which takes the protocol itself as first parameter.
|
|
|
|
|
|
|
|
|
|
In `uefi-rs`, protocols are simply `struct`s containing `extern "efiapi" fn`s.
|
|
|
|
|
It's imperative to add `#[repr(C)]` to ensure the functions are laid out in memory
|
|
|
|
|
in the order the UEFI spec requires.
|
|
|
|
|
|
|
|
|
|
Each protocol also has a Globally Unique Identifier (in the C API, they're usually
|
|
|
|
|
found in a `EFI_*_PROTOCOL_GUID` define). In Rust, we store the GUID as an associated
|
|
|
|
|
constant, by implementing the unsafe trait `uefi::proto::Identify`. For convenience,
|
2022-12-11 04:27:08 -05:00
|
|
|
this is done through the `unsafe_protocol` macro.
|
2020-06-24 11:46:21 +03:00
|
|
|
|
|
|
|
|
Finally, you should derive the `Protocol` trait. This is a marker trait,
|
|
|
|
|
extending `Identify`, which is used as a generic bound in the functions which retrieve
|
|
|
|
|
protocol implementations.
|
|
|
|
|
|
|
|
|
|
An example protocol declaration:
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
/// Protocol which does something.
|
|
|
|
|
#[repr(C)]
|
2022-12-11 04:27:08 -05:00
|
|
|
#[unsafe_protocol("abcdefgh-1234-5678-9012-123456789abc")]
|
2020-06-24 11:46:21 +03:00
|
|
|
pub struct NewProtocol {
|
|
|
|
|
some_entry_point: extern "efiapi" fn(
|
|
|
|
|
this: *const NewProtocol,
|
|
|
|
|
some_parameter: SomeType,
|
|
|
|
|
some_other_parameter: SomeOtherType,
|
|
|
|
|
) -> Status,
|
|
|
|
|
some_other_entry_point: extern "efiapi" fn(
|
|
|
|
|
this: *mut NewProtocol,
|
|
|
|
|
another_parameter: AnotherType,
|
|
|
|
|
) -> SomeOtherResult,
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
There should also be an `impl` block providing safe access to the functions:
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
impl NewProtocol {
|
|
|
|
|
/// This function does something.
|
|
|
|
|
pub fn do_something(&self, a: SomeType, b: SomeOtherType) -> Result {
|
|
|
|
|
// Call the wrapped function
|
|
|
|
|
let status = unsafe { (self.some_entry_point)(self, a, b) };
|
|
|
|
|
// `Status` provides a helper function for converting to `Result`
|
|
|
|
|
status.into()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
2020-12-01 10:32:58 +02:00
|
|
|
|
|
|
|
|
[fork]: https://docs.github.com/en/free-pro-team@latest/github/getting-started-with-github/fork-a-repo
|
2021-12-12 20:36:44 +02:00
|
|
|
|
|
|
|
|
## Publishing new versions of the crates
|
|
|
|
|
|
2021-12-12 21:44:45 +02:00
|
|
|
Maintainers of this repository might also be interested in [the guidelines](PUBLISHING.md)
|
2021-12-12 20:36:44 +02:00
|
|
|
for publishing new versions of the uefi-rs crates.
|