chainload: Misc bug fixes and improvements
diff --git a/stage23/drivers/disk.s2.c b/stage23/drivers/disk.s2.c
index 0832bcdf..08017dd6 100644
--- a/stage23/drivers/disk.s2.c
+++ b/stage23/drivers/disk.s2.c
@@ -372,6 +372,16 @@ static void find_unique_sectors(void) {
}
}
+static void find_part_handles(EFI_HANDLE *handles, size_t handle_count) {
+ for (size_t i = 0; i < handle_count; i++) {
+ struct volume *vol = disk_volume_from_efi_handle(handles[i]);
+ if (vol == NULL) {
+ continue;
+ }
+ vol->efi_part_handle = handles[i];
+ }
+}
+
void disk_create_index(void) {
EFI_STATUS status;
@@ -389,7 +399,9 @@ void disk_create_index(void) {
int optical_indices = 1, hdd_indices = 1;
- for (size_t i = 0; i < handles_size / sizeof(EFI_HANDLE); i++) {
+ size_t handle_count = handles_size / sizeof(EFI_HANDLE);
+
+ for (size_t i = 0; i < handle_count; i++) {
if (volume_index_i == MAX_VOLUMES) {
print("WARNING: TOO MANY VOLUMES!");
break;
@@ -456,6 +468,7 @@ void disk_create_index(void) {
}
find_unique_sectors();
+ find_part_handles(handles, handle_count);
}
#endif
diff --git a/stage23/fs/file.h b/stage23/fs/file.h
index ac261f47..57d3a413 100644
--- a/stage23/fs/file.h
+++ b/stage23/fs/file.h
@@ -5,6 +5,9 @@
#include <stddef.h>
#include <stdbool.h>
#include <lib/part.h>
+#if uefi == 1
+# include <efi.h>
+#endif
bool fs_get_guid(struct guid *guid, struct volume *part);
@@ -13,6 +16,9 @@ struct file_handle {
void *fd;
int (*read)(void *fd, void *buf, uint64_t loc, uint64_t count);
uint64_t size;
+#if uefi == 1
+ EFI_HANDLE efi_part_handle;
+#endif
};
int fopen(struct file_handle *ret, struct volume *part, const char *filename);
diff --git a/stage23/fs/file.s2.c b/stage23/fs/file.s2.c
index 74994402..a90e9fcb 100644
--- a/stage23/fs/file.s2.c
+++ b/stage23/fs/file.s2.c
@@ -36,6 +36,10 @@ int fopen(struct file_handle *ret, struct volume *part, const char *filename) {
}
#endif
+#if uefi == 1
+ ret->efi_part_handle = part->efi_part_handle;
+#endif
+
if (iso9660_check_signature(part)) {
struct iso9660_file_handle *fd = ext_mem_alloc(sizeof(struct iso9660_file_handle));
diff --git a/stage23/lib/part.h b/stage23/lib/part.h
index b6de033e..398e9d86 100644
--- a/stage23/lib/part.h
+++ b/stage23/lib/part.h
@@ -16,6 +16,7 @@
struct volume {
#if uefi == 1
EFI_HANDLE efi_handle;
+ EFI_HANDLE efi_part_handle;
EFI_BLOCK_IO *block_io;
bool unique_sector_valid;
diff --git a/stage23/mm/pmm.s2.c b/stage23/mm/pmm.s2.c
index 063e4e16..85f4cc77 100644
--- a/stage23/mm/pmm.s2.c
+++ b/stage23/mm/pmm.s2.c
@@ -324,19 +324,26 @@ void init_memmap(void) {
our_type = MEMMAP_USABLE; break;
}
- memmap[memmap_entries].type = our_type;
- memmap[memmap_entries].base = entry->PhysicalStart;
- memmap[memmap_entries].length = entry->NumberOfPages * 4096;
+ uint64_t base = entry->PhysicalStart;
+ uint64_t length = entry->NumberOfPages * 4096;
+
+ if (our_type == MEMMAP_USABLE) {
+ if (base + length >= 0x100000000) {
+ our_type = MEMMAP_EFI_RECLAIMABLE;
+ } else if (base < 0x1000) {
+ if (base + length <= 0x1000) {
+ continue;
+ }
- if (memmap[memmap_entries].base < 0x1000) {
- if (memmap[memmap_entries].base + memmap[memmap_entries].length <= 0x1000) {
- continue;
+ length -= 0x1000 - base;
+ base = 0x1000;
}
-
- memmap[memmap_entries].length -= 0x1000 - memmap[memmap_entries].base;
- memmap[memmap_entries].base = 0x1000;
}
+ memmap[memmap_entries].base = base;
+ memmap[memmap_entries].length = length;
+ memmap[memmap_entries].type = our_type;
+
memmap_entries++;
}
@@ -344,7 +351,7 @@ void init_memmap(void) {
allocations_disallowed = false;
- // Let's leave 64MiB to the firmware
+ // Let's leave 64MiB to the firmware below 4GiB
for (size_t i = 0; i < 64; i++) {
ext_mem_alloc_type(0x100000, MEMMAP_EFI_RECLAIMABLE);
}
diff --git a/stage23/protos/chainload.c b/stage23/protos/chainload.c
index acea5558..f773488c 100644
--- a/stage23/protos/chainload.c
+++ b/stage23/protos/chainload.c
@@ -120,6 +120,8 @@ void chainload(char *config) {
if (!uri_open(image, image_path))
panic("chainload: Failed to open image with path `%s`. Is the path correct?", image_path);
+ EFI_HANDLE efi_part_handle = image->efi_part_handle;
+
void *_ptr = freadall(image, MEMMAP_RESERVED);
size_t image_size = image->size;
void *ptr;
@@ -171,13 +173,6 @@ void chainload(char *config) {
// as us (the loader) for some EFI images to properly work (Windows for instance)
EFI_GUID loaded_img_prot_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
- EFI_LOADED_IMAGE_PROTOCOL *loader_loaded_image = NULL;
- status = gBS->HandleProtocol(efi_image_handle, &loaded_img_prot_guid,
- (void **)&loader_loaded_image);
- if (status) {
- panic("chainload: HandleProtocol failure (%x)", status);
- }
-
EFI_LOADED_IMAGE_PROTOCOL *new_handle_loaded_image = NULL;
status = gBS->HandleProtocol(new_handle, &loaded_img_prot_guid,
(void **)&new_handle_loaded_image);
@@ -185,7 +180,9 @@ void chainload(char *config) {
panic("chainload: HandleProtocol failure (%x)", status);
}
- new_handle_loaded_image->DeviceHandle = loader_loaded_image->DeviceHandle;
+ if (efi_part_handle != 0) {
+ new_handle_loaded_image->DeviceHandle = efi_part_handle;
+ }
UINTN exit_data_size = 0;
CHAR16 *exit_data = NULL;
