All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/7] Support writing grub modules in Rust
@ 2021-08-24 13:32 Daniel Axtens
  2021-08-24 13:32 ` [RFC PATCH 1/7] emu: support grub_memalign Daniel Axtens
                   ` (7 more replies)
  0 siblings, 8 replies; 10+ messages in thread
From: Daniel Axtens @ 2021-08-24 13:32 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Axtens

grub is a trusted component of the secure boot process, including
"traditional" GPG-based secure boot, UEFI-based secure boot, and the
WIP secure boot process using appended signatures. Most of grub is
written in C and has suffered from a number of memory-unsafety issues
in the past, something about which many of us have very distinct and
unpleasant memories!
 
Rust is a systems programming language suitable for low-level
code. Rust can provide strong compile-time guarantees about memory
safety. It also is reasonably easy for Rust code to interoperate with
C.
 
Grub's modular design may work in our favour here. Potentially
vulnerable components such as image and file-system parsers are
written as individual modules. Can we progressively rewrite these
modules in a safer language?

This patch set provides my efforts so far in making this possible.

It allows a module written almost entirely in Rust to be built and
run (in qemu) on x86_64-{emu,efi}, arm64-efi and powerpc-ieee1275.

It still needs work, but it's at the stage where it's not entirely
trivial, and where I want to start getting more feedback on it.

There are a few comments on things that need to be changed further on
in the series, but I think the biggest overarching change we probably
want to move towards doing more of what the Rust for Linux (kernel)
project has done: drop Cargo and build everything (except tests)
directly with rustc. This is a pain because Cargo is magic, but it
will resolve some hairy issues.

(For example, currently on x86_64 platforms you can't have multiple
Rust modules because each defines a __rust_probestack intrinsic
despite my attempts to disable it. IMO that's a rustc bug and I have
reported it. But, there are other intrinsics that Rust code could
validly call, and we don't want implementations linked into each
module, we want the modules to call into the kernel. This is - as far
as I can tell - impossible to do with Cargo builds; we need finer
control.)

Another big issue where we want to follow the Rust for Linux project
is how to handle failing allocations: by default in Rust that kills
your program (!), a situation which is entirely unacceptable for the
linux kernel. It's also unacceptable in Grub, so we should figure out
how they avoid it and learn from them.

I have proposed a Linux Plumbers talk in the systems boot stream to
discuss this further. I'd also welcome on-list discussions.

(Now, back to addressing the review comments on my previous patch
series!)

Daniel Axtens (7):
  emu: support grub_memalign
  Rust: module build infrastructure
  Rust: add a slightly more idiomatic wrapper around command handling
  Rust: add the rust_hello module
  powerpc: Support Rust
  x86_64-efi: Support Rust
  arm64-efi: Support Rust

 .gitignore                                    |  1 +
 Makefile.util.def                             |  6 ++
 conf/Makefile.common                          |  1 +
 configure.ac                                  | 71 +++++++++++++++++++
 gentpl.py                                     | 28 +++++++-
 grub-core/Makefile.am                         | 20 ++++++
 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 +++
 grub-core/kern/emu/mm.c                       |  6 ++
 grub-core/lib/rust/bindings.h                 |  4 ++
 grub-core/lib/rust/conftest/Cargo.lock        |  7 ++
 grub-core/lib/rust/conftest/Cargo.toml        | 10 +++
 grub-core/lib/rust/conftest/src/lib.rs        | 10 +++
 grub-core/lib/rust/grub/.gitignore            |  1 +
 grub-core/lib/rust/grub/Cargo.toml            |  8 +++
 grub-core/lib/rust/grub/src/command.rs        | 50 +++++++++++++
 grub-core/lib/rust/grub/src/lib.rs            | 64 +++++++++++++++++
 grub-core/lib/rust/targets/arm64-efi.json     | 27 +++++++
 .../lib/rust/targets/powerpc-ieee1275.json    | 28 ++++++++
 grub-core/lib/rust/targets/x86_64-efi.json    | 27 +++++++
 grub-core/lib/rust/targets/x86_64-emu.json    | 27 +++++++
 include/grub/dl.h                             | 21 +++++-
 include/grub/mm.h                             |  2 -
 tests/test_rust.in                            | 19 +++++
 28 files changed, 547 insertions(+), 6 deletions(-)
 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 grub-core/lib/rust/bindings.h
 create mode 100644 grub-core/lib/rust/conftest/Cargo.lock
 create mode 100644 grub-core/lib/rust/conftest/Cargo.toml
 create mode 100644 grub-core/lib/rust/conftest/src/lib.rs
 create mode 100644 grub-core/lib/rust/grub/.gitignore
 create mode 100644 grub-core/lib/rust/grub/Cargo.toml
 create mode 100644 grub-core/lib/rust/grub/src/command.rs
 create mode 100644 grub-core/lib/rust/grub/src/lib.rs
 create mode 100644 grub-core/lib/rust/targets/arm64-efi.json
 create mode 100644 grub-core/lib/rust/targets/powerpc-ieee1275.json
 create mode 100644 grub-core/lib/rust/targets/x86_64-efi.json
 create mode 100644 grub-core/lib/rust/targets/x86_64-emu.json
 create mode 100644 tests/test_rust.in

-- 
2.30.2



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH 1/7] emu: support grub_memalign
  2021-08-24 13:32 [RFC PATCH 0/7] Support writing grub modules in Rust Daniel Axtens
@ 2021-08-24 13:32 ` Daniel Axtens
  2021-08-24 13:32 ` [RFC PATCH 2/7] Rust: module build infrastructure Daniel Axtens
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Daniel Axtens @ 2021-08-24 13:32 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Axtens

This is trivial to do and simplifies Rust support enormously.

Signed-off-by: Daniel Axtens <dja@axtens.net>
---
 grub-core/kern/emu/mm.c | 6 ++++++
 include/grub/mm.h       | 2 --
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/grub-core/kern/emu/mm.c b/grub-core/kern/emu/mm.c
index 4d1046a219eb..71dc8d422f3e 100644
--- a/grub-core/kern/emu/mm.c
+++ b/grub-core/kern/emu/mm.c
@@ -73,3 +73,9 @@ grub_realloc (void *ptr, grub_size_t size)
     grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
   return ret;
 }
+
+void *
+grub_memalign (grub_size_t align, grub_size_t size)
+{
+  return aligned_alloc (align, size);
+}
diff --git a/include/grub/mm.h b/include/grub/mm.h
index 9c38dd3ca5d2..4407179a838d 100644
--- a/include/grub/mm.h
+++ b/include/grub/mm.h
@@ -34,9 +34,7 @@ void *EXPORT_FUNC(grub_malloc) (grub_size_t size);
 void *EXPORT_FUNC(grub_zalloc) (grub_size_t size);
 void EXPORT_FUNC(grub_free) (void *ptr);
 void *EXPORT_FUNC(grub_realloc) (void *ptr, grub_size_t size);
