From 9d6afab837a0214e094410e749baf360fbbf1fab Mon Sep 17 00:00:00 2001 From: Kat Perez Date: Thu, 30 Apr 2026 14:43:12 -0400 Subject: [PATCH] Add ODP_PatinaSmbiosDemo driver --- .gitattributes | 4 + .../Drivers/ODP_PatinaSmbiosDemo/Cargo.lock | 568 ++++++++++++++++++ .../Drivers/ODP_PatinaSmbiosDemo/Cargo.toml | 26 + .../ODP_PatinaSmbiosDemo.depex | 1 + .../Drivers/ODP_PatinaSmbiosDemo/README.md | 87 +++ .../ODP_PatinaSmbiosDemo/rust-toolchain.toml | 9 + .../Drivers/ODP_PatinaSmbiosDemo/src/main.rs | 40 ++ .../ODP_PatinaSmbiosDemo/src/platform.rs | 116 ++++ 8 files changed, 851 insertions(+) create mode 100644 .gitattributes create mode 100644 uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/Cargo.lock create mode 100644 uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/Cargo.toml create mode 100644 uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/ODP_PatinaSmbiosDemo.depex create mode 100644 uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/README.md create mode 100644 uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/rust-toolchain.toml create mode 100644 uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/src/main.rs create mode 100644 uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/src/platform.rs diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..0e8f064 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +# UEFI dependency expressions are compiled bytecode (TRUE/END opcodes etc.), +# not text. Mark as binary so diff viewers stop rendering raw bytes as +# garbled glyphs. +*.depex binary diff --git a/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/Cargo.lock b/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/Cargo.lock new file mode 100644 index 0000000..0b70857 --- /dev/null +++ b/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/Cargo.lock @@ -0,0 +1,568 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ODP_PatinaSmbiosDemo" +version = "0.1.0" +dependencies = [ + "log", + "patina", + "patina_smbios", + "patina_tianocore", +] + +[[package]] +name = "aarch64-cpu" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a21cd0131c25c438e19cd6a774adf7e3f64f7f4d723022882facc2dee0f8bc9" +dependencies = [ + "tock-registers", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "compile-time" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e55ede5279d4d7c528906853743abeb26353ae1e6c440fcd6d18316c2c2dd903" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "rustc_version", + "semver", + "time", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "goblin" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "983a6aafb3b12d4c41ea78d39e189af4298ce747353945ff5105b54a056e5cd9" +dependencies = [ + "log", + "plain", + "scroll", +] + +[[package]] +name = "indoc" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "linkme" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83272d46373fb8decca684579ac3e7c8f3d71d4cc3aa693df8759e260ae41cf" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32d59e20403c7d08fe62b4376edfe5c7fb2ef1e6b1465379686d0f21c8df444b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "mu_rust_helpers" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028b489eb1f6ce61c83feee2cc5e8fb60978115a466c74b84b78aafed6041f34" +dependencies = [ + "mu_uefi_decompress", + "mu_uefi_guid", + "mu_uefi_perf_timer", +] + +[[package]] +name = "mu_uefi_decompress" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b85df261b0b0241dee3c95a186fac29234b0e60bfabef7d57d3099ec2b7cb6" +dependencies = [ + "bitvec", + "log", +] + +[[package]] +name = "mu_uefi_guid" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "091e08bf3b952c68a5d3915d53b4221dc41fad3e00d3eb2020d2dd46f83ae5e2" +dependencies = [ + "r-efi", + "uuid", +] + +[[package]] +name = "mu_uefi_perf_timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df471d72676adaa480d61a0c9ed30a844a90842f876c188a0b30cb760d2444aa" +dependencies = [ + "aarch64-cpu", + "log", +] + +[[package]] +name = "num-conv" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "patina" +version = "21.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45283b21e6ed7c75525b6b4a7b2d6fa9daa002a44cebfe688c17d88b5a5efe22" +dependencies = [ + "cfg-if", + "compile-time", + "fallible-streaming-iterator", + "fixedbitset", + "goblin", + "indoc", + "linkme", + "log", + "mu_rust_helpers", + "num-traits", + "patina_macro", + "r-efi", + "safe-mmio", + "scroll", + "spin", + "uart_16550", + "uuid", + "x86_64", + "zerocopy", + "zerocopy-derive", +] + +[[package]] +name = "patina_macro" +version = "21.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9eb707320aa4e7691ce9738973d0c112902d3a1f30d89d3c39843e214935346" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "uuid", +] + +[[package]] +name = "patina_smbios" +version = "21.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c288ec2368c897742a4a6015abd5afb4188cbc2538d422cffaf639f44911ef7" +dependencies = [ + "log", + "patina", + "patina_macro", + "r-efi", + "spin", + "zerocopy", + "zerocopy-derive", +] + +[[package]] +name = "patina_tianocore" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb43aa11f4adc0a4a1cd8cacb931c9953e42a9fb9383d725fc68061df98403e9" +dependencies = [ + "log", + "patina", + "patina_macro", + "r-efi", + "spin", + "uart_16550", +] + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "raw-cpuid" +version = "10.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "safe-mmio" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0a69f884a1511aa811aa94e04559414a66b18ca63f50f84ca31e304f38bad0d" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scroll" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1257cd4248b4132760d6524d6dda4e053bc648c9070b960929bf50cfb1e7add" +dependencies = [ + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed76efe62313ab6610570951494bdaa81568026e0318eaa55f167de70eeea67d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tock-registers" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b9e2fdb3a1e862c0661768b7ed25390811df1947a8acbfbefe09b47078d93c4" + +[[package]] +name = "uart_16550" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e492212ac378a5e00da953718dafb1340d9fbaf4f27d6f3c5cab03d931d1c049" +dependencies = [ + "bitflags 2.11.1", + "rustversion", + "x86", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "uuid" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" + +[[package]] +name = "volatile" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x86" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2781db97787217ad2a2845c396a5efe286f87467a5810836db6d74926e94a385" +dependencies = [ + "bit_field", + "bitflags 1.3.2", + "raw-cpuid", +] + +[[package]] +name = "x86_64" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae" +dependencies = [ + "bit_field", + "bitflags 2.11.1", + "rustversion", + "volatile", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/Cargo.toml b/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/Cargo.toml new file mode 100644 index 0000000..ca18efa --- /dev/null +++ b/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/Cargo.toml @@ -0,0 +1,26 @@ +# Cargo manifest for the ODP_PatinaSmbiosDemo UEFI DXE driver. +# +# SPDX-License-Identifier: MIT +# + +# Cargo.toml serves a similar role to an EDK II .inf file — it declares the module name, dependencies +# (equivalent to [Packages] and [LibraryClasses]), and build settings. +[package] +name = "ODP_PatinaSmbiosDemo" +version = "0.1.0" +edition = "2024" +rust-version = "1.89" +license = "MIT" +# Demo binary — never published to crates.io. +publish = false + +[[bin]] +name = "ODP_PatinaSmbiosDemo" +path = "src/main.rs" +test = false + +[dependencies] +patina_tianocore = "0.1" +patina = { version = "21", default-features = false, features = ["alloc"] } +patina_smbios = { version = "21", default-features = false } +log = { version = "0.4", default-features = false } diff --git a/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/ODP_PatinaSmbiosDemo.depex b/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/ODP_PatinaSmbiosDemo.depex new file mode 100644 index 0000000..2a47cc2 --- /dev/null +++ b/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/ODP_PatinaSmbiosDemo.depex @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/README.md b/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/README.md new file mode 100644 index 0000000..3e07e13 --- /dev/null +++ b/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/README.md @@ -0,0 +1,87 @@ +# ODP Patina SMBIOS Demonstration Driver + +This driver shows how to build a UEFI DXE driver that produces an SMBIOS Type 0 (BIOS Information) record using **only the native Patina component model** — no `EFI_SMBIOS_PROTOCOL`, no raw buffer construction, no `unsafe` boilerplate inside the publishing component. + +It uses the [`patina_tianocore`](https://crates.io/crates/patina_tianocore) bridge crate to ship today on a TianoCore DXE core while keeping the same source compatible with a Patina-native DXE core later. + +## Assumptions and Limitations + +The reader is assumed to be familiar with UEFI driver authoring and the TianoCore build process. Familiarity with [`ODP_RustDxeDemo`](../ODP_RustDxeDemo) — the prior, lower-level Rust demo using raw `r-efi` — is helpful but not required. + +This driver is compiled outside the EDK II build system and linked into the firmware image via the `.fdf` file, the same way as `ODP_RustDxeDemo`. It depends on the SMBIOS service exposed by `patina_smbios`'s `SmbiosProvider` component, and on the boot services / memory manager wiring done automatically by `patina_tianocore::driver_entry!`. + +## What's where + +``` +ODP_PatinaSmbiosDemo/ +├── Cargo.toml Module manifest +├── ODP_PatinaSmbiosDemo.depex DXE depex (TRUE — no protocol prerequisites) +├── README.md This file +└── src/ + ├── main.rs 3-line driver shell — driver_entry!(...) + └── platform.rs Platform impl + BiosInfoSmbiosPublisher + component. This file is portable across + runtimes; lift it into a shared crate + when you also want a Patina-native binary. +``` + +## Prerequisites + +```bash +# Rust nightly toolchain (required by patina dependencies) +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +rustup target add x86_64-unknown-uefi +``` + +> If your target platform is ARM, replace `x86_64` with `aarch64` (i.e., `aarch64-unknown-uefi`). + +## Compile + +```bash +cd ./uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo +BUILD_DATE=$(date +%m/%d/%Y) cargo build --target x86_64-unknown-uefi --release +``` + +The output will be a PE32+ executable: `target/x86_64-unknown-uefi/release/ODP_PatinaSmbiosDemo.efi`. + +`BUILD_DATE` is consumed by `option_env!("BUILD_DATE")` inside the publisher so the SMBIOS record carries the actual build date. Skipping it is fine — the record falls back to `01/01/1970`. + +## Insert into UEFI build + +Add to your platform `.fdf` (no `.dsc` entry needed): + +```text +FILE DRIVER = C74158C9-87BC-448B-86B1-818071938A4C { + SECTION DXE_DEPEX = /OdpPkg/Drivers/ODP_PatinaSmbiosDemo/ODP_PatinaSmbiosDemo.depex + SECTION PE32 = /OdpPkg/Drivers/ODP_PatinaSmbiosDemo/target/x86_64-unknown-uefi/release/ODP_PatinaSmbiosDemo.efi + SECTION UI = "ODP_PatinaSmbiosDemo" +} +``` + +The `FILE DRIVER` GUID is unique to this driver. The `.depex` is a minimal `TRUE` expression (`0x06 0x08`), unlike `ODP_RustDxeDemo`'s GUID-pinned depex on `gEfiVariableArchProtocolGuid`. This driver only uses boot services and the SMBIOS service it instantiates itself, so it has no protocol prerequisites and dispatches as soon as the DXE phase begins. + +After rebuilding and booting your firmware, the SMBIOS table published to the UEFI Configuration Table will contain a Type 0 record whose vendor string is `"Acme Inc."`. From a UEFI shell: + +``` +Shell> smbiosview -t 0 +``` + +## Migrating to Patina native + +When your firmware is ready to host the Patina DXE core, you do **not** rewrite this driver. You write a sibling crate that uses the same `OemPlatform` struct from `platform.rs`: + +```rust +use my_platform::OemPlatform; + +patina_tianocore::impl_component_info!(OemPlatform); + +impl MemoryInfo for OemPlatform { /* ... */ } +impl CpuInfo for OemPlatform { /* ... */ } +impl PlatformInfo for OemPlatform { /* ... */ } +``` + +The `BiosInfoSmbiosPublisher` component, the `Platform::components` registration, and the SMBIOS record itself transfer with **zero changes**. + +## Customize for your own platform + +In your tree, copy the directory, change the vendor string and BIOS version in `platform.rs`, and add additional record-publishing components alongside `BiosInfoSmbiosPublisher` (Type 1 system info, Type 2 baseboard, Type 3 enclosure, etc. — `patina_smbios::smbios_record` ships typed structs for all standard SMBIOS record types). diff --git a/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/rust-toolchain.toml b/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/rust-toolchain.toml new file mode 100644 index 0000000..0b7adfb --- /dev/null +++ b/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/rust-toolchain.toml @@ -0,0 +1,9 @@ +# Pinned Rust toolchain for ODP_PatinaSmbiosDemo (UEFI targets). +# +# SPDX-License-Identifier: MIT +# + +[toolchain] +channel = "nightly-2025-12-12" +targets = ["x86_64-unknown-uefi", "aarch64-unknown-uefi"] +components = ["rust-src", "clippy", "rustfmt"] diff --git a/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/src/main.rs b/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/src/main.rs new file mode 100644 index 0000000..5bc48c8 --- /dev/null +++ b/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/src/main.rs @@ -0,0 +1,40 @@ +//! ODP Patina SMBIOS Demonstration Driver +//! +//! SPDX-License-Identifier: MIT +//! +//! Shows how to publish an SMBIOS record from a UEFI driver that uses ONLY +//! the native Patina component model — no `EFI_SMBIOS_PROTOCOL`, no raw +//! buffer construction, no `unsafe` boilerplate. +//! +//! This file is the entire TianoCore driver shell. The Platform definition +//! lives in `platform.rs` next to it; the bridge crate `patina_tianocore` +//! handles the rest (allocator, panic handler, `efi_main`, dispatcher, +//! memory manager wiring). +//! +//! ## How the same code runs on Patina native +//! +//! `platform.rs` is intentionally portable. To run the same component +//! registrations on a Patina-native DXE core, you'd write a sibling crate +//! that contains: +//! +//! ```rust,ignore +//! use my_platform::OemPlatform; +//! +//! patina_tianocore::impl_component_info!(OemPlatform); +//! impl MemoryInfo for OemPlatform { /* ... */ } +//! impl CpuInfo for OemPlatform { /* ... */ } +//! impl PlatformInfo for OemPlatform { /* ... */ } +//! ``` +//! +//! The `Platform` impl in `platform.rs` is unchanged. + +#![no_std] +#![no_main] +#![feature(allocator_api)] + +mod platform; + +// One line generates the global allocator, panic handler, `efi_main` entry +// point, boot-services + memory-manager wiring, and dispatches every +// component registered by `OemPlatform`. +patina_tianocore::driver_entry!(platform: platform::OemPlatform); diff --git a/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/src/platform.rs b/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/src/platform.rs new file mode 100644 index 0000000..b29332a --- /dev/null +++ b/uefi/OdpPkg/Drivers/ODP_PatinaSmbiosDemo/src/platform.rs @@ -0,0 +1,116 @@ +//! OEM platform definition — shared across runtimes. +//! +//! SPDX-License-Identifier: MIT +//! +//! This module is intentionally portable: it has no TianoCore-specific code. +//! Move it into a separate crate when you want to also run on Patina native; +//! both the TianoCore driver binary (this crate, via `driver_entry!`) and +//! the Patina-native binary (via `impl_component_info!`) can depend on the +//! same source. +//! +//! ## What's demonstrated +//! +//! [`BiosInfoSmbiosPublisher`] is the headline example. It depends on +//! `Service` from `patina_smbios`, builds a typed +//! `Type0PlatformFirmwareInformation` record, and hands it to +//! `smbios.add_record(...)`. There is no reference to `EFI_SMBIOS_PROTOCOL`, +//! no raw buffer construction in the publishing component. Serialization, +//! handle allocation, string-pool assembly, and table publication all +//! happen inside `patina_smbios`. + +extern crate alloc; + +use alloc::string::String; +use alloc::vec; + +use patina::component::component; +use patina::component::service::Service; +use patina::error::Result; +use patina_smbios::component::SmbiosProvider; +use patina_smbios::service::{SMBIOS_HANDLE_PI_RESERVED, Smbios, SmbiosExt, SmbiosTableHeader}; +use patina_smbios::smbios_record::Type0PlatformFirmwareInformation; +use patina_tianocore::prelude::*; + +/// Publishes a Type 0 (BIOS Information) SMBIOS record via the native +/// `Service` interface. +/// +/// ## Build-time metadata +/// +/// `firmware_version` and `firmware_release_date` are pulled from the build +/// command line — same convention as `patina-dxe-core-oem`: +/// +/// - `env!("CARGO_PKG_VERSION")` — version string from this crate's +/// `Cargo.toml`. +/// - `option_env!("BUILD_DATE")` — set by your build system +/// (e.g. `BUILD_DATE=04/30/2026 cargo build ...`); falls back to +/// `01/01/1970` when absent. +pub struct BiosInfoSmbiosPublisher { + pub vendor: &'static str, + pub system_bios_major: u8, + pub system_bios_minor: u8, +} + +#[component] +impl BiosInfoSmbiosPublisher { + pub fn entry_point(self, smbios: Service) -> Result<()> { + let firmware_version = env!("CARGO_PKG_VERSION"); + let firmware_release_date = option_env!("BUILD_DATE").unwrap_or("01/01/1970"); + + let record = Type0PlatformFirmwareInformation { + header: SmbiosTableHeader::new(0, 0, SMBIOS_HANDLE_PI_RESERVED), + // String pool is 1-indexed — these reference the vec below. + vendor: 1, + firmware_version: 2, + firmware_release_date: 3, + bios_starting_address_segment: 0xE000, + firmware_rom_size: 0x0F, + characteristics: 0x08, + characteristics_ext1: 0x03, + characteristics_ext2: 0x01, + system_bios_major_release: self.system_bios_major, + system_bios_minor_release: self.system_bios_minor, + embedded_controller_major_release: 0xFF, + embedded_controller_minor_release: 0xFF, + extended_bios_rom_size: 0x0000, + string_pool: vec![ + String::from(self.vendor), + String::from(firmware_version), + String::from(firmware_release_date), + ], + }; + + let handle = smbios.add_record(None, &record).map_err(|e| { + log::error!("BiosInfoSmbiosPublisher: add_record failed: {:?}", e); + patina::error::EfiError::DeviceError + })?; + + log::info!( + "BiosInfoSmbiosPublisher: added Type 0 BIOS info (vendor={}, version={}, date={}) handle=0x{:04X}", + self.vendor, + firmware_version, + firmware_release_date, + handle, + ); + Ok(()) + } +} + +/// The single `Platform` impl that drives both runtimes. +pub struct OemPlatform; + +impl Platform for OemPlatform { + fn components(add: &mut impl ComponentAdder) { + // The SMBIOS service provider from patina_smbios. On TianoCore this + // also installs the EDK II SMBIOS protocol internally for legacy C + // consumers — but that's `patina_smbios`'s implementation detail, + // invisible to the publisher below. + add.component(SmbiosProvider::new(3, 9)); + + // Pure Rust SMBIOS record publisher. Zero C protocol references. + add.component(BiosInfoSmbiosPublisher { + vendor: "Acme Inc.", + system_bios_major: 2, + system_bios_minor: 14, + }); + } +}