lib/config: Change default paths for config search and ordering
Also prefer searching within the EFI app's directory first, on EFI.
diff --git a/CONFIG.md b/CONFIG.md
index 0fdcefec..a7fc0a32 100644
--- a/CONFIG.md
+++ b/CONFIG.md
@@ -2,22 +2,13 @@
## Location of the config file
-First, Limine considers configurations supplied to it as SMBIOS OEM String
-entries (Type 11). Such configurations are accepted if the first string of such
-an entry starts with the prefix of `limine:config:`. The rest of the string is
-taken as the config file. If such a configuration is found, no further scanning
-for config files is done. As such, the `boot():` drive is undefined on BIOS,
-and set to the boot device of Limine on UEFI.
-
-Next, Limine scans for a config file on *the boot drive*. Every partition on
-the boot drive is scanned sequentially - first partition first (or, on UEFI,
-the partition containing the EFI executable of the booted Limine is scanned
-first), last partition last - for the presence of either a `/limine.conf`,
-`/limine/limine.conf`, `/boot/limine.conf`, or a `/boot/limine/limine.conf`
-file, in that order.
-
-For EFI-booted Limine, `/EFI/BOOT/limine.conf` and `/EFI/limine/limine.conf`
-are also scanned, after the aforementioned paths, in that order.
+For EFI-booted Limine, `<EFI app path>/limine.conf` is taken into account
+first. On BIOS, or on EFI if that file is not found, Limine scans for the
+config file on *the boot drive*. Every partition of the boot drive is scanned
+sequentially - first partition first (or, on EFI, the partition containing the
+EFI executable of the booted Limine is scanned first), last partition last -
+for the presence of either a `/boot/limine/limine.conf`, `/boot/limine.conf`,
+`/limine/limine.conf`, or a `/limine.conf` file, in that order.
Once the file is located, Limine will use it as its config file. Other possible
candidates in subsequent partitions or directories are ignored.
@@ -25,6 +16,16 @@ candidates in subsequent partitions or directories are ignored.
It is thus imperative that the intended config file is placed in a location
that will not be shadowed by another candidate config file.
+### Config via SMBIOS
+
+Alternatively, if present, Limine considers first and foremost configurations
+supplied to it as SMBIOS OEM String entries (Type 11). Such configurations are
+accepted if the first string of such an entry starts with the prefix of
+`limine:config:`. The rest of the string is taken as the config file. If such a
+configuration is found, no further scanning for config files is done. As such,
+in this SMBIOS-provided config file scenario, the `boot():` drive is undefined
+on BIOS, and set to the boot device of Limine on UEFI.
+
## Structure of the config file
The Limine configuration file is comprised of *menu entries* and *options*.
diff --git a/USAGE.md b/USAGE.md
index cc645f51..f7917756 100644
--- a/USAGE.md
+++ b/USAGE.md
@@ -10,10 +10,8 @@ the `/EFI/BOOT` directory of a FAT formatted EFI system partition. These files
can be installed there and coexist with a BIOS installation of Limine
(see below) so that the disk will be bootable on both BIOS and UEFI systems.
-The boot device must contain the `limine.conf` files in
-either the root, `limine`, `boot`, or `boot/limine` directory of one of the
-partitions, formatted with a supported file system (the ESP partition is
-recommended).
+A valid config file should also be provided as described in
+[CONFIG.md](CONFIG.md).
## Secure Boot
Limine can be booted with secure boot if the executable is signed and the key
@@ -32,8 +30,8 @@ limine bios-install <path to device/image>
```
The boot device must contain the `limine-bios.sys` and `limine.conf` files in
-either the root, `limine`, `boot`, or `boot/limine` directory of one of the
-partitions, formatted with a supported file system.
+either a `boot/limine`, `boot`, `limine`, or root directory of one of the
+partitions, formatted with a supported file system. See [CONFIG.md](CONFIG.md).
## BIOS/GPT
If using a GPT formatted device, create a partition on the GPT device (usually
@@ -45,8 +43,8 @@ limine bios-install <path to device/image> <1-based stage 2 partition number>
```
The boot device must contain the `limine-bios.sys` and `limine.conf` files in
-either the root, `limine`, `boot`, or `boot/limine` directory of one of the
-partitions, formatted with a supported file system.
+either a `boot/limine`, `boot`, `limine`, or root directory of one of the
+partitions, formatted with a supported file system. See [CONFIG.md](CONFIG.md).
## BIOS/UEFI hybrid ISO creation
In order to create a hybrid ISO with Limine, place the
diff --git a/common/entry.s2.c b/common/entry.s2.c
index f72e3c37..8cbd37fc 100644
--- a/common/entry.s2.c
+++ b/common/entry.s2.c
@@ -41,10 +41,12 @@ static bool stage3_init(struct volume *part) {
bool old_cif = case_insensitive_fopen;
case_insensitive_fopen = true;
- if ((stage3 = fopen(part, "/limine-bios.sys")) == NULL
- && (stage3 = fopen(part, "/limine/limine-bios.sys")) == NULL
+ if (true
+ && (stage3 = fopen(part, "/boot/limine/limine-bios.sys")) == NULL
&& (stage3 = fopen(part, "/boot/limine-bios.sys")) == NULL
- && (stage3 = fopen(part, "/boot/limine/limine-bios.sys")) == NULL) {
+ && (stage3 = fopen(part, "/limine/limine-bios.sys")) == NULL
+ && (stage3 = fopen(part, "/limine-bios.sys")) == NULL
+ ) {
case_insensitive_fopen = old_cif;
return false;
}
diff --git a/common/entry.s3.c b/common/entry.s3.c
index cb7bb783..9eb2497d 100644
--- a/common/entry.s3.c
+++ b/common/entry.s3.c
@@ -98,20 +98,31 @@ defer_error:
could_not_match:
print("WARNING: Could not meaningfully match the boot device handle with a volume.\n");
print(" Using the first volume containing a Limine configuration!\n");
+ print("\n");
+ print("THIS IS A BUG! Please report this issue upstream.\n");
+ print("Press any key to continue...\n");
+ for (;;) {
+ int ret = pit_sleep_and_quit_on_keypress(65535);
+ if (ret != 0) {
+ break;
+ }
+ }
for (size_t i = 0; i < volume_index_i; i++) {
struct file_handle *f;
bool old_cif = case_insensitive_fopen;
case_insensitive_fopen = true;
- if ((f = fopen(volume_index[i], "/limine.conf")) != NULL
- || (f = fopen(volume_index[i], "/limine/limine.conf")) != NULL
- || (f = fopen(volume_index[i], "/boot/limine.conf")) != NULL
- || (f = fopen(volume_index[i], "/boot/limine/limine.conf")) != NULL
+ if (
+ false
#if defined (UEFI)
- || (f = fopen(volume_index[i], "/EFI/BOOT/limine.conf")) != NULL
|| (f = fopen(volume_index[i], "/EFI/limine/limine.conf")) != NULL
+ || (f = fopen(volume_index[i], "/EFI/BOOT/limine.conf")) != NULL
#endif
+ || (f = fopen(volume_index[i], "/boot/limine/limine.conf")) != NULL
+ || (f = fopen(volume_index[i], "/boot/limine.conf")) != NULL
+ || (f = fopen(volume_index[i], "/limine/limine.conf")) != NULL
+ || (f = fopen(volume_index[i], "/limine.conf")) != NULL
) {
goto opened;
}
diff --git a/common/lib/config.c b/common/lib/config.c
index a82aa08f..87cc5d1a 100644
--- a/common/lib/config.c
+++ b/common/lib/config.c
@@ -27,19 +27,104 @@ no_unwind bool bad_config = false;
static char *config_addr;
+#if defined (UEFI)
+
+#define EFI_APP_PATH_LEN 128
+static char efi_app_path[128] = {0};
+
+static bool init_efi_app_path(size_t *len_out) {
+ EFI_STATUS status;
+ EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
+ EFI_DEVICE_PATH_PROTOCOL *path;
+ CHAR16 *file_path, *p, *last_slash;
+
+ EFI_GUID loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+
+ status = gBS->HandleProtocol(efi_image_handle, &loaded_image_protocol_guid,
+ (void **)&loaded_image);
+ if (status != 0) {
+ return false;
+ }
+
+ path = loaded_image->FilePath;
+
+ while (!(path->Type == END_DEVICE_PATH_TYPE && path->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE)) {
+ if (path->Type == MEDIA_DEVICE_PATH && path->SubType == MEDIA_FILEPATH_DP) {
+ goto found;
+ }
+
+ path = (void *)path + *((uint16_t *)&path->Length[0]);
+ }
+
+ return false;
+
+found:
+ file_path = (CHAR16 *)((void *)path + 4);
+
+ last_slash = NULL;
+ for (p = file_path; *p; p++) {
+ if (*p == L'\\') {
+ last_slash = p;
+ }
+ }
+
+ if (last_slash) {
+ size_t len = (last_slash - file_path) + 1;
+ if (len >= EFI_APP_PATH_LEN) {
+ len = EFI_APP_PATH_LEN - 1;
+ }
+
+ for (size_t i = 0; i < len; i++) {
+ efi_app_path[i] = (char)(file_path[i] & 0xff);
+ if (efi_app_path[i] == '\\') {
+ efi_app_path[i] = '/';
+ }
+ }
+ efi_app_path[len] = 0;
+ if (len_out != NULL) {
+ *len_out = len;
+ }
+ } else {
+ efi_app_path[0] = '/';
+ efi_app_path[1] = 0;
+ if (len_out != NULL) {
+ *len_out = 1;
+ }
+ }
+
+ return true;
+}
+#endif
+
int init_config_disk(struct volume *part) {
+#if defined (UEFI)
+ bool use_default_efi_search_path = false;
+
+ size_t len;
+ if (!init_efi_app_path(&len)) {
+ use_default_efi_search_path = true;
+ } else {
+ if (len + sizeof("limine.conf") >= EFI_APP_PATH_LEN) {
+ use_default_efi_search_path = true;
+ } else {
+ strcpy(efi_app_path + len, "limine.conf");
+ }
+ }
+#endif
+
struct file_handle *f;
bool old_cif = case_insensitive_fopen;
case_insensitive_fopen = true;
- if ((f = fopen(part, "/limine.conf")) != NULL
- || (f = fopen(part, "/limine/limine.conf")) != NULL
- || (f = fopen(part, "/boot/limine.conf")) != NULL
- || (f = fopen(part, "/boot/limine/limine.conf")) != NULL
+ if (
+ false
#if defined (UEFI)
- || (f = fopen(part, "/EFI/BOOT/limine.conf")) != NULL
- || (f = fopen(part, "/EFI/limine/limine.conf")) != NULL
+ || (f = fopen(part, use_default_efi_search_path ? "/EFI/BOOT/limine.conf" : efi_app_path)) != NULL
#endif
+ || (f = fopen(part, "/boot/limine/limine.conf")) != NULL
+ || (f = fopen(part, "/boot/limine.conf")) != NULL
+ || (f = fopen(part, "/limine/limine.conf")) != NULL
+ || (f = fopen(part, "/limine.conf")) != NULL
) {
goto opened;
}