-#ifndef GRUB_MACHINE_EMU
 void *EXPORT_FUNC(grub_memalign) (grub_size_t align, grub_size_t size);
-#endif
 
 void grub_mm_check_real (const char *file, int line);
 #define grub_mm_check() grub_mm_check_real (GRUB_FILE, __LINE__);
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 2/7] Rust: module build infrastructure
  2021-08-24 13:32 [RFC PATCH 0/7] Support writing grub modules in Rust Daniel Axtens
  2021-08-24 13:32 ` [RFC PATCH 1/7] emu: support grub_memalign Daniel Axtens
@ 2021-08-24 13:32 ` Daniel Axtens
  2021-08-24 13:32 ` [RFC PATCH 3/7] Rust: add a slightly more idiomatic wrapper around command handling Daniel Axtens
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Daniel Axtens @ 2021-08-24 13:32 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Axtens

Make the grub build infrastructure able to detect a Rust toolchain on a
supported platform and build modules partially written in Rust.

In order to use this you will need:

 - to be building for x86_64-emu (more platforms added later)

 - to have a nightly rust toolchain:

    rustup toolchain install nightly

 - to install the Rust standard library sources:

    rustup component add --toolchain nightly rust-src

 - bindgen

    I'm fairly sure I installed this from my distro.

Key components
==============

configure.ac
------------

configure will check for the presence of rustc, cargo and bindgen.

configure will verify that it can build a minimal freestanding static
library for the target.

Teach configure:

 --disable-rust / --enable-rust: force Rust support off/on

 --enable-rust-debug: build rust modules in debug mode rather than release
                      mode

Introduce COND_RUST to mark when rust is available.

gentpl.py
---------

Teach gentpl.py about some rust keywords for building modules. (These
are demonstrated later on in the series.)

grub-core/lib/rust
------------------

This comprises 3 parts: bindings, a core support 'library', and
a target definition.

1. Bindings

Teach the build system how to make Rust bindings of the C funtions with
bindgen, and how to clean up after Rust builds.

2. Core support

Provide a basic Rust interface for grub (lib.rs). Rust code is built in
the freestanding/embedded mode, so we don't have access to the standard
library ('std'). We do provide rust modules with access to 'core' and
'alloc', giving them core features and dynamic memory. To do this we need
to supply 2 helpers:

 - an allocator: teach Rust to call grub_memalign()/grub_free()
   Currently failed Rust allocations will panic; this is definitely something
   I want to fix, as the Linux kernel rust project has done.

 - panic: call grub_fatal when a rust panic occurs.
   In future I want to print a bit more info, but so far I haven't actually
   caused a panic yet.

3. Target

Provide a description of x86_64-emu as a Rust target.json file. This is based on
the autogenerated target.json file, with some changes to represent the compile
flags used in the rest of grub (no mmx or sse, soft-float, mcmodel=large, no redzone)
and some general assumptions grub makes (specifically that it runs singlethreaded).

This doesn't actually make anything with Rust, but it lays the foundations.

Signed-off-by: Daniel Axtens <dja@axtens.net>
---
 conf/Makefile.common                       |  1 +
 configure.ac                               | 71 ++++++++++++++++++++++
 gentpl.py                                  | 28 ++++++++-
 grub-core/Makefile.am                      | 20 ++++++
 grub-core/lib/rust/bindings.h              |  4 ++
 grub-core/lib/rust/conftest/Cargo.lock     |  7 +++
 grub-core/lib/rust/conftest/Cargo.toml     | 10 +++
 grub-core/lib/rust/conftest/src/lib.rs     | 10 +++
 grub-core/lib/rust/grub/.gitignore         |  1 +
 grub-core/lib/rust/grub/Cargo.toml         |  8 +++
 grub-core/lib/rust/grub/src/lib.rs         | 63 +++++++++++++++++++
 grub-core/lib/rust/targets/x86_64-emu.json | 27 ++++++++
 include/grub/dl.h                          | 21 ++++++-
 13 files changed, 267 insertions(+), 4 deletions(-)
 create mode 100644 grub-core/lib/rust/bindings.h
 create mode 100644 grub-core/lib/rust/conftest/Cargo.lock
 create mode 100644 grub-core/lib/rust/conftest/Cargo.toml
 create mode 100644 grub-core/lib/rust/conftest/src/lib.rs
 create mode 100644 grub-core/lib/rust/grub/.gitignore
 create mode 100644 grub-core/lib/rust/grub/Cargo.toml
 create mode 100644 grub-core/lib/rust/grub/src/lib.rs
 create mode 100644 grub-core/lib/rust/targets/x86_64-emu.json

diff --git a/conf/Makefile.common b/conf/Makefile.common
index 2a1a886f6d52..aa3b24d36f41 100644
--- a/conf/Makefile.common
+++ b/conf/Makefile.common
@@ -125,6 +125,7 @@ TESTS =
 EXTRA_DIST =
 CLEANFILES =
 BUILT_SOURCES =
+RUST_BUILDDIRS =
 
 # Rules for Automake input
 
diff --git a/configure.ac b/configure.ac
index b025e1e84cfb..f75fb3706ad6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -364,6 +364,24 @@ AM_PROG_CC_C_O
 AM_PROG_AS
 AM_PATH_PYTHON([2.6])
 
+rust_target="${target_cpu}-${platform}"
+if ! test -f "$srcdir/grub-core/lib/rust/targets/${rust_target}.json"; then
+  rust_excuse="No rust target JSON file for this platform yet"
+fi
+AC_SUBST(rust_target)
+
+AC_CHECK_PROG(CARGO, [cargo], [yes], [no])
+AC_CHECK_PROG(RUSTC, [rustc], [yes], [no])
+AC_CHECK_PROG(BINDGEN, [bindgen], [yes], [no])
+
+if test x$CARGO = xno ; then
+  rust_excuse="no cargo binary";
+elif test x$RUSTC = xno ; then
+  rust_excuse="no rustc binary";
+elif test x$BINDGEN = xno ; then
+  rust_excuse="no bindgen binary";
+fi
+
 # Must be GCC.
 test "x$GCC" = xyes || AC_MSG_ERROR([GCC is required])
 
@@ -599,6 +617,21 @@ fi
 
 TARGET_CC_VERSION="$(LC_ALL=C $TARGET_CC --version | head -n1)"
 
+if test x"$rust_excuse" = x ; then
+  AC_CACHE_CHECK([whether nightly rustc can compile for $rust_target], [grub_cv_target_rustc], [
+  tmp_builddir=`pwd`
+  cd $srcdir/grub-core/lib/rust/conftest;
+  if CARGO_TARGET_DIR=$tmp_builddir/grub-core/lib/rust/conftest/target cargo +nightly build --release --target ../targets/${rust_target}.json -Zbuild-std=core,alloc 2>/dev/null >/dev/null; then
+    grub_cv_target_rustc=yes;
+  else
+    grub_cv_target_rustc=no;
+    rust_excuse="cannot compile conftest package with rust nightly";
+  fi
+  cd $tmp_builddir
+  rm -rf grub-core/lib/rust/conftest/target
+  ])
+fi
+
 AC_CACHE_CHECK([which extra warnings work], [grub_cv_target_cc_w_extra_flags], [
   LDFLAGS="$TARGET_LDFLAGS -nostdlib -static"
 
@@ -1622,6 +1655,32 @@ enable_grub_mkfont=no
 fi
 AC_SUBST([enable_grub_mkfont])
 
+AC_ARG_ENABLE([rust],
+	      [AS_HELP_STRING([--enable-rust],
+                             [build Rust language grub modules (default=guessed)])])
+
+if test x"$enable_rust" = xyes && test x"$rust_excuse" != x ; then
+  AC_MSG_ERROR([Rust was explicitly requested but can't be compiled ($rust_excuse)])
+fi
+if test x"$enable_rust" = xno ; then
+  rust_excuse="explictly disabled"
+fi
+
+AC_ARG_ENABLE([rust-debug],
+              AC_HELP_STRING([--enable-rust-debug],
+                             [build Rust code with debugging information [default=no]]),
+              [rust_debug_release=$enableval],
+              [rust_debug_release=no])
+
+if test "x$rust_debug_release" = "xyes" ; then
+    RUST_TARGET_SUBDIR=debug
+else
+    RUST_TARGET_SUBDIR=release
+fi
+if test "x$rust_debug_release" = xyes && test "x$rust_excuse" != x ; then
+  AC_MSG_ERROR([Rust debug release specified but cannot enable rust ($rust_excuse)])
+fi
+
 SAVED_CC="$CC"
 SAVED_CPP="$CPP"
 SAVED_CFLAGS="$CFLAGS"
@@ -1951,6 +2010,10 @@ AC_SUBST(TARGET_LDFLAGS)
 AC_SUBST(TARGET_CPPFLAGS)
 AC_SUBST(TARGET_CCASFLAGS)
 
+RUST_TARGET_PATH="\$(abs_top_srcdir)/grub-core/lib/rust/targets/${rust_target}.json"
+AC_SUBST(RUST_TARGET_PATH)
+AC_SUBST(RUST_TARGET_SUBDIR)
+
 AC_SUBST(TARGET_IMG_LDFLAGS)
 AC_SUBST(TARGET_IMG_CFLAGS)
 AC_SUBST(TARGET_IMG_BASE_LDOPT)
@@ -2031,6 +2094,9 @@ AM_CONDITIONAL([COND_HAVE_ASM_USCORE], [test x$HAVE_ASM_USCORE = x1])
 AM_CONDITIONAL([COND_STARFIELD], [test "x$starfield_excuse" = x])
 AM_CONDITIONAL([COND_HAVE_EXEC], [test "x$have_exec" = xy])
 
+AM_CONDITIONAL([COND_RUST], [test x"$rust_excuse" = x])
+AM_CONDITIONAL([RUST_DEBUG_RELEASE], [test x$rust_debug_release = xyes])
+
 test "x$prefix" = xNONE && prefix="$ac_default_prefix"
 test "x$exec_prefix" = xNONE && exec_prefix="${prefix}"
 datarootdir="$(eval echo "$datarootdir")"
@@ -2166,5 +2232,10 @@ echo "With stack smashing protector: Yes"
 else
 echo "With stack smashing protector: No"
 fi
+if [ x"$rust_excuse" = x ]; then
+echo "With rust module support: Yes ($RUST_TARGET_SUBDIR mode)"
+else
+echo "With rust module support: No ($rust_excuse)"
+fi
 echo "*******************************************************"
 ]
diff --git a/gentpl.py b/gentpl.py
index c86550d4f9e5..8820baa73edc 100644
--- a/gentpl.py
+++ b/gentpl.py
@@ -490,6 +490,9 @@ def set_canonical_name_suffix(suffix):
 def cname(defn):
     return canonical_name_re.sub('_', defn['name'] + canonical_name_suffix)
 
+def cratelibname(defn):
+    return canonical_name_re.sub('_', "lib" + defn['name']) + ".a"
+
 def rule(target, source, cmd):
     if cmd[0] == "\n":
         output("\n" + target + ": " + source + cmd.replace("\n", "\n\t") + "\n")
@@ -629,6 +632,9 @@ def platform_values(defn, platform, suffix):
 def extra_dist(defn):
     return foreach_value(defn, "extra_dist", lambda value: value + " ")
 
+def rust_sources(defn):
+    return foreach_value(defn, "rust", lambda value: value + " ")
+
 def platform_sources(defn, p): return platform_values(defn, p, "")
 def platform_nodist_sources(defn, p): return platform_values(defn, p, "_nodist")
 
@@ -682,14 +688,30 @@ def module(defn, platform):
     gvar_add("MODULE_FILES", name + ".module$(EXEEXT)")
 
     var_set(cname(defn) + "_SOURCES", platform_sources(defn, platform) + " ## platform sources")
-    var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform) + " ## platform nodist sources")
-    var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform))
+    var_set(cname(defn) + "_RUSTSOURCES", rust_sources(defn))
     var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_MODULE) " + platform_cflags(defn, platform))
     var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_MODULE) " + platform_ldflags(defn, platform))
     var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_MODULE) " + platform_cppflags(defn, platform))
     var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_MODULE) " + platform_ccasflags(defn, platform))
     var_set(cname(defn) + "_DEPENDENCIES", "$(TARGET_OBJ2ELF) " + platform_dependencies(defn, platform))
 
+    if 'crate' in defn:
+        rustlib = defn['crate'] + "/target/$(rust_target)/$(RUST_TARGET_SUBDIR)/" + cratelibname(defn)
+        output("""
+""" + rustlib + ": $(" + cname(defn) + """_RUSTSOURCES) $(COMMON_RUSTSOURCES)
+	cd $(abs_srcdir)/""" + defn['crate'] + """; \\
+	CARGO_TARGET_DIR=$(abs_builddir)/""" + defn['crate'] + """/target cargo +nightly build $(CARGO_RELEASE_ARGS) --target=$(RUST_TARGET_PATH) -Zbuild-std=core,alloc
+""")
+        gvar_add("RUST_BUILDDIRS", "$(abs_builddir)/" + defn['crate'] + "/target/$(rust_target)/$(RUST_TARGET_SUBDIR)/")
+    else:
+        rustlib = ""
+
+    var_set(cname(defn) + "_RUSTLIBRARY", rustlib)
+    var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform) + " $(" + cname(defn) + "_RUSTLIBRARY)")
+    # the rust library needs to be a built source so that automake builds it
+    # before attempting to build the module. putting it in marker and ldadd is insufficient
+    var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform) + " $(" + cname(defn) + "_RUSTLIBRARY) ## platform nodist sources and built rust libraries")
+        
     gvar_add("dist_noinst_DATA", extra_dist(defn))
     gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)")
     gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)")
@@ -698,7 +720,7 @@ def module(defn, platform):
     gvar_add("MARKER_FILES", name + ".marker")
     gvar_add("CLEANFILES", name + ".marker")
     output("""
-""" + name + """.marker: $(""" + cname(defn) + """_SOURCES) $(nodist_""" + cname(defn) + """_SOURCES)
+""" + name + ".marker: $(" + cname(defn) + "_SOURCES) $(nodist_" + cname(defn) + """_SOURCES)
 	$(TARGET_CPP) -DGRUB_LST_GENERATOR $(CPPFLAGS_MARKER) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(""" + cname(defn) + """_CPPFLAGS) $(CPPFLAGS) $^ > $@.new || (rm -f $@; exit 1)
 	grep 'MARKER' $@.new > $@; rm -f $@.new
 """)
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index ee88e44e97a0..71c1444bcf7d 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -26,6 +26,23 @@ CFLAGS_LIBRARY += $(CFLAGS_PLATFORM) -fno-builtin
 CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM)
 CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM)
 
+if RUST_DEBUG_RELEASE
+CARGO_RELEASE_ARGS=
+else
+CARGO_RELEASE_ARGS=--release
+endif
+
+if COND_RUST
+lib/rust/grub/src/bindings.rs: lib/rust/bindings.h
+	bindgen --use-core lib/rust/bindings.h --ctypes-prefix=cty -o lib/rust/grub/src/bindings.rs -- -I ../include -I.. -DGRUB_FILE='"<rust bindings>"'
+
+CLEANFILES += lib/rust/grub/src/bindings.rs
+
+COMMON_RUSTSOURCES = lib/rust/grub/src/bindings.rs lib/rust/grub/src/lib.rs
+else
+COMMON_RUSTSOURCES =
+endif
+
 build-grub-pep2elf$(BUILD_EXEEXT): $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
 	$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=64 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pep2elf\" $^
 CLEANFILES += build-grub-pep2elf$(BUILD_EXEEXT)
@@ -504,3 +521,6 @@ windowsdir: $(PROGRAMS) $(starfield_DATA) $(platform_DATA)
 	for x in $(platform_DATA); do \
 		cp -fp $$x $(windowsdir)/$(target_cpu)-$(platform)/$$x; \
 	done
+
+clean-local:
+	rm -rf $(RUST_BUILDDIRS)
diff --git a/grub-core/lib/rust/bindings.h b/grub-core/lib/rust/bindings.h
new file mode 100644
index 000000000000..3c28eae0d4fe
--- /dev/null
+++ b/grub-core/lib/rust/bindings.h
@@ -0,0 +1,4 @@
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
diff --git a/grub-core/lib/rust/conftest/Cargo.lock b/grub-core/lib/rust/conftest/Cargo.lock
new file mode 100644
index 000000000000..b666d240a75f
--- /dev/null
+++ b/grub-core/lib/rust/conftest/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "conftest"
+version = "0.1.0"
diff --git a/grub-core/lib/rust/conftest/Cargo.toml b/grub-core/lib/rust/conftest/Cargo.toml
new file mode 100644
index 000000000000..065e0ed0d744
--- /dev/null
+++ b/grub-core/lib/rust/conftest/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "conftest"
+version = "0.1.0"
+edition = "2018"
+
+[lib]
+crate_type = ["staticlib"]
+
+
+[dependencies]
diff --git a/grub-core/lib/rust/conftest/src/lib.rs b/grub-core/lib/rust/conftest/src/lib.rs
new file mode 100644
index 000000000000..40749f704583
--- /dev/null
+++ b/grub-core/lib/rust/conftest/src/lib.rs
@@ -0,0 +1,10 @@
+#![no_std]
+
+use core::panic::PanicInfo;
+
+pub fn foo() {}
+
+#[panic_handler]
+fn panic(_panic: &PanicInfo<'_>) -> ! {
+    loop {}
+}
diff --git a/grub-core/lib/rust/grub/.gitignore b/grub-core/lib/rust/grub/.gitignore
new file mode 100644
index 000000000000..4c8e25833099
--- /dev/null
+++ b/grub-core/lib/rust/grub/.gitignore
@@ -0,0 +1 @@
+src/bindings.rs
diff --git a/grub-core/lib/rust/grub/Cargo.toml b/grub-core/lib/rust/grub/Cargo.toml
new file mode 100644
index 000000000000..0e590e8a636e
--- /dev/null
+++ b/grub-core/lib/rust/grub/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "grub"
+version = "0.1.0"
+authors = ["Daniel Axtens <dja@axtens.net>"]
+edition = "2018"
+
+[dependencies]
+cty = "^0.2"
diff --git a/grub-core/lib/rust/grub/src/lib.rs b/grub-core/lib/rust/grub/src/lib.rs
new file mode 100644
index 000000000000..c34f332c88af
--- /dev/null
+++ b/grub-core/lib/rust/grub/src/lib.rs
@@ -0,0 +1,63 @@
+#![no_std]
+#![allow(non_camel_case_types)]
+#![allow(non_upper_case_globals)]
+#![allow(non_snake_case)]
+#![allow(unused)]
+#![feature(alloc_error_handler)]
+
+pub mod bindings;
+use bindings::grub_size_t;
+use core::alloc::GlobalAlloc;
+use core::alloc::Layout;
+use core::convert::TryInto;
+use core::panic::PanicInfo;
+use core::ptr;
+
+struct GrubAlloc;
+
+unsafe impl GlobalAlloc for GrubAlloc {
+    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+        let size: grub_size_t = match layout.size().try_into() {
+            Ok(x) => x,
+            Err(_) => {
+                return ptr::null_mut();
+            }
+        };
+
+        let align: grub_size_t = match layout.align().try_into() {
+            Ok(x) => x,
+            Err(_) => {
+                return ptr::null_mut();
+            }
+        };
+
+        bindings::grub_memalign(align, size) as *mut u8
+    }
+
+    unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
+        bindings::grub_free(ptr as _);
+    }
+}
+
+#[global_allocator]
+static grub_alloc: GrubAlloc = GrubAlloc;
+
+/* FIXME: This is annoying, ideally this wouldn't happen or would get
+caught elsewhere. I think we need the failable alloc work */
+#[alloc_error_handler]
+fn on_oom(_layout: Layout) -> ! {
+    // todo, more info
+    unsafe { bindings::grub_fatal("OOM in Rust code\0".as_ptr() as *const _) };
+
+    // grub_fatal should not return but keep compiler happy
+    loop {}
+}
+
+#[panic_handler]
+fn panicker(reason: &PanicInfo) -> ! {
+    // todo, more info
+    unsafe { bindings::grub_fatal("Panic in Rust\0".as_ptr() as *const _) };
+
+    // grub_fatal should not return but keep compiler happy
+    loop {}
+}
diff --git a/grub-core/lib/rust/targets/x86_64-emu.json b/grub-core/lib/rust/targets/x86_64-emu.json
new file mode 100644
index 000000000000..00f1a2b6badf
--- /dev/null
+++ b/grub-core/lib/rust/targets/x86_64-emu.json
@@ -0,0 +1,27 @@
+{
+  "arch": "x86_64",
+  "cpu": "x86-64",
+  "env": "gnu",
+  "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128",
+  "dynamic-linking": true,
+  "llvm-target": "x86_64-unknown-linux-gnu",
+  "max-atomic-width": 64,
+  "os": "none",
+  "position-independent-executables": true,
+  "pre-link-args": {
+    "gcc": [
+      "-m64"
+    ]
+  },
+  "target-pointer-width": "64",
+  "features": "-mmx,-sse,+soft-float",
+  "relocation-model": "static",
+  "code-model": "large",
+  "disable-redzone": true,
+  "panic-strategy": "abort",
+  "singlethread": true,
+  "no-builtins": true,
+  "stack-probes": {
+    "kind": "none"
+  }
+}
diff --git a/include/grub/dl.h b/include/grub/dl.h
index b3753c9ca262..55e6a48c46e7 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -38,7 +38,26 @@
 
 #ifndef GRUB_MOD_INIT
 
-#if !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_KERNEL)
+#if defined(RUST_WRAPPER)
+
+/* Rust modules always use grub_##name##_{init,fini} */
+
+#define GRUB_MOD_INIT(name)	\
+void grub_##name##_init(void); \
+static void __attribute__((used))  \
+grub_mod_init (grub_dl_t mod __attribute__ ((unused))) \
+{ \
+  grub_##name##_init(); \
+}
+
+#define GRUB_MOD_FINI(name)	\
+void grub_##name##_fini(void); \
+static void __attribute__((used)) \
+grub_mod_fini (void) \
+{ \
+  grub_##name##_fini(); \
+}
+#elif !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_KERNEL)
 
 #define GRUB_MOD_INIT(name)	\
 static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 3/7] Rust: add a slightly more idiomatic wrapper around command handling
  2021-08-24 13:32 [RFC PATCH 0/7] Support writing grub modules in Rust Daniel Axtens
  2021-08-24 13:32 ` [RFC PATCH 1/7] emu: support grub_memalign Daniel Axtens
  2021-08-24 13:32 ` [RFC PATCH 2/7] Rust: module build infrastructure Daniel Axtens
@ 2021-08-24 13:32 ` Daniel Axtens
  2021-08-24 13:32 ` [RFC PATCH 4/7] Rust: add the rust_hello module Daniel Axtens
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Daniel Axtens @ 2021-08-24 13:32 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Axtens

Add a way to do registering and deregistering of commands that is just
a tiny bit more "Rust-y".

Signed-off-by: Daniel Axtens <dja@axtens.net>
---
 grub-core/Makefile.am                  |  2 +-
 grub-core/lib/rust/grub/src/command.rs | 50 ++++++++++++++++++++++++++
 grub-core/lib/rust/grub/src/lib.rs     |  1 +
 3 files changed, 52 insertions(+), 1 deletion(-)
 create mode 100644 grub-core/lib/rust/grub/src/command.rs

diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 71c1444bcf7d..b565803efb05 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -38,7 +38,7 @@ lib/rust/grub/src/bindings.rs: lib/rust/bindings.h
 
 CLEANFILES += lib/rust/grub/src/bindings.rs
 
-COMMON_RUSTSOURCES = lib/rust/grub/src/bindings.rs lib/rust/grub/src/lib.rs
+COMMON_RUSTSOURCES = lib/rust/grub/src/bindings.rs lib/rust/grub/src/lib.rs lib/rust/grub/src/command.rs
 else
 COMMON_RUSTSOURCES =
 endif
diff --git a/grub-core/lib/rust/grub/src/command.rs b/grub-core/lib/rust/grub/src/command.rs
new file mode 100644
index 000000000000..e96b0ad78608
--- /dev/null
+++ b/grub-core/lib/rust/grub/src/command.rs
@@ -0,0 +1,50 @@
+extern crate alloc;
+use crate::bindings;
+use alloc::string::String;
+use cty;
+
+pub type GrubCommandFunc = unsafe extern "C" fn(
+    cmd: *mut bindings::grub_command,
+    argc: cty::c_int,
+    argv: *mut *mut cty::c_char,
+) -> bindings::grub_err_t;
+
+pub struct GrubCommand {
+    grub_command: bindings::grub_command_t,
+}
+
+impl GrubCommand {
+    pub fn new(
+        name: &'static str,
+        func: GrubCommandFunc,
+        summary: &'static str,
+        description: &'static str,
+    ) -> GrubCommand {
+        let grub_command = register_command_prio(name, func, summary, description, 0);
+        GrubCommand { grub_command }
+    }
+}
+
+impl Drop for GrubCommand {
+    fn drop(&mut self) {
+        unsafe { bindings::grub_unregister_command(self.grub_command) };
+    }
+}
+
+fn register_command_prio(
+    name: &'static str,
+    func: GrubCommandFunc,
+    summary: &'static str,
+    description: &'static str,
+    prio: cty::c_int,
+) -> bindings::grub_command_t {
+    unsafe {
+        bindings::grub_register_command_prio(
+            name.as_ptr() as *const _,
+            Some(func),
+            summary.as_ptr() as *const _,
+            description.as_ptr() as *const _,
+            prio,
+        )
+    }
+}
diff --git a/grub-core/lib/rust/grub/src/lib.rs b/grub-core/lib/rust/grub/src/lib.rs
index c34f332c88af..02411292ba12 100644
--- a/grub-core/lib/rust/grub/src/lib.rs
+++ b/grub-core/lib/rust/grub/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(alloc_error_handler)]
 
 pub mod bindings;
+pub mod command;
 use bindings::grub_size_t;
 use core::alloc::GlobalAlloc;
 use core::alloc::Layout;
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 4/7] Rust: add the rust_hello module
  2021-08-24 13:32 [RFC PATCH 0/7] Support writing grub modules in Rust Daniel Axtens
                   ` (2 preceding siblings ...)
  2021-08-24 13:32 ` [RFC PATCH 3/7] Rust: add a slightly more idiomatic wrapper around command handling Daniel Axtens
@ 2021-08-24 13:32 ` Daniel Axtens
  2021-08-24 13:32 ` [RFC PATCH 5/7] powerpc: Support Rust Daniel Axtens
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Daniel Axtens @ 2021-08-24 13:32 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Axtens

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



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 5/7] powerpc: Support Rust
  2021-08-24 13:32 [RFC PATCH 0/7] Support writing grub modules in Rust Daniel Axtens
                   ` (3 preceding siblings ...)
  2021-08-24 13:32 ` [RFC PATCH 4/7] Rust: add the rust_hello module Daniel Axtens
@ 2021-08-24 13:32 ` Daniel Axtens
  2021-08-24 13:32 ` [RFC PATCH 6/7] x86_64-efi: " Daniel Axtens
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Daniel Axtens @ 2021-08-24 13:32 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Axtens

This is all required to get Rust working with powerpc.

Again based mostly on the rustc target.json emitter with a few tweaks
for grub.

To get the rust toolchain:

rustup target add powerpc-unknown-linux-gnu --toolchain nightly

Signed-off-by: Daniel Axtens <dja@axtens.net>
---
 .../lib/rust/targets/powerpc-ieee1275.json    | 28 +++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 grub-core/lib/rust/targets/powerpc-ieee1275.json

diff --git a/grub-core/lib/rust/targets/powerpc-ieee1275.json b/grub-core/lib/rust/targets/powerpc-ieee1275.json
new file mode 100644
index 000000000000..9ed363373527
--- /dev/null
+++ b/grub-core/lib/rust/targets/powerpc-ieee1275.json
@@ -0,0 +1,28 @@
+{
+  "arch": "powerpc",
+  "data-layout": "E-m:e-p:32:32-i64:64-n32",
+  "dynamic-linking": true,
+  "env": "gnu",
+  "llvm-target": "powerpc-unknown-linux-gnu",
+  "max-atomic-width": 32,
+  "os": "none",
+  "position-independent-executables": true,
+  "pre-link-args": {
+    "gcc": [
+      "-m32"
+    ]
+  },
+  "target-endian": "big",
+  "target-family": [
+    "unix"
+  ],
+  "target-mcount": "_mcount",
+  "target-pointer-width": "32",
+  "features": "-altivec,-vsx,-hard-float",
+  "relocation-model": "static",
+  "code-model": "large",
+  "disable-redzone": true,
+  "panic-strategy": "abort",
+  "singlethread": true,
+  "no-builtins": true
+}
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 6/7] x86_64-efi: Support Rust
  2021-08-24 13:32 [RFC PATCH 0/7] Support writing grub modules in Rust Daniel Axtens
                   ` (4 preceding siblings ...)
  2021-08-24 13:32 ` [RFC PATCH 5/7] powerpc: Support Rust Daniel Axtens
@ 2021-08-24 13:32 ` Daniel Axtens
  2021-08-24 13:32 ` [RFC PATCH 7/7] arm64-efi: " Daniel Axtens
  2021-08-25  5:34 ` [RFC PATCH 0/7] Support writing grub modules in Rust Heinrich Schuchardt
  7 siblings, 0 replies; 10+ messages in thread
