9front - general discussion about 9front
 help / color / mirror / Atom feed
From: Michael Forney <mforney@mforney.org>
To: 9front@9front.org
Subject: [9front] [PATCH] boot/efi: delay GetMemoryMap until right before ExitBootServices
Date: Wed, 16 Nov 2022 19:40:49 +0000	[thread overview]
Message-ID: <058CCCF199316D00FB1ABF63EBD3B3A8@mforney.org> (raw)


The UEFI specification suggests calling GetMemoryMap immediately
before ExitBootServices to ensure that the loader has the current
memory map. The firmware is able to enforce this since we have to
pass a "MapKey" from the last GetMemoryMap to ExitBootServices.

The T14 AMD gen 1 firmware is quite strict about this, and even a call
to OutputString will invalidate the MapKey. This causes
ExitBootServices to fail, and we enter 9front with boot services still
running. This causes all sorts of problems including leaving the
IOMMU enabled, breaking 9front's PCI drivers.

To fix this, move memconf() to unload(), right before
ExitBootServices. To retain the ability to override the memory map,
check if *e820 is already set and if so, ignore the output of
GetMemoryMap except for the MapKey.
---
Still some room for improvement around the *conf helper functions, but
I think this is fine for now.

I also wonder what we should be doing if GetMemoryMap fails. If we
don't have any potentially valid MapKey, how could ExitBootServices
succeed? Perhaps we could make unload return an error string on
failure, and pass it back from bootkern so that we can inform the user
that something is wrong.

diff a854bb07cd792a52c5e75aabca76c22b7dd18fc6 eb07ce3baa9705a30ecf3cd6b31ff851e24cb3d1
--- a/sys/src/boot/efi/efi.c
+++ b/sys/src/boot/efi/efi.c
@@ -36,12 +36,6 @@
 	eficall(ST->BootServices->Stall, (UINTN)us);
 }
 
-void
-unload(void)
-{
-	eficall(ST->BootServices->ExitBootServices, IH, MK);
-}
-
 static void
 memconf(char **cfg)
 {
@@ -72,6 +66,8 @@
 	entvers = 1;
 	if(eficall(ST->BootServices->GetMemoryMap, &mapsize, mapbuf, &MK, &entsize, &entvers))
 		return;
+	if(cfg == nil)
+		return;
 
 	s = *cfg;
 	for(p = mapbuf; mapsize >= entsize; p += entsize, mapsize -= entsize){
@@ -93,7 +89,6 @@
 	*s = '\0';
 	if(s > *cfg){
 		s[-1] = '\n';
-		print(*cfg);
 		*cfg = s;
 	}
 }
@@ -276,9 +271,15 @@
 void
 eficonfig(char **cfg)
 {
-	memconf(cfg);
 	acpiconf(cfg);
 	screenconf(cfg);
+}
+
+void
+unload(char **cfg)
+{
+	memconf(cfg);
+	eficall(ST->BootServices->ExitBootServices, IH, MK);
 }
 
 EFI_STATUS
--- a/sys/src/boot/efi/fns.h
+++ b/sys/src/boot/efi/fns.h
@@ -16,7 +16,7 @@
 void (*close)(void *f);
 
 int readn(void *f, void *data, int len);
-void unload(void);
+void unload(char **cfg);
 
 int getc(void);
 void putc(int c);
--- a/sys/src/boot/efi/sub.c
+++ b/sys/src/boot/efi/sub.c
@@ -156,6 +156,23 @@
 
 char *confend;
 
+static int
+hasconf(char *s)
+{
+	char *p;
+	int n;
+
+	n = strlen(s);
+	for(p = BOOTARGS; n <= confend - p; p++){
+		if(memcmp(p, s, n) == 0)
+			return 1;
+		p = strchr(p, '\n');
+		if(p == nil)
+			break;
+	}
+	return 0;
+}
+
 static char*
 getconf(char *s, char *buf)
 {
@@ -364,7 +381,7 @@
 
 	close(f);
 	print("boot\n");
-	unload();
+	unload(hasconf("*e820=") ? nil : &confend);
 
 	jump(e);
 

             reply	other threads:[~2022-11-16 20:14 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-16 19:40 Michael Forney [this message]
2022-11-19 16:14 ` Lucas Francesco
2022-11-19 16:56   ` Lucas Francesco
2022-12-02 20:17 ` cinap_lenrek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=058CCCF199316D00FB1ABF63EBD3B3A8@mforney.org \
    --to=mforney@mforney.org \
    --cc=9front@9front.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).