#include "vxBoot/fs/smemfs.h" #include "vxBoot/loader.h" #include "vxBoot/terminal.h" #include #include /* 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 = ld_image_mem_not_available, .strerror = "memory not available"}, {.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 smemfs_inode const * restrict const inode, struct kernel_info * restrict const kernel, Elf32_Ehdr *hdr ) { Elf32_Phdr program; uintptr_t paddress; uintptr_t origin; 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; /* check available space in RAM to load the image */ if (kernel->memory.program.size >= kernel->hardware.ram.available) return (ld_image_mem_not_available); /* set the kernel's origin address */ origin = kernel->hardware.ram.physical.kernel_addr; origin |= 0xa0000000; kernel->memory.program.start = (void*)origin; /* 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->hardware.ram.physical.kernel_addr; kernel->entry |= (uintptr_t)0x80000000; return (ld_image_success); }