From: Daniel Axtens @ 2021-08-24 13:32 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Axtens

Only tested in qemu, not on real hardware.

Signed-off-by: Daniel Axtens <dja@axtens.net>
---
 grub-core/lib/rust/targets/x86_64-efi.json | 27 ++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 grub-core/lib/rust/targets/x86_64-efi.json

diff --git a/grub-core/lib/rust/targets/x86_64-efi.json b/grub-core/lib/rust/targets/x86_64-efi.json
new file mode 100644
index 000000000000..00f1a2b6badf
--- /dev/null
+++ b/grub-core/lib/rust/targets/x86_64-efi.json
@@ -0,0 +1,27 @@
+{
+  "arch": "x86_64",
+  "cpu": "x86-64",
+  "env": "gnu",
+  "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128",
+  "dynamic-linking": true,
+  "llvm-target": "x86_64-unknown-linux-gnu",
+  "max-atomic-width": 64,
+  "os": "none",
+  "position-independent-executables": true,
+  "pre-link-args": {
+    "gcc": [
+      "-m64"
+    ]
+  },
+  "target-pointer-width": "64",
+  "features": "-mmx,-sse,+soft-float",
+  "relocation-model": "static",
+  "code-model": "large",
+  "disable-redzone": true,
+  "panic-strategy": "abort",
+  "singlethread": true,
+  "no-builtins": true,
+  "stack-probes": {
+    "kind": "none"
+  }
+}
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 7/7] arm64-efi: Support Rust
  2021-08-24 13:32 [RFC PATCH 0/7] Support writing grub modules in Rust Daniel Axtens
                   ` (5 preceding siblings ...)
  2021-08-24 13:32 ` [RFC PATCH 6/7] x86_64-efi: " Daniel Axtens
