Skip to content

patina-v16.0.0

Choose a tag to compare

@github-actions github-actions released this 20 Nov 20:50
· 458 commits to refs/heads/main since this release

What's Changed

  • PE Image Load: Include image name on failure @vineelko (#1069)
    Change Details
      ## Description

    PE Image Load: Include image name on failure

    • Impacts functionality?
    • Impacts security?
    • Breaking change?
    • Includes tests?
    • Includes documentation?

    How This Was Tested

    Validated on Q35

    Integration Instructions

    NA




  • patina\_debugger: Switch breakpoint to be conditional @cfernald (#1087)
    Change Details
      ## Description

    The breakpoint always causing an exception may not be well understood and could lead to people leaving breakpoints in production code causing unexpected exceptions. This commit changes the existing breakpoint function to only trigger a breakpoint if the debugger is enabled, and renames the existing breakpoint function to breakpoint_unchecked to indicate that it will always trigger a breakpoint regardless of the debugger state.

    • Impacts functionality?
    • Impacts security?
    • Breaking change?
    • Includes tests?
    • Includes documentation?

    How This Was Tested

    Unit tests

    Integration Instructions

    N/A

      </blockquote>
      <hr>
    </details>
    
  • Resolve issues with compiling on aarch64 hosts @cfernald (#1089)
    Change Details
      ## Description
    1. Resolves non-comprehensive conditional compilation causing compilation errors on aarch64 hosts for test.
    2. Disables testing failing on aarch64 hosts due to issue #1071.
    3. Fixes compiler warnings due to unused includes in aarch64 test compilation.
    • Impacts functionality?
    • Impacts security?
    • Breaking change?
    • Includes tests?
    • Includes documentation?

    How This Was Tested

    CI tested

    Integration Instructions

    N/A

      </blockquote>
      <hr>
    </details>
    

⚠️ Breaking Changes

  • [REBASE\&FF] Move the `Core` to be 'static for the platform binary @Javagedes (#1049)
    Change Details
      ## Description

    This pull request implements the major breaking changes that will be introduced as a part of RFC #22. Overall, this pull request does the following things:

    1. This commit moves platform configuration of the core into the
      PlatformInfo trait. This trait has multiple type associations for
      configuring the different subsystems of the core. As of this commit
      the following type associations exist:
      • ComponentInfo used to attach and configure patina components to
        be dispatched by the core.
      • CpuInfo used to configure cpu releated functionality such as the
        GIC Bases for AARCH64 systems.
      • MemoryInfo used to configure memory related functionality such as
        prioritizing 32 bit memory allocations.
    2. It requires the core to be static within the platform binary and simplifies the initialization process for the platform.
    3. Updates all documentation to reflect the new interface

    Side Effects

    Due to the changes listed above, there are some minor side effects that have occurred:

    1. Initialization of the advanced logger (To get the address) is now implemented on the Logger itself, and not the component (and renamed to init).
    2. Patina component dispatch has been moved into its own subsystem with its own TPL Mutex
    3. The Decompress trait is no longer a service but rather specified as an associated type by the Plaform trait. SectionExtractorNull has been added back.
    4. GicBases is no longer a config, but a required Platform trait method for AARCH64 systems that will cause a compilation error if not provided
    5. The timer frequency is no longer a config, but an optional Platform trait method.

    Reference Q35 / SBSA implementation: OpenDevicePartnership/patina-dxe-core-qemu#74

    • Impacts functionality?
    • Impacts security?
    • Breaking change?
    • Includes tests?
    • Includes documentation?

    How This Was Tested

    Boot to Shell on Q35, SBSA

    Integration Instructions

    PlatformInfo trait

    Platforms must now implement the PlatformInfo trait which describes the platform customizations for the Core. This trait has multiple type associations to provide customizations to the different subsystems of the core. They can be implemented on the same type (example below), or implemented on separate types to support re-use for different platforms. See below:

    use patina_dxe_core::*;
    use patina_adv_logger::components
    
    struct Q35;
    
    impl ComponentInfo for Q35 {
        fn components(mut add: Add<Component>) {
            add.component(q35_services::mm_config_provider::MmConfigurationProvider);
            add.component(q35_services::mm_control::QemuQ35PlatformMmControl::new());
            add.component(patina_mm::component::sw_mmi_manager::SwMmiManager::new());
        }
    
        fn configs(mut add: Add<Config>) {
            add.config(patina_mm::config::MmCommunicationConfiguration {
                    acpi_base: patina_mm::config::AcpiBase::Mmio(0x0), // Actual ACPI base address will be set during boot
                    cmd_port: patina_mm::config::MmiPort::Smi(0xB2),
                    data_port: patina_mm::config::MmiPort::Smi(0xB3),
                    comm_buffers: vec![],
                });
        }
    }
    
    impl MemoryInfo for Q35 { }
    
    impl CpuInfo for Q35 { }
    
    impl Platform for Q35 {
        type MemoryInfo = Self;
        type ComponentInfo = Self;
        type CpuInfo = Self;
        type Extractor = CompositeSectionExtractor;
    }

    Core must now be 'static

    The core must now be initialized as a static. Its interface has now also changed. Building off the above example, you would add:

    static CORE: Core<Q35> = Core::new(CompositeSectionExtractor::new());
    
    #[cfg_attr(target_os = "uefi", unsafe(export_name = "efi_main"))]
    pub extern "efiapi" fn _start(physical_hob_list: *const c_void) -> ! {
        CORE.entry_point(physical_hob_list)
    }

    Advanced Logger init changes

    The init_advanced_logger method has moved to the static logger struct and is renamed to init, rather than the component.

    static LOGGER: AdvancedLogger<Uart16550> = AdvancedLogger::new(
        Format::Standard,
        &[
            ("goblin", log::LevelFilter::Off),
            ("gcd_measure", log::LevelFilter::Off),
            ("allocations", log::LevelFilter::Off),
            ("efi_memory_map", log::LevelFilter::Off),
        ],
        log::LevelFilter::Info,
        Uart16550::Io { base: 0x402 },
    );
    
    #[cfg_attr(target_os = "uefi", unsafe(export_name = "efi_main"))]
    pub extern "efiapi" fn _start(physical_hob_list: *const c_void) -> ! {
          // SAFETY: The physical_hob_list pointer is considered valid at this point as it's provided by the core
        // to the entry point.
        unsafe { LOGGER.init(physical_hob_list).unwrap(); }
        log::set_logger(&LOGGER).map(|()| log::set_max_level(log::LevelFilter::Trace)).unwrap();
    
        CORE.entry_point(physical_hob_list)
    }
      </blockquote>
      <hr>
    </details>
    

🐛 Bug Fixes

  • patina\_dxe\_core: Tests: Fix Intermittent Test Failure @os-d (#1094)
    Change Details
      ## Description

    Recent tests added a MockPageTable to the static GCD, but this is not cleaned up on GCD.reset(). As a result, there is a race condition where certain tests that expect there not to be a page table installed in the GCD can fail. This fixes that by removing the page table if installed in GCD.reset().

    • Impacts functionality?
    • Impacts security?
    • Breaking change?
    • Includes tests?
    • Includes documentation?

    How This Was Tested

    Had a 100% repro with cargo test after this no repro. Confirmed this was the issue under the debugger.

    Integration Instructions

    N/A.

      </blockquote>
      <hr>
    </details>
    

📖 Documentation Updates

  • [REBASE\&FF] Move the `Core` to be 'static for the platform binary @Javagedes (#1049)
    Change Details
      ## Description

    This pull request implements the major breaking changes that will be introduced as a part of RFC #22. Overall, this pull request does the following things:

    1. This commit moves platform configuration of the core into the
      PlatformInfo trait. This trait has multiple type associations for
      configuring the different subsystems of the core. As of this commit
      the following type associations exist:
      • ComponentInfo used to attach and configure patina components to
        be dispatched by the core.
      • CpuInfo used to configure cpu releated functionality such as the
        GIC Bases for AARCH64 systems.
      • MemoryInfo used to configure memory related functionality such as
        prioritizing 32 bit memory allocations.
    2. It requires the core to be static within the platform binary and simplifies the initialization process for the platform.
    3. Updates all documentation to reflect the new interface

    Side Effects

    Due to the changes listed above, there are some minor side effects that have occurred:

    1. Initialization of the advanced logger (To get the address) is now implemented on the Logger itself, and not the component (and renamed to init).
    2. Patina component dispatch has been moved into its own subsystem with its own TPL Mutex
    3. The Decompress trait is no longer a service but rather specified as an associated type by the Plaform trait. SectionExtractorNull has been added back.
    4. GicBases is no longer a config, but a required Platform trait method for AARCH64 systems that will cause a compilation error if not provided
    5. The timer frequency is no longer a config, but an optional Platform trait method.

    Reference Q35 / SBSA implementation: OpenDevicePartnership/patina-dxe-core-qemu#74

    • Impacts functionality?
    • Impacts security?
    • Breaking change?
    • Includes tests?
    • Includes documentation?

    How This Was Tested

    Boot to Shell on Q35, SBSA

    Integration Instructions

    PlatformInfo trait

    Platforms must now implement the PlatformInfo trait which describes the platform customizations for the Core. This trait has multiple type associations to provide customizations to the different subsystems of the core. They can be implemented on the same type (example below), or implemented on separate types to support re-use for different platforms. See below:

    use patina_dxe_core::*;
    use patina_adv_logger::components
    
    struct Q35;
    
    impl ComponentInfo for Q35 {
        fn components(mut add: Add<Component>) {
            add.component(q35_services::mm_config_provider::MmConfigurationProvider);
            add.component(q35_services::mm_control::QemuQ35PlatformMmControl::new());
            add.component(patina_mm::component::sw_mmi_manager::SwMmiManager::new());
        }
    
        fn configs(mut add: Add<Config>) {
            add.config(patina_mm::config::MmCommunicationConfiguration {
                    acpi_base: patina_mm::config::AcpiBase::Mmio(0x0), // Actual ACPI base address will be set during boot
                    cmd_port: patina_mm::config::MmiPort::Smi(0xB2),
                    data_port: patina_mm::config::MmiPort::Smi(0xB3),
                    comm_buffers: vec![],
                });
        }
    }
    
    impl MemoryInfo for Q35 { }
    
    impl CpuInfo for Q35 { }
    
    impl Platform for Q35 {
        type MemoryInfo = Self;
        type ComponentInfo = Self;
        type CpuInfo = Self;
        type Extractor = CompositeSectionExtractor;
    }

    Core must now be 'static

    The core must now be initialized as a static. Its interface has now also changed. Building off the above example, you would add:

    static CORE: Core<Q35> = Core::new(CompositeSectionExtractor::new());
    
    #[cfg_attr(target_os = "uefi", unsafe(export_name = "efi_main"))]
    pub extern "efiapi" fn _start(physical_hob_list: *const c_void) -> ! {
        CORE.entry_point(physical_hob_list)
    }

    Advanced Logger init changes

    The init_advanced_logger method has moved to the static logger struct and is renamed to init, rather than the component.

    static LOGGER: AdvancedLogger<Uart16550> = AdvancedLogger::new(
        Format::Standard,
        &[
            ("goblin", log::LevelFilter::Off),
            ("gcd_measure", log::LevelFilter::Off),
            ("allocations", log::LevelFilter::Off),
            ("efi_memory_map", log::LevelFilter::Off),
        ],
        log::LevelFilter::Info,
        Uart16550::Io { base: 0x402 },
    );
    
    #[cfg_attr(target_os = "uefi", unsafe(export_name = "efi_main"))]
    pub extern "efiapi" fn _start(physical_hob_list: *const c_void) -> ! {
          // SAFETY: The physical_hob_list pointer is considered valid at this point as it's provided by the core
        // to the entry point.
        unsafe { LOGGER.init(physical_hob_list).unwrap(); }
        log::set_logger(&LOGGER).map(|()| log::set_max_level(log::LevelFilter::Trace)).unwrap();
    
        CORE.entry_point(physical_hob_list)
    }
      </blockquote>
      <hr>
    </details>
    
  • patina: test: Add test on event callback support @Javagedes (#927)
    Change Details
      Please Note: This PR is finished, and ready for review, however this is marked as draft, as some tests are disabled until RFC 0017 is completed.

    Description

    adds a new attribute for the #[patina_test] attribute macro that allows the user to specify a UEFI event that the test should be executed on. When the UEFI event callback is fired, the patina_test will be executed.

    This new attribute is #[on(event= <REAL_GUID>)] e.g. #[on(event = r_efi::efi::EVENT_GROUP_READY_TO_BOOT)].

    After this change, not all patina_tests are executed immediately during the TestRunner component. Due To this, test result reporting is delayed to two separate event callbacks. Test results are now reported once at READY_TO_BOOT and once at EXIT_BOOT_SERVICES.

    The fail_fast config feature has been removed. This is because not all tests happen within the control of the TestRunner component, and thus cannot fail if it wanted to. Instead, an optional callback can be registered by the platform to handle an error however the platform prefers, that is executed anytime a test fails.

    Example Test reporting:

    INFO - INFO - Patina on-system unit-test results:
    INFO -   patina_adv_logger::integration_test::adv_logger_test ... ok (1 passes)
    INFO -   patina_dxe_core::memory_manager::memory_manager_allocations_test ... ok (1 passes)
    INFO -   patina_dxe_core::memory_manager::memory_manager_attributes_test ... ok (1 passes)
    INFO -   qemu_q35_dxe_core::my_test ... ok (413 passes)
    INFO -   qemu_q35_dxe_core::ready_to_boot_test ... ok (1 passes)
    
    • Impacts functionality?
    • Impacts security?
    • Breaking change?
    • Includes tests?
    • Includes documentation?

    How This Was Tested

    Boot to QEMUQ35 with various tests that use the event callback logic.

    Integration Instructions

    1. Developers can now edit or write patina_tests that use the newly created attribute macro. This attribute macro allows you to specify an event guid to have your test executed on. Example seen below. Please note that if an invalid guid is provided, or the event never fires, the test results will report the test as "not triggered"
    #[patina_test]
    #[on(event = r_efi::efi::EVENT_GROUP_READY_TO_BOOT)]
    fn my_patina_test() -> Result {
      Ok(())
    }
    1. Developers can now register a callback function that is executed if a test fails
    let component = TestRunner::default().with_callback(|test_name, err_msg| {
        panic!("{test_name} errored with result {err_msg});
    });
    1. Remove any configuration of fail_fast e.g. fail_fast(...). Replace with custom error handling when a patina test fails with .with_callback(fn(&'static str, &'static str))

Full Changelog: patina-v15.1.0...v16.0.0