patina
Copilot instructions556 starsChanged 6 months agoApache-2.0View on GitHub
Patina is a Rust-based UEFI firmware project. It currently replaces the traditional C-based EDK II DXE Core with a Rust implementation that introduces a component-based architecture with dependency injection in addition to a general-purpose UEFI Rust SDK. The workspace is organized into four top-level areas: - components/ - Feature components (ACPI, Advanced Logger, MM, Performance, SMBIOS, etc.) - core/ - Shared core internals (debugger, collections, CPU, dependency expressions, stack traces) - patinadxecore/ - Main DXE Core library that ties everything…
We split this copilot-instructions.md into the rules it gives an agent
26 rules. About 0 are common, 5 are distinctive, and 21 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
21
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 23
All commands go through cargo make.
- Very specific: line 38
Never use mod.rs files. Use named module files (e.g., my_module.rs) instead.
- Very specific: line 39
No public definitions directly in lib.rs - only public module declarations.
- Very specific: line 56
Prefer zerocopy for binary data and memory layouts over manual unsafe pointer/slice operations.
- Very specific: line 60
Document preconditions, postconditions, and invariants for every unsafe block.
- Very specific: line 61
Prefer fallible constructors returning Result over constructors that silently handle invalid input or panic.
- Very specific: line 72
Prefer Result return types.
- Very specific: line 77
Use expect("descriptive message") over bare unwrap().
- Very specific: line 85
Use the log crate for structured logging.
- Distinctive: line 88
Do not log in hot paths or have entry/exit logs.
- Very specific: line 89
Prefer using patina::writelncrlf for formatting strings that will be logged over writeln!
- Distinctive: line 106
Use the stored dependencies pattern: store all dependency references as fields in the component struct.
- Distinctive: line 115
Write tests to cover critical logic and edge cases, not just to hit coverage numbers.
- Very specific: line 116
Test naming: prefix with test_<component_name>_ or test_<service_name>_.
- Very specific: line 117
Prefer mockall for trait mocking in unit tests.
- Very specific: line 118
Use pretty_assertions for readable test diffs.
- Distinctive: line 129
Keep traits focused on a single responsibility (Interface Segregation).
- Very specific: line 136
All public items must be documented.
- Very specific: line 137
Use /// doc comments with these sections as appropriate: Examples, Errors,
- Distinctive: line 139
Document traits, not their implementations.
- Very specific: line 148
Use TplMutex for synchronization in shared state.
- Very specific: line 150
Do not use TplMutex for interior mutability on non-shared data.
- Very specific: line 151
No memory allocation or deallocation after ExitBootServices.
- Very specific: line 161
Do not create Rust references (&T or &mut T) to MMIO space.
- Very specific: line 185
All external dependencies are vetted via cargo-deny for license compatibility, security advisories, and allowed sources.
- Very specific: line 187
Use workspace-level dependency declarations in the root Cargo.toml for consistency.
≈ “Common” is an estimate: at least 1 in 5 of the 3,669 Copilot instructions files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Patina Project Instructions
Patina is a Rust-based UEFI firmware project. It currently replaces the traditional C-based EDK II DXE Core with a Rust implementation that introduces a component-based architecture with dependency injection in addition to a general-purpose UEFI Rust SDK.
Project Structure
The workspace is organized into four top-level areas:
components/- Feature components (ACPI, Advanced Logger, MM, Performance, SMBIOS, etc.)core/- Shared core internals (debugger, collections, CPU, dependency expressions, stack traces)patina_dxe_core/- Main DXE Core library that ties everything togethersdk/- Public SDK (patinacrate for Boot/Runtime Services, component infrastructure,patina_ffsfor firmware file system,patina_macrofor proc-macros)
Crate dependency rules are strict. Components depend on sdk/ only - never on each other or on core/. The SDK
depends only on generic external crates. Core crates may depend on each other and on the SDK. See
docs/src/dev/code_organization.md for the full dependency matrix.
Build and Test Commands
All commands go through cargo make. Never run raw cargo commands.
cargo make check- Type-check all codecargo make fmt- Format code (run after every edit)cargo make clippy- Lint with clippycargo make test- Run all unit testscargo make all- Full PR readiness (fmt-check, deny, cspell, clippy, build, test, coverage, doc)cargo make build-x64/cargo make build-aarch64- Build for UEFI targetscargo make coverage- Generate test coverage reportscargo make doc- Build documentation
See Makefile.toml for the complete command list.
Module Organization
- Never use
mod.rsfiles. Use named module files (e.g.,my_module.rs) instead. - No public definitions directly in
lib.rs- only public module declarations. - Break implementations into logical files with clean namespaces.
- Crate naming:
patina_prefix for public crates,patina_internal_for internal crates,_macrosuffix for proc-macro crates.
// WRONG: using mod.rs
// src/memory/mod.rs
// CORRECT: using named module file
// src/memory.rsSee docs/src/component/requirements.md for crate layout standards.
Safety Conventions
- Prefer
zerocopyfor binary data and memory layouts over manual unsafe pointer/slice operations.zerocopyprovides safe, zero-cost abstractions for interpreting byte buffers as typed data. - Minimize
unsafecode. Constrain it within safe abstraction wrappers. - Document preconditions, postconditions, and invariants for every
unsafeblock. - Prefer fallible constructors returning
Resultover constructors that silently handle invalid input or panic. - Mark functions
unsafeonly when the caller must uphold a contract the function itself cannot verify internally. If the function validates all inputs before the unsafe operation, it can remain safe.
See docs/src/dev/principles/unsafe.md for the full safety philosophy
(software safety vs. hardware safety distinctions).
Error Handling
- Prefer
Resultreturn types. Avoid panics in production code. - At UEFI ABI boundaries (
extern "efiapi"functions), useefi::Status. - Internally, use domain-specific Rust error types with
Debug,Display, andErrortrait implementations. - Implement
From<>conversions at error type boundaries to create clean error chains. - Use
expect("descriptive message")over bareunwrap(). Reserveunwrap()for test code only.
See docs/src/dev/principles/error-handling.md for error
propagation patterns and examples.
Logging
- Use the
logcrate for structured logging. - Log at appropriate levels:
trace,debug,info,warn,error. - Include relevant context in log messages.
- Do not log in hot paths or have entry/exit logs.
- Prefer using
patina::writelncrlffor formatting strings that will be logged overwriteln!.
Component Model
Patina uses dependency injection through component entry point function signatures. A component only executes when all its declared dependencies are available.
- Define components with the
#[component]attribute macro on animplblock. The impl must containfn entry_point(self, ...) -> Result<()>. - Register service implementations with
#[derive(IntoService)]and#[service(dyn Trait)]. - Param types:
Config<T>,ConfigMut<T>,Service<T>,Hob<T>,Protocol<P>,Commands,Handle,StandardRuntimeServices,&Storage/&mut Storage,Option<P>, tuples. ConfigMut<T>components run first (config is unlocked); callinglock()makes the value immutable and enablesConfig<T>components to execute.Service<dyn Trait>is preferred overService<ConcreteType>for mockability. Use a concrete wrapper struct only when generic method signatures are needed.- Use the stored dependencies pattern: store all dependency references as fields in the component struct. The entry point stores references; methods use them.
See docs/src/component/interface.md and
docs/src/component/getting_started.md for details and examples.
Mocking and Testing
- Target ≥80% code coverage. Patch coverage ≥80% is a required PR check.
- Write tests to cover critical logic and edge cases, not just to hit coverage numbers.
- Test naming: prefix with
test_<component_name>_ortest_<service_name>_. - Prefer
mockallfor trait mocking in unit tests. Use#[automock]on traits to generate mocks. - Use
pretty_assertionsfor readable test diffs.
See docs/src/dev/testing.md for the full testing strategy.
Trait Design
Traits serve as abstraction points - not code reuse mechanisms. Use crates for
code reuse (see docs/src/dev/principles/reuse.md).
- Define traits to represent swappable behavior (e.g.,
BootServices,SerialIO). - Implementations can vary per platform without affecting consumers.
- Keep traits focused on a single responsibility (Interface Segregation).
See docs/src/dev/principles/abstractions.md for the full trait
design philosophy.
Documentation Standards
- All public items must be documented. Set
#[deny(missing_docs)]in component crates. - Use
///doc comments with these sections as appropriate: Examples, Errors, Safety, Panics. - Document traits, not their implementations.
- In most cases, do not add
# Argumentsor# Returnssections - the function signature should be self-evident. In cases where there is unavoidable ambiguity, add these sections to provide clarity.
See docs/src/dev/documenting.md for templates and style guides.
UEFI-Specific Guidelines
- Use
TplMutexfor synchronization in shared state. Do not use non-TPL-aware primitives likespin::Mutex. Keep critical sections narrow. - Do not use
TplMutexfor interior mutability on non-shared data. - No memory allocation or deallocation after
ExitBootServices.
See docs/src/dxe_core/synchronization.md,
docs/src/dxe_core/memory_management.md, and
docs/src/integrate/patina_dxe_core_requirements.md.
Hardware Access
Memory-Mapped I/O (MMIO)
Do not create Rust references (&T or &mut T) to MMIO space. The compiler may
insert spurious reads through references, which can clear interrupt status bits, pop
FIFO entries, or trigger other device side-effects. MMIO must be accessed exclusively
through raw pointers with volatile operations.
Patina uses the https://github.com/google/safe-mmio crate for all MMIO
access. safe-mmio provides UniqueMmioPointer<T> which never creates a &T to device
memory. Its field wrapper types encode read side-effect semantics at the type level:
ReadPure<T>/ReadPureWrite<T>— reads have no side-effects (shared access OK).ReadOnly<T>/ReadWrite<T>— reads have side-effects (require&mutaccess).WriteOnly<T>— write-only register.
See docs/src/dev/hardware_access/mmio.md for the full rationale, wrapper
reference table, and links to safe-mmio documentation.
Architectural Interfaces
Minimize the use of inline assembly. Generally, architectural interfaces accessed through inline assembly should be wrapped in safe Rust abstractions in the SDK. The exception to this is if the interface is not generally applicable.
Dependency Management
- All external dependencies are vetted via
cargo-denyfor license compatibility, security advisories, and allowed sources. - Use workspace-level dependency declarations in the root
Cargo.tomlfor consistency. - Evaluate new dependencies against the criteria in
docs/src/dev/principles/dependency-management.md.
Formatting
Formatting is enforced by rustfmt via rustfmt.toml. Always run
cargo make fmt after editing code.
Common Anti-Patterns
Flag these patterns during review:
- Using
mod.rsinstead of named module files - Raw slice/pointer manipulation where
zerocopywould work - Unnecessary
unsafewithout a safe abstraction wrapper unwrap()in production code (outside of tests)- Cross-component dependencies (components must only depend on
sdk/) - Adding public type definitions directly in
lib.rs - Missing documentation on public items
- Using non-TPL-aware synchronization primitives for shared state
- Creating Rust references (
&T/&mut T) to MMIO space instead of usingsafe-mmio
Where files are headingNew Copilot instructions files have more rules about branches and pull requests, and fewer about code style.
Of the Copilot instructions files we read, the 2,297 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