@ 2021-08-24 13:32 ` Daniel Axtens
  2021-08-25  5:34 ` [RFC PATCH 0/7] Support writing grub modules in Rust Heinrich Schuchardt
  7 siblings, 0 replies; 10+ messages in thread
From: Daniel Axtens @ 2021-08-24 13:32 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Axtens

Only tested on qemu, not real hardware.

To get the rust toolchain:

rustup target add aarch64-unknown-linux-gnu --toolchain nightly

Signed-off-by: Daniel Axtens <dja@axtens.net>
---
 grub-core/lib/rust/targets/arm64-efi.json | 27 +++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 grub-core/lib/rust/targets/arm64-efi.json

diff --git a/grub-core/lib/rust/targets/arm64-efi.json b/grub-core/lib/rust/targets/arm64-efi.json
new file mode 100644
index 000000000000..8508ae3e3a31
--- /dev/null
+++ b/grub-core/lib/rust/targets/arm64-efi.json
@@ -0,0 +1,27 @@
+{
+  "arch": "aarch64",
+  "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
+  "dynamic-linking": true,
+  "env": "gnu",
+  "llvm-target": "aarch64-unknown-linux-gnu",
+  "max-atomic-width": 128,
+  "os": "none",
+  "position-independent-executables": true,
+  "supported-sanitizers": [
+    "address",
+    "leak",
+    "memory",
+    "thread",
+    "hwaddress"
+  ],
+  "target-mcount": "\u0001_mcount",
+  "target-pointer-width": "64",
+  "features": "-fp,-neon",
+  "disable-redzone": true,
+  "panic-strategy": "abort",
+  "singlethread": true,
+  "no-builtins": true,
+  "stack-probes": {
+    "kind": "none"
+  }
+}
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH 0/7] Support writing grub modules in Rust
  2021-08-24 13:32 [RFC PATCH 0/7] Support writing grub modules in Rust Daniel Axtens
                   ` (6 preceding siblings ...)
  2021-08-24 13:32 ` [RFC PATCH 7/7] arm64-efi: " Daniel Axtens
