2020-01-01 14:19:18 +01:00
|
|
|
#include <kernel/loader.h>
|
2020-01-05 09:00:43 +01:00
|
|
|
#include <kernel/fs/vfs.h>
|
2020-01-01 14:19:18 +01:00
|
|
|
#include <kernel/memory.h>
|
2020-03-15 00:56:31 +01:00
|
|
|
#include <lib/string.h>
|
2020-01-01 14:19:18 +01:00
|
|
|
|
|
|
|
/* loader_load_image() - Load the program into Virtual Memory */
|
2020-03-15 00:56:31 +01:00
|
|
|
int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header)
|
2020-01-01 14:19:18 +01:00
|
|
|
{
|
|
|
|
Elf32_Phdr program;
|
|
|
|
uint32_t paddress;
|
|
|
|
uint16_t i;
|
|
|
|
|
|
|
|
// Walk one time to get program size and
|
|
|
|
// check ELF validity.
|
|
|
|
i = -1;
|
|
|
|
process->memory.program.size = 0;
|
|
|
|
while (++i < header->e_phnum)
|
|
|
|
{
|
|
|
|
// Read programme header.
|
2020-01-05 09:00:43 +01:00
|
|
|
vfs_lseek(file, header->e_phoff + (sizeof(Elf32_Phdr) * i), SEEK_SET);
|
|
|
|
if (vfs_read(file, &program, sizeof(Elf32_Phdr)) != sizeof(Elf32_Phdr))
|
2020-03-15 00:56:31 +01:00
|
|
|
return (-1);
|
2020-01-01 14:19:18 +01:00
|
|
|
|
|
|
|
// Check programe type.
|
|
|
|
if (program.p_type != PT_LOAD)
|
2020-03-15 00:56:31 +01:00
|
|
|
return (-2);
|
2020-01-01 14:19:18 +01:00
|
|
|
|
|
|
|
// Update program size
|
|
|
|
process->memory.program.size = process->memory.program.size + program.p_memsz;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate programe space into
|
|
|
|
// physical memory.
|
|
|
|
process->memory.program.start = (uint32_t)pm_alloc(process->memory.program.size);
|
|
|
|
if (process->memory.program.start == 0x00000000)
|
2020-03-15 00:56:31 +01:00
|
|
|
return (-3);
|
2020-01-01 14:19:18 +01:00
|
|
|
|
|
|
|
// Now, load all program section into
|
|
|
|
// physical memory.
|
|
|
|
i = -1;
|
|
|
|
while (++i < header->e_phnum)
|
|
|
|
{
|
|
|
|
// Read programme header.
|
2020-01-05 09:00:43 +01:00
|
|
|
vfs_lseek(file, header->e_phoff + (sizeof(Elf32_Phdr) * i), SEEK_SET);
|
|
|
|
vfs_read(file, &program, sizeof(Elf32_Phdr));
|
2020-01-01 14:19:18 +01:00
|
|
|
|
|
|
|
// Generate physical address
|
|
|
|
paddress = program.p_vaddr + process->memory.program.start;
|
|
|
|
|
|
|
|
// p_filesz can be smaller than p_memsz so, we need to wipe the area
|
|
|
|
// before the dump.
|
|
|
|
memset((void *)paddress, 0, program.p_memsz);
|
|
|
|
|
|
|
|
// Dump the program.
|
2020-01-05 09:00:43 +01:00
|
|
|
vfs_lseek(file, program.p_offset, SEEK_SET);
|
|
|
|
vfs_read(file, (void *)paddress, program.p_filesz);
|
2020-01-01 14:19:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Generate program entry address
|
2020-03-15 00:56:31 +01:00
|
|
|
process->context.spc = (uint32_t)(header->e_entry + (uint32_t)process->memory.program.start);
|
|
|
|
return ((process->context.spc == 0x00000000));
|
2020-01-01 14:19:18 +01:00
|
|
|
}
|