summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2022-12-02 20:08:36 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2022-12-02 20:08:36 +0000
commitd67e83ed27fbb11ad21880352e706e095ecc0dfb (patch)
treeaa6543a2bae5a72e86793a77b8c39409e936c7b7
parent12ccc63ec3d72d1ef5b591c7f50534ac3b1e890b (diff)
9boot: delay GetMemoryMap until right before ExitBootServices (thanks michael forney!)
Michael Forney reported the following: 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. --- Michael sent a patch that moves memconf() to unload(), but i prefer to make this explicit by calling memconf() before and keep unload() as just that, not touching the configuration.
-rw-r--r--sys/src/boot/efi/efi.c10
-rw-r--r--sys/src/boot/efi/fns.h1
-rw-r--r--sys/src/boot/efi/sub.c63
3 files changed, 42 insertions, 32 deletions
diff --git a/sys/src/boot/efi/efi.c b/sys/src/boot/efi/efi.c
index ee13ba9b8..0c872d443 100644
--- a/sys/src/boot/efi/efi.c
+++ b/sys/src/boot/efi/efi.c
@@ -42,7 +42,7 @@ unload(void)
eficall(ST->BootServices->ExitBootServices, IH, MK);
}
-static void
+void
memconf(char **cfg)
{
static uchar memtype[EfiMaxMemoryType] = {
@@ -73,6 +73,10 @@ memconf(char **cfg)
if(eficall(ST->BootServices->GetMemoryMap, &mapsize, mapbuf, &MK, &entsize, &entvers))
return;
+ /* only called to get MK for ExitBootServices() */
+ if(cfg == nil)
+ return;
+
s = *cfg;
for(p = mapbuf; mapsize >= entsize; p += entsize, mapsize -= entsize){
t = (EFI_MEMORY_DESCRIPTOR*)p;
@@ -93,7 +97,7 @@ memconf(char **cfg)
*s = '\0';
if(s > *cfg){
s[-1] = '\n';
- print(*cfg);
+ /* print(*cfg); -- no printing allowed, can change MK */
*cfg = s;
}
}
@@ -276,7 +280,7 @@ Found:
void
eficonfig(char **cfg)
{
- memconf(cfg);
+ /* memconf(cfg); -- must be called right before unload() */
acpiconf(cfg);
screenconf(cfg);
}
diff --git a/sys/src/boot/efi/fns.h b/sys/src/boot/efi/fns.h
index e029ebdb6..db1234110 100644
--- a/sys/src/boot/efi/fns.h
+++ b/sys/src/boot/efi/fns.h
@@ -37,3 +37,4 @@ char *decfmt(char *s, int i, ulong a);
uintptr eficall(void *proc, ...);
void eficonfig(char **cfg);
+void memconf(char**);
diff --git a/sys/src/boot/efi/sub.c b/sys/src/boot/efi/sub.c
index 8e73c361f..81adcfa56 100644
--- a/sys/src/boot/efi/sub.c
+++ b/sys/src/boot/efi/sub.c
@@ -154,50 +154,53 @@ timeout(int ms)
#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
#define BOOTARGSLEN (4096-0x200-BOOTLINELEN)
-char *confend;
+static char *confend;
static char*
-getconf(char *s, char *buf)
+findconf(char *s)
{
char *p, *e;
- int n;
-
- n = strlen(s);
+ int n = strlen(s);
for(p = BOOTARGS; p < confend; p = e+1){
- for(e = p+1; e < confend; e++)
- if(*e == '\n')
- break;
- if(memcmp(p, s, n) == 0){
- p += n;
- n = e - p;
- buf[n] = 0;
- memmove(buf, p, n);
- return buf;
+ for(e = p; e < confend && *e != '\n'; e++){
+ if(*e == '\0')
+ return nil;
}
+ if(e - p >= n && memcmp(p, s, n) == 0)
+ return p;
}
return nil;
}
+static char*
+getconf(char *s, char *buf)
+{
+ char *p, *e;
+
+ if((p = findconf(s)) == nil)
+ return nil;
+ p += strlen(s);
+ for(e = p; *e != '\n'; e++)
+ ;
+ memmove(buf, p, e - p);
+ buf[e - p] = '\0';
+ return buf;
+}
+
static int
delconf(char *s)
{
char *p, *e;
- for(p = BOOTARGS; p < confend; p = e){
- for(e = p+1; e < confend; e++){
- if(*e == '\n'){
- e++;
- break;
- }
- }
- if(memcmp(p, s, strlen(s)) == 0){
- memmove(p, e, confend - e);
- confend -= e - p;
- *confend = 0;
- return 1;
- }
- }
- return 0;
+ if((p = findconf(s)) == nil)
+ return 0;
+ for(e = p; *e != '\n'; e++)
+ ;
+ e++;
+ memmove(p, e, confend - e);
+ confend -= e - p;
+ *confend = '\0';
+ return 1;
}
char*
@@ -364,6 +367,8 @@ bootkern(void *f)
close(f);
print("boot\n");
+
+ memconf(findconf("*e820=")?nil:&confend);
unload();
jump(e);