summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormischief <mischief@offblast.org>2020-11-21 14:18:52 -0800
committermischief <mischief@offblast.org>2020-11-21 14:18:52 -0800
commit486ce605467693526541c0d46dffc25478751411 (patch)
tree172c95f14737017042d61f7b6d7faaa1ac2c5d4a
parentad9b1234c365919fa9d8cdb3008b4d42acf37c60 (diff)
downloadplan9front-486ce605467693526541c0d46dffc25478751411.tar.xz
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.
-rw-r--r--sys/src/boot/efi/efi.h16
-rw-r--r--sys/src/boot/efi/fs.c32
-rw-r--r--sys/src/boot/efi/iso.c6
3 files changed, 51 insertions, 3 deletions
diff --git a/sys/src/boot/efi/efi.h b/sys/src/boot/efi/efi.h
index b78040f3d..aa411c63b 100644
--- a/sys/src/boot/efi/efi.h
+++ b/sys/src/boot/efi/efi.h
@@ -49,6 +49,22 @@ typedef struct {
} 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;
diff --git a/sys/src/boot/efi/fs.c b/sys/src/boot/efi/fs.c
index 5a13b3b6a..807dbdbcb 100644
--- a/sys/src/boot/efi/fs.c
+++ b/sys/src/boot/efi/fs.c
@@ -32,6 +32,12 @@ EFI_GUID EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID = {
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,12 +93,37 @@ int
fsinit(void **pf)
{
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs;
+ EFI_LOADED_IMAGE_PROTOCOL *image;
EFI_FILE_PROTOCOL *root;
EFI_HANDLE *Handles;
void *f;
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 @@ fsinit(void **pf)
if(fsroot == nil)
return -1;
+gotit:
read = fsread;
close = fsclose;
open = fsopen;
diff --git a/sys/src/boot/efi/iso.c b/sys/src/boot/efi/iso.c
index 05b54ca4a..74e414a19 100644
--- a/sys/src/boot/efi/iso.c
+++ b/sys/src/boot/efi/iso.c
@@ -62,7 +62,7 @@ typedef struct {
} 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 @@ isoinit(void **fp)
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;