@ 2021-08-25  5:34 ` Heinrich Schuchardt
  2021-08-25 15:25   ` Daniel Axtens
  7 siblings, 1 reply; 10+ messages in thread
From: Heinrich Schuchardt @ 2021-08-25  5:34 UTC (permalink / raw)
  To: The development of GNU GRUB, Daniel Axtens

On 8/24/21 3:32 PM, Daniel Axtens wrote:
> grub is a trusted component of the secure boot process, including
> "traditional" GPG-based secure boot, UEFI-based secure boot, and the
> WIP secure boot process using appended signatures. Most of grub is
> written in C and has suffered from a number of memory-unsafety issues
> in the past, something about which many of us have very distinct and
> unpleasant memories!
>
> Rust is a systems programming language suitable for low-level
> code. Rust can provide strong compile-time guarantees about memory
> safety. It also is reasonably easy for Rust code to interoperate with
> C.
>
> Grub's modular design may work in our favour here. Potentially
> vulnerable components such as image and file-system parsers are
> written as individual modules. Can we progressively rewrite these
> modules in a safer language?
>
> This patch set provides my efforts so far in making this possible.
>
> It allows a module written almost entirely in Rust to be built and
> run (in qemu) on x86_64-{emu,efi}, arm64-efi and powerpc-ieee1275.
>
> It still needs work, but it's at the stage where it's not entirely
> trivial, and where I want to start getting more feedback on it.
>
> There are a few comments on things that need to be changed further on
> in the series, but I think the biggest overarching change we probably
> want to move towards doing more of what the Rust for Linux (kernel)
> project has done: drop Cargo and build everything (except tests)
> directly with rustc. This is a pain because Cargo is magic, but it
> will resolve some hairy issues.
>
> (For example, currently on x86_64 platforms you can't have multiple
> Rust modules because each defines a __rust_probestack intrinsic
> despite my attempts to disable it. IMO that's a rustc bug and I have
> reported it. But, there are other intrinsics that Rust code could
> validly call, and we don't want implementations linked into each
> module, we want the modules to call into the kernel. This is - as far
> as I can tell - impossible to do with Cargo builds; we need finer
> control.)
>
> Another big issue where we want to follow the Rust for Linux project
> is how to handle failing allocations: by default in Rust that kills
> your program (!), a situation which is entirely unacceptable for the
> linux kernel. It's also unacceptable in Grub, so we should figure out
> how they avoid it and learn from them.
>
> I have proposed a Linux Plumbers talk in the systems boot stream to
> discuss this further. I'd also welcome on-list discussions.
>
> (Now, back to addressing the review comments on my previous patch
> series!)

