shithub: riscv

Download patch

ref: 486ce605467693526541c0d46dffc25478751411
parent: ad9b1234c365919fa9d8cdb3008b4d42acf37c60
author: mischief <mischief@offblast.org>
date: Sat Nov 21 09:18:52 EST 2020

efi: prefer plan9.ini from ESP we loaded from

currently the EFI loader's behavior is to search all disks in a
firmware-defined order.  we search the list returned by the firmware
in reverse order in the hopes of searching the first 9FAT instead of
the ESP, but this results in unintuitive behavior when there are
multiple FAT partitions (possibly in multiple disks), such as loading
a plan9.ini and kernel from a different disk than the one you executed
the EFI loader from.

to resolve this, we change the EFI loader to instead prefer read
plan9.ini and the kernel from the same disk as the EFI loader was read
from, and then fall back to the old behavior, since the old behavior
is relied on by current installations.

--- a/sys/src/boot/efi/efi.h
+++ b/sys/src/boot/efi/efi.h
@@ -49,6 +49,22 @@
 } EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
 
 typedef struct {
+	UINT32		Revision;
+	EFI_HANDLE	ParentHandle;
+	void		*SystemTable;
+	EFI_HANDLE	DeviceHandle;
+	void		*FilePath;
+	void		*Reserved;
+	UINT32		LoadOptionsSize;
+	void		*LoadOptions;
+	void		*ImageBase;
+	UINT64		ImageSize;
+	UINT32		ImageCodeType;
+	UINT32		ImageDataType;
+	void		*Unload;
+} EFI_LOADED_IMAGE_PROTOCOL;
+
+typedef struct {
 	UINT32		RedMask;
 	UINT32		GreenMask;
 	UINT32		BlueMask;
--- a/sys/src/boot/efi/fs.c
+++ b/sys/src/boot/efi/fs.c
@@ -32,6 +32,12 @@
 	0xc9, 0x69, 0x72, 0x3b,
 };
 
+static EFI_GUID EFI_LOADED_IMAGE_PROTOCOL_GUID = {
+	0x5b1b31a1, 0x9562, 0x11d2,
+	0x8e, 0x3f, 0x00, 0xa0,
+	0xc9, 0x69, 0x72, 0x3b,
+};
+
 static
 EFI_FILE_PROTOCOL *fsroot;
 
@@ -87,6 +93,7 @@
 fsinit(void **pf)
 {
 	EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs;
+	EFI_LOADED_IMAGE_PROTOCOL *image;
 	EFI_FILE_PROTOCOL *root;
 	EFI_HANDLE *Handles;
 	void *f;
@@ -93,6 +100,30 @@
 	UINTN Count;
 	int i;
 
+	image = nil;
+
+	/* locate kernel and plan9.ini by deriving a fs protocol
+	 * from the device the loader was read from.
+	 * if that fails, fall back to old method.
+	 */
+	if(eficall(ST->BootServices->HandleProtocol, IH,
+		&EFI_LOADED_IMAGE_PROTOCOL_GUID, &image) == 0 &&
+		eficall(ST->BootServices->HandleProtocol, image->DeviceHandle,
+		&EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, &fs) == 0 &&
+		eficall(fs->OpenVolume, fs, &root) == 0){
+
+		fsroot = root;
+		f = fsopen("/plan9.ini");
+		if(f != nil){
+			if(pf != nil)
+				*pf = f;
+			else
+				fsclose(f);
+
+			goto gotit;
+		}
+	}
+
 	Count = 0;
 	Handles = nil;
 	if(eficall(ST->BootServices->LocateHandleBuffer,
@@ -126,6 +157,7 @@
 	if(fsroot == nil)
 		return -1;
 
+gotit:
 	read = fsread;
 	close = fsclose;
 	open = fsopen;
--- a/sys/src/boot/efi/iso.c
+++ b/sys/src/boot/efi/iso.c
@@ -62,7 +62,7 @@
 } EFI_BLOCK_IO_PROTOCOL;
 
 static EFI_GUID
-EFI_BLOCK_IO_PROTOCO_GUID = {
+EFI_BLOCK_IO_PROTOCOL_GUID = {
 	0x964e5b21, 0x6459, 0x11d2,
 	0x8e, 0x39, 0x00, 0xa0,
 	0xc9, 0x69, 0x72, 0x3b,
@@ -191,13 +191,13 @@
 	Count = 0;
 	Handles = nil;
 	if(eficall(ST->BootServices->LocateHandleBuffer,
-		ByProtocol, &EFI_BLOCK_IO_PROTOCO_GUID, nil, &Count, &Handles))
+		ByProtocol, &EFI_BLOCK_IO_PROTOCOL_GUID, nil, &Count, &Handles))
 		return -1;
 
 	for(i=0; i<Count; i++){
 		bio = nil;
 		if(eficall(ST->BootServices->HandleProtocol,
-			Handles[i], &EFI_BLOCK_IO_PROTOCO_GUID, &bio))
+			Handles[i], &EFI_BLOCK_IO_PROTOCOL_GUID, &bio))
 			continue;
 	
 		media = bio->Media;