[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH 4/7] Rust: add the rust_hello module
From: |
Daniel Axtens |
Subject: |
[RFC PATCH 4/7] Rust: add the rust_hello module |
Date: |
Tue, 24 Aug 2021 23:32:40 +1000 |
Build an actual module with Rust!
This module, built whenever COND_RUST is enabled, does the following:
- Prints a message when the module is loaded.
- Registers a command which prints hello when run.
- Deregisters the command when the module is unloaded.
You can build it with the usual make, no special magic required.
A test is supplied.
A few outstanding to-dos:
- The Rust source doesn't get preprocessed in such a way as to allow the
normal module to insert the little shim command that loads the module
when called. (the command.lst stuff)
- I haven't looked at how to specify sections etc in Rust so I use wrap.c
to specify a license.
- Bindgen uses the 'cty' module to specify c-types. That's MIT licensed, which
is GPLv3 compatible (AIUI) but maybe we want to write our own. The linux
kernel has one of it's own which is GPLv2 only, I'm hoping to ask if they
can dual-license it so we can borrow it.
- The module does somewhat expose that more idiomatic layers around the
bindings
would be very nice.
Signed-off-by: Daniel Axtens <dja@axtens.net>
---
.gitignore | 1 +
Makefile.util.def | 6 +++
grub-core/Makefile.core.def | 9 ++++
grub-core/commands/rust-hello/.gitignore | 1 +
grub-core/commands/rust-hello/Cargo.lock | 24 ++++++++++
grub-core/commands/rust-hello/Cargo.toml | 16 +++++++
grub-core/commands/rust-hello/src/lib.rs | 57 ++++++++++++++++++++++++
grub-core/commands/rust-hello/wrap.c | 8 ++++
tests/test_rust.in | 19 ++++++++
9 files changed, 141 insertions(+)
create mode 100644 grub-core/commands/rust-hello/.gitignore
create mode 100644 grub-core/commands/rust-hello/Cargo.lock
create mode 100644 grub-core/commands/rust-hello/Cargo.toml
create mode 100644 grub-core/commands/rust-hello/src/lib.rs
create mode 100644 grub-core/commands/rust-hello/wrap.c
create mode 100644 tests/test_rust.in
diff --git a/.gitignore b/.gitignore
index f6a1bd051752..68288d6481e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -264,6 +264,7 @@ widthspec.bin
/stamp-h1
/syslinux_test
/tar_test
+/test_rust
/test_sha512sum
/test_unset
/tests/syslinux/ubuntu10.04_grub.cfg
diff --git a/Makefile.util.def b/Makefile.util.def
index f8b356cc1fa4..bca56493f189 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -1211,6 +1211,12 @@ script = {
common = tests/syslinux_test.in;
};
+script = {
+ testcase;
+ name = test_rust;
+ common = tests/test_rust.in;
+};
+
program = {
testcase;
name = example_unit_test;
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 8022e1c0a794..8c3f1be4495e 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2527,3 +2527,12 @@ module = {
common = commands/i386/wrmsr.c;
enable = x86;
};
+
+module = {
+ name = rust_hello;
+ common = commands/rust-hello/wrap.c;
+ rust = commands/rust-hello/src/lib.rs;
+ crate = commands/rust-hello;
+
+ condition = COND_RUST;
+};
diff --git a/grub-core/commands/rust-hello/.gitignore
b/grub-core/commands/rust-hello/.gitignore
new file mode 100644
index 000000000000..eb5a316cbd19
--- /dev/null
+++ b/grub-core/commands/rust-hello/.gitignore
@@ -0,0 +1 @@
+target
diff --git a/grub-core/commands/rust-hello/Cargo.lock
b/grub-core/commands/rust-hello/Cargo.lock
new file mode 100644
index 000000000000..af55da87ad9a
--- /dev/null
+++ b/grub-core/commands/rust-hello/Cargo.lock
@@ -0,0 +1,24 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "cty"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7313c0d620d0cb4dbd9d019e461a4beb501071ff46ec0ab933efb4daa76d73e3"
+
+[[package]]
+name = "grub"
+version = "0.1.0"
+dependencies = [
+ "cty",
+]
+
+[[package]]
+name = "rust-hello"
+version = "0.1.0"
+dependencies = [
+ "cty",
+ "grub",
+]
diff --git a/grub-core/commands/rust-hello/Cargo.toml
b/grub-core/commands/rust-hello/Cargo.toml
new file mode 100644
index 000000000000..81535262c3db
--- /dev/null
+++ b/grub-core/commands/rust-hello/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "rust-hello"
+version = "0.1.0"
+authors = ["Daniel Axtens <dja@axtens.net>"]
+edition = "2018"
+
+[lib]
+crate_type = ["staticlib"]
+
+[profile.release]
+panic="abort"
+lto = true
+
+[dependencies]
+grub = { path = "../../lib/rust/grub" }
+cty = "^0.2"
diff --git a/grub-core/commands/rust-hello/src/lib.rs
b/grub-core/commands/rust-hello/src/lib.rs
new file mode 100644
index 000000000000..db0f43046d5e
--- /dev/null
+++ b/grub-core/commands/rust-hello/src/lib.rs
@@ -0,0 +1,57 @@
+#![no_std]
+
+use core::mem::replace;
+use cty;
+use grub::command::GrubCommand;
+
+/* See https://docs.rust-embedded.org/book/peripherals/singletons.html */
+struct ModuleData {
+ command: Option<GrubCommand>,
+}
+
+impl ModuleData {
+ fn take_command(&mut self) -> GrubCommand {
+ let c = replace(&mut self.command, None);
+ c.unwrap()
+ }
+}
+
+static mut MODULEDATA: ModuleData = ModuleData { command: None };
+
+// This _doesn't_ need no-mangle because it's called via a function
+// pointer. It does, AIUI, need extern "C" to get the ABI right.
+extern "C" fn rust_hello_cmd(
+ _cmd: *mut grub::bindings::grub_command,
+ _argc: cty::c_int,
+ _argv: *mut *mut cty::c_char,
+) -> grub::bindings::grub_err_t {
+ unsafe {
+ grub::bindings::grub_printf("Hello from command written in
Rust\n\0".as_ptr() as *const _)
+ };
+
+ grub::bindings::grub_err_t_GRUB_ERR_NONE
+}
+
+#[no_mangle]
+pub extern "C" fn grub_rust_hello_init() {
+ let hello = GrubCommand::new(
+ "rust_hello\0",
+ rust_hello_cmd,
+ "\0",
+ "say hello from rust\0",
+ );
+
+ unsafe {
+ MODULEDATA.command = Some(hello);
+ };
+
+ unsafe { grub::bindings::grub_printf("Hello from Rust\n\0".as_ptr() as
*const _) };
+}
+
+#[no_mangle]
+pub extern "C" fn grub_rust_hello_fini() {
+ // this causes the command to go out of scope, leading to it being
unregistered
+ unsafe {
+ MODULEDATA.take_command();
+ };
+}
diff --git a/grub-core/commands/rust-hello/wrap.c
b/grub-core/commands/rust-hello/wrap.c
new file mode 100644
index 000000000000..97775d6840ae
--- /dev/null
+++ b/grub-core/commands/rust-hello/wrap.c
@@ -0,0 +1,8 @@
+#define RUST_WRAPPER
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE("GPLv3+");
+/* rust code defines grub_rust_hello_{init,fini}, this is just for the
+ scripts that determine modules */
+GRUB_MOD_INIT(rust_hello);
+GRUB_MOD_FINI(rust_hello);
diff --git a/tests/test_rust.in b/tests/test_rust.in
new file mode 100644
index 000000000000..b2ceb6f56898
--- /dev/null
+++ b/tests/test_rust.in
@@ -0,0 +1,19 @@
+#! @BUILD_SHEBANG@
+
+. "@builddir@/grub-core/modinfo.sh"
+
+out=`echo "insmod rust_hello; rust_hello;" | @builddir@/grub-shell`
+
+if [ ${grub_modinfo_platform} != emu ]; then
+ if ! echo $out | grep "Hello from Rust" > /dev/null; then
+ echo "Did not see hello from rust module"
+ exit 1
+ fi
+fi
+
+if echo $out | grep "Hello from command written in Rust" > /dev/null; then
+ exit 0;
+else
+ echo "Did not see hello from rust command"
+ exit 1;
+fi
--
2.30.2
- [RFC PATCH 0/7] Support writing grub modules in Rust, Daniel Axtens, 2021/08/24
- [RFC PATCH 1/7] emu: support grub_memalign, Daniel Axtens, 2021/08/24
- [RFC PATCH 2/7] Rust: module build infrastructure, Daniel Axtens, 2021/08/24
- [RFC PATCH 3/7] Rust: add a slightly more idiomatic wrapper around command handling, Daniel Axtens, 2021/08/24
- [RFC PATCH 4/7] Rust: add the rust_hello module,
Daniel Axtens <=
- [RFC PATCH 5/7] powerpc: Support Rust, Daniel Axtens, 2021/08/24
- [RFC PATCH 6/7] x86_64-efi: Support Rust, Daniel Axtens, 2021/08/24
- [RFC PATCH 7/7] arm64-efi: Support Rust, Daniel Axtens, 2021/08/24
- Re: [RFC PATCH 0/7] Support writing grub modules in Rust, Heinrich Schuchardt, 2021/08/25