Hello Daniel,

riscv64 is one of the architectures supported by GRUB. Why is it missing
in your series?

Best regards

Heinrich

>
> Daniel Axtens (7):
>    emu: support grub_memalign
>    Rust: module build infrastructure
>    Rust: add a slightly more idiomatic wrapper around command handling
>    Rust: add the rust_hello module
>    powerpc: Support Rust
>    x86_64-efi: Support Rust
>    arm64-efi: Support Rust
>
>   .gitignore                                    |  1 +
>   Makefile.util.def                             |  6 ++
>   conf/Makefile.common                          |  1 +
>   configure.ac                                  | 71 +++++++++++++++++++
>   gentpl.py                                     | 28 +++++++-
>   grub-core/Makefile.am                         | 20 ++++++
>   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 +++
>   grub-core/kern/emu/mm.c                       |  6 ++
>   grub-core/lib/rust/bindings.h                 |  4 ++
>   grub-core/lib/rust/conftest/Cargo.lock        |  7 ++
>   grub-core/lib/rust/conftest/Cargo.toml        | 10 +++
>   grub-core/lib/rust/conftest/src/lib.rs        | 10 +++
>   grub-core/lib/rust/grub/.gitignore            |  1 +
>   grub-core/lib/rust/grub/Cargo.toml            |  8 +++
>   grub-core/lib/rust/grub/src/command.rs        | 50 +++++++++++++
>   grub-core/lib/rust/grub/src/lib.rs            | 64 +++++++++++++++++
>   grub-core/lib/rust/targets/arm64-efi.json     | 27 +++++++
>   .../lib/rust/targets/powerpc-ieee1275.json    | 28 ++++++++
>   grub-core/lib/rust/targets/x86_64-efi.json    | 27 +++++++
>   grub-core/lib/rust/targets/x86_64-emu.json    | 27 +++++++
>   include/grub/dl.h                             | 21 +++++-
>   include/grub/mm.h                             |  2 -
>   tests/test_rust.in                            | 19 +++++
>   28 files changed, 547 insertions(+), 6 deletions(-)
>   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 grub-core/lib/rust/bindings.h
>   create mode 100644 grub-core/lib/rust/conftest/Cargo.lock
>   create mode 100644 grub-core/lib/rust/conftest/Cargo.toml
>   create mode 100644 grub-core/lib/rust/conftest/src/lib.rs
>   create mode 100644 grub-core/lib/rust/grub/.gitignore
>   create mode 100644 grub-core/lib/rust/grub/Cargo.toml
>   create mode 100644 grub-core/lib/rust/grub/src/command.rs
>   create mode 100644 grub-core/lib/rust/grub/src/lib.rs
>   create mode 100644 grub-core/lib/rust/targets/arm64-efi.json
>   create mode 100644 grub-core/lib/rust/targets/powerpc-ieee1275.json
>   create mode 100644 grub-core/lib/rust/targets/x86_64-efi.json
>   create mode 100644 grub-core/lib/rust/targets/x86_64-emu.json
>   create mode 100644 tests/test_rust.in
>



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH 0/7] Support writing grub modules in Rust
  2021-08-25  5:34 ` [RFC PATCH 0/7] Support writing grub modules in Rust Heinrich Schuchardt
@ 2021-08-25 15:25   ` Daniel Axtens
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Axtens @ 2021-08-25 15:25 UTC (permalink / raw)
  To: Heinrich Schuchardt, The development of GNU GRUB

