[major] Add Initial Patina UEFI Services [Rebase & FF] - #1743
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
|
I'm working on some changes to improve unit test coverage. |
ℹ️ QEMU Validation Skipped - Unsupported Target BranchThe Patina QEMU PR validation workflow did not run because the PR targets an unsupported branch. Workflow run: https://github.com/OpenDevicePartnership/patina/actions/runs/34271695917
This comment was automatically generated by the Patina QEMU PR Validation Post workflow. |
f63f1af to
3e810b7
Compare
Pushed. Also updated the |
cfernald
left a comment
There was a problem hiding this comment.
just reviewed the SDK interface for now. Will review the full changes later.
kat-perez
left a comment
There was a problem hiding this comment.
I found several safety and contract issues in the new service layer that should be addressed before merge. The inline comments focus on callback lifetime, protocol reference lifetime, marker protocol compatibility, and duration conversion.
Withdrawn by reviewer for additional cross-checking before feedback is submitted.
b9d0dbd to
75530e3
Compare
|
@Javagedes, @cfernald, @kat-perez, this is ready for you review again when you get time. |
Updates `acpi_protocol_test` to use `ProtocolServices` instead of `StandardBootServices` to locate the ACPI Table and ACPI Get protocols. This allows two unsafe code blocks at the call sites to be removed. This was the last `StandardBootServices` usage in the crate, so `patina_acpi` no longer depends on it at all. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
`CpuArchProtocolInstaller`, `HwInterruptProtocolInstaller`, `SystemTableChecksumInstaller`, and `DecompressProtocolInstaller` were the last components in patina_dxe_core still depending on `StandardBootServices` directly. This change moves them onto `Service<dyn ProtocolServices>` so `StandardBootServices` can be removed from the component model in a follow up change. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Now that no component in patina_dxe_core depends on `StandardBootServices` directly, this drops `ComponentDispatcher::set_boot_services` and the code in `Core::initialize_system_table` that constructed a `StandardBootServices` for the component dispatcher. `StandardRuntimeServices` not modified. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Removes the `StandardBootServices` param from the component benchmark entrry points since `StandardBootServices` is about to be removed from the component model. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Removes the `StandardBootServices` `Param` implementation and all references to it. Removes the `boot_services` field from `Storage`. Removes logic in the `#[component]` parameter validation macro that checked for duplicate `StandardBootServices` parameters. In cases where `StandardBootServices` was used as an example type in tests for `Option<T>` and tuple `Param` implementations, it was replaced with `StandardRuntimeServices`. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Straightforward update to docs that referenced `StandardBootServices` to either drop the reference or replace it with the equivalent info or example from UEFI Services. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Provides a `locate_first_handle()` method to more conveniently find a single handle that supports a given protocol. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Adds a `DriverBinding` trait that can be implemented and passed to `install_driver_binding()` to produce a driver binding protocol in a component. Since components are all statically compiled with the DXE Core, they cannot use image handles as agent handles as is common in C-based DXE drivers. Therefore, a `register_agent()` function is added to `ProtocolServices` that generates a unique agent handle for a component to use when opening protocols. An example of using this API and opening a protocol is added to `patina_samples`. The `open_protocol()` interface is updated to accept an agent handle and `OpenAttributes` that describe how the protocol is being opened. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Moves driver.rs and driver_binding.rs from component/service/uefi_services into a new component/service/uefi_services/driver_model module. Both files expose services that are part of the UEFI Driver Model, connecting drivers to controllers and producing a driver binding protocol, so grouping them together gives components and future additions like component name publishing a clear place in the SDK. Had to broaden `DriverBindingHolder` and its trampoline functions from `pub(super)` to `pub(in crate::component::service::uefi_services)` since protocol.rs is no longer a direct sibling. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Add `LanguageTable` and `LanguageEntry` under `component::service::uefi_services::driver_model`. A `LanguageTable` holds a small list of names, each paired with the ISO 639-2 code the legacy component name protocol uses and the RFC 4646 tag the current one uses. This is similar to how EDK II drivers share `EFI_UNICODE_STRING_TABLE` between both protocols. `lookup_v1()` matches the fixed three character ISO 639-2 code. `lookup_v2()` matches the RFC 4646 tag case insensitively, then falls back to the primary subtag, this covers a practical subset of what `GetBestLanguage()` (in EDK II) does. Neither method depends on anything specific to a protocol, so both can be reused by whatever eventually consumes the table. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
This temporary definition of the component name v1 and v2 protocols is added until the r-efi changes are released. This commit should simply be reverted and the r-efi protocol used (through the SDK re-export) when it is released. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
…tion (until in r-efi) This temporary definition of the EFI Driver Supported EFI Version protocol is added until the r-efi changes are released. This commit should simply be reverted and the r-efi protocol used (through the SDK re-export) when it is released. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
…cols Adds a trait that a component can implement to publish both `EFI_COMPONENT_NAME_PROTOCOL` and `EFI_COMPONENT_NAME2_PROTOCOL`. This prevents components from handling raw structures and maintaining their `SupportedLanguages` strings (having to keep them in sync) the way a C driver does today. `driver_name` is required and returns a `LanguageTable`. `controller_name` defaults to returning `None`. Many drivers only name themselves and do not name their controllers. Adds a new function `install_uefi_driver_model_component_name()` to `ProtocolServicesExt`. This function builds both protocols from a single implementation and computes each protocol's `SupportedLanguages` from the driver name table, and installs both on the same handle. If installing the second protocol fails, the first is uninstalled so a partial publish is not left behind. The `Language` parameter is handled differently between the two protocols because the UEFI specification treats them differently. `EFI_COMPONENT_NAME_PROTOCOL`'s `Language` is a fixed three byte ISO 639-2 code with no NUL termination guarantee, so it is read as a three byte buffer. `EFI_COMPONENT_NAME2_PROTOCOL`'s `Language` is a NUL terminated RFC 4646 tag, so it is read with the existing `Char8Str` type. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Adds `ComponentNameProducerSample` to show a component that publishes a fixed English driver name using `install_uefi_driver_model_component_name()`. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
…I Services To ease UEFI driver model development, this adds a function to `ProtocolServicesExt` to build and install the EFI Driver Supported EFI Version protocol on a handle, creating a new handle if needed. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Demonstrates how to install an instance of the EFI Driver Supported EFI Version protocol on a handle. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Adds a new `Param` type, `Protocol<P>`, so a component's `entry_point` can depend on a specific UEFI protocol interface being installed. The component is not dispatched until both the `ProtocolServices` service and an interface for `P` are available. Dereferencing the parameter gives direct access to the interface. Reuses `Param` implementation from `Service<dyn ProtocolServices>` where possible, with a `locate_interface()` check in `validate()`. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Shows how a `Protocol<P>` parameter can be used to gate component dispatch on a protocol being installed. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Add the PCD Protocol definition to the Patina SDK and implement `ProtocolInterface` for it. This is only intended to be used by a Patina PCD service wrapper to provide service-based access to components that must read and write dynamic PCDs to interact with existing C-based code in an overall software stack. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Adds a trait to define PCD accessors, and a `PcdError` type. Expected to be used by a component to produce a PCD Service and by other component that need to interact with PCDs using the service. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Adds `patina_pcd`, a component that locates `PCD_PROTOCOL` and produces a `PcdServices` service so other components can get and set `Dynamic` and `DynamicEx` PCDs. The `PcdProvider` component takes `Protocol<PcdProtocol>` as an entry point parameter and registers itself as the `PcdServices` service. Scope is limited to get and set. SKU selection, set-callbacks, and token/token-space enumeration are not supported. In general, Patina components should not use PCDs. The Dynamic type PCDs are available through this service only because many C-based drivers dynamically set and read PCD values and, in order for a Patina component to interoperate with those drivers, it must be able to read and set the same PCDs. Patina components that do not have that requirement should not use this service and not include the component at all in their Patina DXE Core binary file where components are selected. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Adds a new Patina Graphics Console Components that implements the functionality of the EDK II GraphicsConsoleDxe driver. Because the EDK II GraphicsConsoleDxe driver is just a participant in a larger UEFI driver model set of drivers, this component is also used to show how a Patina component can participate in the UEFI driver model with other code still written in C and using EDK II-specific mechanisms during DXE execution such as dynamic PCDs. The driver may drop certain extensions specific to EDK II compatibility as more of the dependencies using those features are ported to Patina. The driver is currently not a "drop-in" replacement for the GraphicsConsoleDxe driver as it does not implement a default font package. That will be added in a future commit. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
1fed1b9 to
5051c61
Compare
The C GraphicsConsoleDxe driver registered a default font package
with a single font ("simple font") that was used to render glyphs
when another font was not available. The component currently relies
on an `EFI_HII_FONT_PROTOCOL` that is typically published by
HiiDatabaseDxe. In the C GraphicsConsoleDxe driver, the driver entry
point registers a notify callback on `gEfiHiiDatabaseProtocolGuid`
which calls a `RegisterFontPackage()` function in the driver that
builds a `EFI_HII_SIMPLE_FONT_PACKAGE_HDR` structure that wraps
the glyph data (from `gUsStdNarrowGlyphData`) and then calls
`HiiAddPackages()` to register it with the HII Database.
Originally, the component did not register a default font package.
However, at least on QEMU firmware, the default is used. Therefore,
this change adds a default font package to the component that is
registered with the HII Database if it is available.
This copies the `gUsStdNarrowGlyphData` glyph data exactly from
the C driver. A `font_package` module is added that locates the HII
Database protocol and registers the font package.
Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Adds a document that explains common scenario where services need be shared and stored and patterns for those scenarios. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Adds a document that explains when to use Patina UEFI Services and links to individual service documentation. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
5051c61 to
89f426b
Compare
I made some cumulative changes to better support UEFI Driver Model components, the PR description is updated. The summary of new changes is a |
| /// Ok(()) | ||
| /// } | ||
| /// ``` | ||
| pub trait ConfigTable: Sized + 'static { |
There was a problem hiding this comment.
Why not ?Sized? A lot of config tables are DSTs.
There was a problem hiding this comment.
I went with a different approach than an actual DST as I'm not sure it would work here if following the Config Table ABI in the UEFI Spec (GUID and pointer pairs). An example is SampleDynamicTable.
I thought that gets most of the practical value for a header + trailing data.
| /// Ok(()) | ||
| /// } | ||
| /// ``` | ||
| pub trait ConfigTable: Sized + 'static { |
There was a problem hiding this comment.
It seems odd for the trait to require 'static. I think if this is a requirement to install it should be in the install function instead of the trait.
There was a problem hiding this comment.
Is there a particular reason why? From a boot timeline perspective, a config table is expected to persist through the OS transition, which we treat as 'static. So, it accurately reflects that a UEFI configuration table must stay valid throughout that time once published.
Centralizing it on the trait avoids the lifetime being forgotten elsewhere. The functions rely on TypeId::of::<T>() which requires T be 'static. Functions like get() only return Option<&'static T> so the bound there can just be derived from parameters like in install() where a T parameter is present.
I think it also simplifies tracking what's expected versus manually coordinating/managing it in individual functions.
|
I've made some additional changes to handle pool allocations returned from C code, split GOP-specific logic out to a dedicated component/service and move the default font package into its own component (out of |
Description
Includes an initial merge commit from the current main branch into major.
Adds a new set of Patina component services called "UEFI Services". These services are defined in the Patina SDK, produced by the Patina DXE Core, and used by Patina components.
Main changes:
sdk\patina\src\component\service\uefi_services.patina_dxe_core\src\uefi_services.components\patina_samples\src\component\uefi_services./components) to Patina UEFI Services fromStandardBootServices.ServiceCell<T>for uses cases whereService<T>::new_unit()is used today + an additional case. Slightly controversial. Considered an incremental improvement in clarity and safety. See the commit message for reasoning.StandardBootServicesand related changes to do so across the codebase.Protocol<P>that can allow a protocol to be a dependency for component dispatch.DriverBindingtrait and the ability to generate agent handles - seesdk/patina/src/component/service/uefi_services/driver_binding.rsUefiDriverModelComponentNametrait that can be used for a component to produce the EFI Component Name protocols - seecomponents/patina_samples/src/component/uefi_services/component_name_producer.rsinstall_uefi_driver_model_driver_supported_efi_versionProtocol service to allow components to easily produce the EFI Driver Supported EFI Version Protocol - seesdk/patina/src/component/service/uefi_services/driver_model/driver_supported_efi_version.rscomponents/patina_pcd/.GraphicsConsoleDxedriver. Seecomponents/patina_graphics_console.docs\src\component\storing_state.md.docs\src\component\storing_state.md.How This Was Tested
cargo make allInitial component dispatch (DXE core and sample components):
Later after the Timer Architectural protocol is installed:
End of DXE messages:
All Patina on-system tests pass:
GraphicsConsoleDxefrom QEMU platforms and using thepatina_graphics_consolecomponent instead.Integration Instructions