vxBoot/src/loader/elf/image.c

90 lines
2.6 KiB
C
Raw Normal View History

2021-10-08 19:32:46 +02:00
#include "vxBoot/fs/smemfs.h"
#include "vxBoot/loader.h"
#include <stdlib.h>
#include <string.h>
/* error string list */
const struct ld_error_db image_error_db[] = {
{.id = ld_image_success, .strerror = "valid"},
{.id = ld_image_size_error, .strerror = "size error"},
{.id = ld_image_type_error, .strerror = "type error"},
{.id = ld_image_mem_error, .strerror = "out of memory error"},
{.id = 0xdeb0cad0, .strerror = NULL},
};
/* hypervisor_elf_loader_image_error(): Display image error information */
int loader_image_error(int const errnum)
{
return (loader_error(image_error_db, "ELF image ", errnum));
}
/* loader_load_image() - Load the program into Virtual Memory */
int loader_image_load(
struct kernel_info * restrict const kernel,
struct smemfs_inode * restrict const inode,
Elf32_Ehdr *hdr
) {
Elf32_Phdr program;
uintptr_t paddress;
uintptr_t vmin;
uintptr_t vmax;
off_t offset;
uint16_t i;
/* Walk one time to get the entier program size and check ELF
validity. */
i = -1;
vmin = 0xffffffff;
vmax = 0x00000000;
kernel->memory.program.size = 0;
while (++i < hdr->e_phnum) {
offset = hdr->e_phoff + (i * sizeof(Elf32_Phdr));
if (smemfs_pread(inode, &program, sizeof(Elf32_Phdr), offset)
!= sizeof(Elf32_Phdr)) {
return (ld_image_size_error);
}
if (program.p_vaddr < vmin)
vmin = program.p_vaddr;
if (program.p_vaddr + program.p_memsz > vmax)
vmax = program.p_vaddr + program.p_memsz;
}
kernel->memory.program.size = vmax - vmin;
kernel->memory.program.elf.vmin = vmin;
kernel->memory.program.elf.vmax = vmax;
/* Allocate programe memory */
kernel->memory.program.start = calloc(1, kernel->memory.program.size);
if (kernel->memory.program.start == NULL)
return (ld_image_mem_error);
/* Now, load all program section into physical memory. To do this, we
read each program hdr, generate the "real" physical address of
the segment then dump data.
Note that the p_filesz can be smaller than p_memsz so, we need to
wipe the segment area before the dump. */
i = -1;
while (++i < hdr->e_phnum) {
offset = hdr->e_phoff + (i * sizeof(Elf32_Phdr));
smemfs_pread(inode, &program, sizeof(Elf32_Phdr), offset);
paddress = (uintptr_t)program.p_vaddr - vmin;
paddress += (uintptr_t)kernel->memory.program.start;
memset((void*)paddress, 0x00, program.p_memsz);
smemfs_pread(
inode,
(void*)paddress,
program.p_filesz,
program.p_offset
);
}
/* Generate program entry address */
kernel->entry = (uintptr_t)hdr->e_entry - vmin;
kernel->entry += (uintptr_t)kernel->memory.program.start;
return (ld_image_success);
}