Heinrich Schuchardt <xypron.glpk@gmx.de> writes:

> On 8/24/21 3:32 PM, Daniel Axtens wrote:
>> grub is a trusted component of the secure boot process, including
>> "traditional" GPG-based secure boot, UEFI-based secure boot, and the
>> WIP secure boot process using appended signatures. Most of grub is
>> written in C and has suffered from a number of memory-unsafety issues
>> in the past, something about which many of us have very distinct and
>> unpleasant memories!
>>
>> Rust is a systems programming language suitable for low-level
>> code. Rust can provide strong compile-time guarantees about memory
>> safety. It also is reasonably easy for Rust code to interoperate with
>> C.
>>
>> Grub's modular design may work in our favour here. Potentially
>> vulnerable components such as image and file-system parsers are
>> written as individual modules. Can we progressively rewrite these
>> modules in a safer language?
>>
>> This patch set provides my efforts so far in making this possible.
>>
>> It allows a module written almost entirely in Rust to be built and
>> run (in qemu) on x86_64-{emu,efi}, arm64-efi and powerpc-ieee1275.
>>
>> It still needs work, but it's at the stage where it's not entirely
>> trivial, and where I want to start getting more feedback on it.
>>
>> There are a few comments on things that need to be changed further on
>> in the series, but I think the biggest overarching change we probably
>> want to move towards doing more of what the Rust for Linux (kernel)
>> project has done: drop Cargo and build everything (except tests)
>> directly with rustc. This is a pain because Cargo is magic, but it
>> will resolve some hairy issues.
>>
>> (For example, currently on x86_64 platforms you can't have multiple
>> Rust modules because each defines a __rust_probestack intrinsic
>> despite my attempts to disable it. IMO that's a rustc bug and I have
>> reported it. But, there are other intrinsics that Rust code could
>> validly call, and we don't want implementations linked into each
>> module, we want the modules to call into the kernel. This is - as far
>> as I can tell - impossible to do with Cargo builds; we need finer
>> control.)
>>
>> Another big issue where we want to follow the Rust for Linux project
>> is how to handle failing allocations: by default in Rust that kills
>> your program (!), a situation which is entirely unacceptable for the
>> linux kernel. It's also unacceptable in Grub, so we should figure out
>> how they avoid it and learn from them.
>>
>> I have proposed a Linux Plumbers talk in the systems boot stream to
>> discuss this further. I'd also welcome on-list discussions.
>>
>> (Now, back to addressing the review comments on my previous patch
>> series!)
>
> Hello Daniel,
>
> riscv64 is one of the architectures supported by GRUB. Why is it missing
> in your series?

