stivale2: Implement kernel file tag
diff --git a/stage23/lib/elf.c b/stage23/lib/elf.c
index 4a706e73..e8e92854 100644
--- a/stage23/lib/elf.c
+++ b/stage23/lib/elf.c
@@ -117,9 +117,9 @@ struct elf64_rela {
uint64_t r_addend;
};
-int elf_bits(struct file_handle *fd) {
+int elf_bits(uint8_t *elf) {
struct elf64_hdr hdr;
- fread(fd, &hdr, 0, 20);
+ memcpy(&hdr, elf + (0), 20);
if (strncmp((char *)hdr.ident, "\177ELF", 4)) {
print("elf: Not a valid ELF file.\n");
@@ -136,11 +136,11 @@ int elf_bits(struct file_handle *fd) {
}
}
-static bool elf64_is_relocatable(struct file_handle *fd, struct elf64_hdr *hdr) {
+static bool elf64_is_relocatable(uint8_t *elf, struct elf64_hdr *hdr) {
// Find RELA sections
for (uint16_t i = 0; i < hdr->sh_num; i++) {
struct elf64_shdr section;
- fread(fd, §ion, hdr->shoff + i * sizeof(struct elf64_shdr),
+ memcpy(§ion, elf + (hdr->shoff + i * sizeof(struct elf64_shdr)),
sizeof(struct elf64_shdr));
if (section.sh_type != SHT_RELA)
@@ -157,11 +157,11 @@ static bool elf64_is_relocatable(struct file_handle *fd, struct elf64_hdr *hdr)
return false;
}
-static int elf64_apply_relocations(struct file_handle *fd, struct elf64_hdr *hdr, void *buffer, uint64_t vaddr, size_t size, uint64_t slide) {
+static int elf64_apply_relocations(uint8_t *elf, struct elf64_hdr *hdr, void *buffer, uint64_t vaddr, size_t size, uint64_t slide) {
// Find RELA sections
for (uint16_t i = 0; i < hdr->sh_num; i++) {
struct elf64_shdr section;
- fread(fd, §ion, hdr->shoff + i * sizeof(struct elf64_shdr),
+ memcpy(§ion, elf + (hdr->shoff + i * sizeof(struct elf64_shdr)),
sizeof(struct elf64_shdr));
if (section.sh_type != SHT_RELA)
@@ -175,10 +175,10 @@ static int elf64_apply_relocations(struct file_handle *fd, struct elf64_hdr *hdr
// This is a RELA header, get and apply all relocations
for (uint64_t offset = 0; offset < section.sh_size; offset += section.sh_entsize) {
struct elf64_rela relocation;
- fread(fd, &relocation, section.sh_offset + offset, sizeof(relocation));
+ memcpy(&relocation, elf + (section.sh_offset + offset), sizeof(relocation));
switch (relocation.r_info) {
- case R_X86_64_RELATIVE:
+ case R_X86_64_RELATIVE: {
// Relocation is before buffer
if (relocation.r_addr < vaddr)
continue;
@@ -193,9 +193,9 @@ static int elf64_apply_relocations(struct file_handle *fd, struct elf64_hdr *hdr
// Write the relocated value
*ptr = slide + relocation.r_addend;
break;
-
+ }
default:
- print("elf: Unknown RELA type: %X\n", relocation.r_info);
+ print("elf: Unknown RELA type: %x\n", relocation.r_info);
return 1;
}
}
@@ -204,9 +204,9 @@ static int elf64_apply_relocations(struct file_handle *fd, struct elf64_hdr *hdr
return 0;
}
-int elf64_load_section(struct file_handle *fd, void *buffer, const char *name, size_t limit, uint64_t slide) {
+int elf64_load_section(uint8_t *elf, void *buffer, const char *name, size_t limit, uint64_t slide) {
struct elf64_hdr hdr;
- fread(fd, &hdr, 0, sizeof(struct elf64_hdr));
+ memcpy(&hdr, elf + (0), sizeof(struct elf64_hdr));
if (strncmp((char *)hdr.ident, "\177ELF", 4)) {
print("elf: Not a valid ELF file.\n");
@@ -224,15 +224,15 @@ int elf64_load_section(struct file_handle *fd, void *buffer, const char *name, s
}
struct elf64_shdr shstrtab;
- fread(fd, &shstrtab, hdr.shoff + hdr.shstrndx * sizeof(struct elf64_shdr),
+ memcpy(&shstrtab, elf + (hdr.shoff + hdr.shstrndx * sizeof(struct elf64_shdr)),
sizeof(struct elf64_shdr));
char *names = ext_mem_alloc(shstrtab.sh_size);
- fread(fd, names, shstrtab.sh_offset, shstrtab.sh_size);
+ memcpy(names, elf + (shstrtab.sh_offset), shstrtab.sh_size);
for (uint16_t i = 0; i < hdr.sh_num; i++) {
struct elf64_shdr section;
- fread(fd, §ion, hdr.shoff + i * sizeof(struct elf64_shdr),
+ memcpy(§ion, elf + (hdr.shoff + i * sizeof(struct elf64_shdr)),
sizeof(struct elf64_shdr));
if (!strcmp(&names[section.sh_name], name)) {
@@ -240,17 +240,17 @@ int elf64_load_section(struct file_handle *fd, void *buffer, const char *name, s
return 3;
if (section.sh_size < limit)
return 4;
- fread(fd, buffer, section.sh_offset, section.sh_size);
- return elf64_apply_relocations(fd, &hdr, buffer, section.sh_addr, section.sh_size, slide);
+ memcpy(buffer, elf + (section.sh_offset), section.sh_size);
+ return elf64_apply_relocations(elf, &hdr, buffer, section.sh_addr, section.sh_size, slide);
}
}
return 2;
}
-int elf32_load_section(struct file_handle *fd, void *buffer, const char *name, size_t limit) {
+int elf32_load_section(uint8_t *elf, void *buffer, const char *name, size_t limit) {
struct elf32_hdr hdr;
- fread(fd, &hdr, 0, sizeof(struct elf32_hdr));
+ memcpy(&hdr, elf + (0), sizeof(struct elf32_hdr));
if (strncmp((char *)hdr.ident, "\177ELF", 4)) {
print("elf: Not a valid ELF file.\n");
@@ -268,15 +268,15 @@ int elf32_load_section(struct file_handle *fd, void *buffer, const char *name, s
}
struct elf32_shdr shstrtab;
- fread(fd, &shstrtab, hdr.shoff + hdr.shstrndx * sizeof(struct elf32_shdr),
+ memcpy(&shstrtab, elf + (hdr.shoff + hdr.shstrndx * sizeof(struct elf32_shdr)),
sizeof(struct elf32_shdr));
char *names = ext_mem_alloc(shstrtab.sh_size);
- fread(fd, names, shstrtab.sh_offset, shstrtab.sh_size);
+ memcpy(names, elf + (shstrtab.sh_offset), shstrtab.sh_size);
for (uint16_t i = 0; i < hdr.sh_num; i++) {
struct elf32_shdr section;
- fread(fd, §ion, hdr.shoff + i * sizeof(struct elf32_shdr),
+ memcpy(§ion, elf + (hdr.shoff + i * sizeof(struct elf32_shdr)),
sizeof(struct elf32_shdr));
if (!strcmp(&names[section.sh_name], name)) {
@@ -284,7 +284,7 @@ int elf32_load_section(struct file_handle *fd, void *buffer, const char *name, s
return 3;
if (section.sh_size < limit)
return 4;
- fread(fd, buffer, section.sh_offset, section.sh_size);
+ memcpy(buffer, elf + (section.sh_offset), section.sh_size);
return 0;
}
}
@@ -292,9 +292,9 @@ int elf32_load_section(struct file_handle *fd, void *buffer, const char *name, s
return 2;
}
-int elf64_load(struct file_handle *fd, uint64_t *entry_point, uint64_t *_slide, uint32_t alloc_type) {
+int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t alloc_type) {
struct elf64_hdr hdr;
- fread(fd, &hdr, 0, sizeof(struct elf64_hdr));
+ memcpy(&hdr, elf + (0), sizeof(struct elf64_hdr));
if (strncmp((char *)hdr.ident, "\177ELF", 4)) {
print("Not a valid ELF file.\n");
@@ -316,7 +316,7 @@ int elf64_load(struct file_handle *fd, uint64_t *entry_point, uint64_t *_slide,
size_t try_count = 0;
size_t max_simulated_tries = 250;
- if (!elf64_is_relocatable(fd, &hdr)) {
+ if (!elf64_is_relocatable(elf, &hdr)) {
simulation = false;
goto final;
}
@@ -327,7 +327,7 @@ again:
final:
for (uint16_t i = 0; i < hdr.ph_num; i++) {
struct elf64_phdr phdr;
- fread(fd, &phdr, hdr.phoff + i * sizeof(struct elf64_phdr),
+ memcpy(&phdr, elf + (hdr.phoff + i * sizeof(struct elf64_phdr)),
sizeof(struct elf64_phdr));
if (phdr.p_type != PT_LOAD)
@@ -346,7 +346,7 @@ final:
goto again;
}
- fread(fd, (void *)(uintptr_t)load_vaddr, phdr.p_offset, phdr.p_filesz);
+ memcpy((void *)(uintptr_t)load_vaddr, elf + (phdr.p_offset), phdr.p_filesz);
size_t to_zero = (size_t)(phdr.p_memsz - phdr.p_filesz);
@@ -355,7 +355,7 @@ final:
memset(ptr, 0, to_zero);
}
- if (elf64_apply_relocations(fd, &hdr, (void *)(uintptr_t)load_vaddr, phdr.p_vaddr, phdr.p_memsz, slide))
+ if (elf64_apply_relocations(elf, &hdr, (void *)(uintptr_t)load_vaddr, phdr.p_vaddr, phdr.p_memsz, slide))
return -1;
}
@@ -370,9 +370,9 @@ final:
return 0;
}
-int elf32_load(struct file_handle *fd, uint32_t *entry_point, uint32_t alloc_type) {
+int elf32_load(uint8_t *elf, uint32_t *entry_point, uint32_t alloc_type) {
struct elf32_hdr hdr;
- fread(fd, &hdr, 0, sizeof(struct elf32_hdr));
+ memcpy(&hdr, elf + (0), sizeof(struct elf32_hdr));
if (strncmp((char *)hdr.ident, "\177ELF", 4)) {
print("Not a valid ELF file.\n");
@@ -391,7 +391,7 @@ int elf32_load(struct file_handle *fd, uint32_t *entry_point, uint32_t alloc_typ
for (uint16_t i = 0; i < hdr.ph_num; i++) {
struct elf32_phdr phdr;
- fread(fd, &phdr, hdr.phoff + i * sizeof(struct elf32_phdr),
+ memcpy(&phdr, elf + (hdr.phoff + i * sizeof(struct elf32_phdr)),
sizeof(struct elf32_phdr));
if (phdr.p_type != PT_LOAD)
@@ -399,7 +399,7 @@ int elf32_load(struct file_handle *fd, uint32_t *entry_point, uint32_t alloc_typ
memmap_alloc_range((size_t)phdr.p_paddr, (size_t)phdr.p_memsz, alloc_type, true, true, false);
- fread(fd, (void *)(uintptr_t)phdr.p_paddr, phdr.p_offset, phdr.p_filesz);
+ memcpy((void *)(uintptr_t)phdr.p_paddr, elf + (phdr.p_offset), phdr.p_filesz);
size_t to_zero = (size_t)(phdr.p_memsz - phdr.p_filesz);
diff --git a/stage23/lib/elf.h b/stage23/lib/elf.h
index 331ca063..564e82a5 100644
--- a/stage23/lib/elf.h
+++ b/stage23/lib/elf.h
@@ -6,12 +6,12 @@
#define FIXED_HIGHER_HALF_OFFSET_64 ((uint64_t)0xffffffff80000000)
-int elf_bits(struct file_handle *fd);
+int elf_bits(uint8_t *elf);
-int elf64_load(struct file_handle *fd, uint64_t *entry_point, uint64_t *slide, uint32_t alloc_type);
-int elf64_load_section(struct file_handle *fd, void *buffer, const char *name, size_t limit, uint64_t slide);
+int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *slide, uint32_t alloc_type);
+int elf64_load_section(uint8_t *elf, void *buffer, const char *name, size_t limit, uint64_t slide);
-int elf32_load(struct file_handle *fd, uint32_t *entry_point, uint32_t alloc_type);
-int elf32_load_section(struct file_handle *fd, void *buffer, const char *name, size_t limit);
+int elf32_load(uint8_t *elf, uint32_t *entry_point, uint32_t alloc_type);
+int elf32_load_section(uint8_t *elf, void *buffer, const char *name, size_t limit);
#endif
diff --git a/stage23/protos/stivale.c b/stage23/protos/stivale.c
index 18b77caf..fa0b3cb5 100644
--- a/stage23/protos/stivale.c
+++ b/stage23/protos/stivale.c
@@ -32,17 +32,19 @@ void stivale_load(char *config, char *cmdline) {
stivale_struct.flags |= (1 << 1); // we give colour information
- struct file_handle *kernel = ext_mem_alloc(sizeof(struct file_handle));
+ struct file_handle *kernel_file = ext_mem_alloc(sizeof(struct file_handle));
char *kernel_path = config_get_value(config, 0, "KERNEL_PATH");
if (kernel_path == NULL)
panic("KERNEL_PATH not specified");
- if (!uri_open(kernel, kernel_path))
+ if (!uri_open(kernel_file, kernel_path))
panic("Could not open kernel resource");
struct stivale_header stivale_hdr;
+ uint8_t *kernel = freadall(kernel_file, STIVALE_MMAP_BOOTLOADER_RECLAIMABLE);
+
int bits = elf_bits(kernel);
int ret;
diff --git a/stage23/protos/stivale2.c b/stage23/protos/stivale2.c
index 90954ce0..ab8ac900 100644
--- a/stage23/protos/stivale2.c
+++ b/stage23/protos/stivale2.c
@@ -50,17 +50,19 @@ static void append_tag(struct stivale2_struct *s, struct stivale2_tag *tag) {
}
void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table) {
- struct file_handle *kernel = ext_mem_alloc(sizeof(struct file_handle));
+ struct file_handle *kernel_file = ext_mem_alloc(sizeof(struct file_handle));
char *kernel_path = config_get_value(config, 0, "KERNEL_PATH");
if (kernel_path == NULL)
panic("KERNEL_PATH not specified");
- if (!uri_open(kernel, kernel_path))
+ if (!uri_open(kernel_file, kernel_path))
panic("Could not open kernel resource");
struct stivale2_header stivale2_hdr;
+ uint8_t *kernel = freadall(kernel_file, STIVALE2_MMAP_BOOTLOADER_RECLAIMABLE);
+
int bits = elf_bits(kernel);
int ret;
@@ -126,6 +128,18 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
strcpy(stivale2_struct.bootloader_brand, "Limine");
strcpy(stivale2_struct.bootloader_version, LIMINE_VERSION);
+ //////////////////////////////////////////////
+ // Create kernel file struct tag
+ //////////////////////////////////////////////
+ {
+ struct stivale2_struct_tag_kernel_file *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_kernel_file));
+ tag->tag.identifier = STIVALE2_STRUCT_TAG_KERNEL_FILE_ID;
+
+ tag->kernel_file = (uint64_t)(uintptr_t)kernel;
+
+ append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
+ }
+
//////////////////////////////////////////////
// Create firmware struct tag
//////////////////////////////////////////////
diff --git a/test/stivale2.c b/test/stivale2.c
index 7e80ed65..77b6a103 100644
--- a/test/stivale2.c
+++ b/test/stivale2.c
@@ -134,6 +134,11 @@ void stivale2_main(struct stivale2_struct *info) {
e9_printf("EFI system table at: %x", t->system_table);
break;
}
+ case STIVALE2_STRUCT_TAG_KERNEL_FILE_ID: {
+ struct stivale2_struct_tag_kernel_file *t = (struct stivale2_struct_tag_kernel_file *)tag;
+ e9_printf("Raw kernel file loaded at: %x", t->kernel_file);
+ break;
+ }
case STIVALE2_STRUCT_TAG_SMP_ID: {
struct stivale2_struct_tag_smp *s = (struct stivale2_struct_tag_smp *)tag;
e9_puts("SMP tag:");