I simply didn't try it. I figured the 4 platforms I tried were
sufficient to demonstrate things and that people who were interested in
other platforms could create their own target.json files and post them.

It's probably easy enough to add support as LLVM and Rust support riscv64.

You could try creating a riscv64-efi.json yourself based on:

rustc +nightly -Z unstable-options --target=riscv64-unknown-linux-gnu \
--print target-spec-json > grub-core/lib/rust/targets/riscv64-efi.json

and then modify the resultant json file to disable hard float etc, set
singlethread mode, set necessary code model flags, etc. (You can compare
the target.json files for other targets to see what I mean.)

Kind regards,
Daniel

>
> Best regards
>
> Heinrich
>
>>
>> Daniel Axtens (7):
>>    emu: support grub_memalign
>>    Rust: module build infrastructure
>>    Rust: add a slightly more idiomatic wrapper around command handling
>>    Rust: add the rust_hello module
>>    powerpc: Support Rust
>>    x86_64-efi: Support Rust
>>    arm64-efi: Support Rust
>>
>>   .gitignore                                    |  1 +
>>   Makefile.util.def                             |  6 ++
>>   conf/Makefile.common                          |  1 +
>>   configure.ac                                  | 71 +++++++++++++++++++
>>   gentpl.py                                     | 28 +++++++-
>>   grub-core/Makefile.am                         | 20 ++++++
>>   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 +++
>>   grub-core/kern/emu/mm.c                       |  6 ++
>>   grub-core/lib/rust/bindings.h                 |  4 ++
>>   grub-core/lib/rust/conftest/Cargo.lock        |  7 ++
>>   grub-core/lib/rust/conftest/Cargo.toml        | 10 +++
>>   grub-core/lib/rust/conftest/src/lib.rs        | 10 +++
>>   grub-core/lib/rust/grub/.gitignore            |  1 +
>>   grub-core/lib/rust/grub/Cargo.toml            |  8 +++
>>   grub-core/lib/rust/grub/src/command.rs        | 50 +++++++++++++
>>   grub-core/lib/rust/grub/src/lib.rs            | 64 +++++++++++++++++
>>   grub-core/lib/rust/targets/arm64-efi.json     | 27 +++++++
>>   .../lib/rust/targets/powerpc-ieee1275.json    | 28 ++++++++
>>   grub-core/lib/rust/targets/x86_64-efi.json    | 27 +++++++
>>   grub-core/lib/rust/targets/x86_64-emu.json    | 27 +++++++
>>   include/grub/dl.h                             | 21 +++++-
>>   include/grub/mm.h                             |  2 -
>>   tests/test_rust.in                            | 19 +++++
>>   28 files changed, 547 insertions(+), 6 deletions(-)
>>   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 grub-core/lib/rust/bindings.h
>>   create mode 100644 grub-core/lib/rust/conftest/Cargo.lock
>>   create mode 100644 grub-core/lib/rust/conftest/Cargo.toml
>>   create mode 100644 grub-core/lib/rust/conftest/src/lib.rs
>>   create mode 100644 grub-core/lib/rust/grub/.gitignore
>>   create mode 100644 grub-core/lib/rust/grub/Cargo.toml
>>   create mode 100644 grub-core/lib/rust/grub/src/command.rs
>>   create mode 100644 grub-core/lib/rust/grub/src/lib.rs
>>   create mode 100644 grub-core/lib/rust/targets/arm64-efi.json
>>   create mode 100644 grub-core/lib/rust/targets/powerpc-ieee1275.json
>>   create mode 100644 grub-core/lib/rust/targets/x86_64-efi.json
>>   create mode 100644 grub-core/lib/rust/targets/x86_64-emu.json
>>   create mode 100644 tests/test_rust.in
>>


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-08-25 15:25 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-24 13:32 [RFC PATCH 0/7] Support writing grub modules in Rust Daniel Axtens
2021-08-24 13:32 ` [RFC PATCH 1/7] emu: support grub_memalign Daniel Axtens
2021-08-24 13:32 ` [RFC PATCH 2/7] Rust: module build infrastructure Daniel Axtens
2021-08-24 13:32 ` [RFC PATCH 3/7] Rust: add a slightly more idiomatic wrapper around command handling Daniel Axtens
2021-08-24 13:32 ` [RFC PATCH 4/7] Rust: add the rust_hello module Daniel Axtens
2021-08-24 13:32 ` [RFC PATCH 5/7] powerpc: Support Rust Daniel Axtens
2021-08-24 13:32 ` [RFC PATCH 6/7] x86_64-efi: " Daniel Axtens
2021-08-24 13:32 ` [RFC PATCH 7/7] arm64-efi: " Daniel Axtens
2021-08-25  5:34 ` [RFC PATCH 0/7] Support writing grub modules in Rust Heinrich Schuchardt
2021-08-25 15:25   ` Daniel Axtens

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.