#include "vxBoot/terminal.h" #include "vxBoot/fs/smemfs.h" #include "vxBoot/loader.h" #include #include /* error string list */ const struct ld_error_db header_error_db[] = { {.id = ld_header_valid, .strerror = "valid"}, {.id = ld_header_size_error, .strerror = "size error"}, {.id = ld_header_magic_error, .strerror = "magic error"}, {.id = ld_header_class_error, .strerror = "class error"}, {.id = ld_header_indent_error, .strerror = "indent error"}, {.id = ld_header_type_error, .strerror = "type error"}, {.id = ld_header_machine_error, .strerror = "machine error"}, {.id = ld_header_version_error, .strerror = "version error"}, {.id = 0xdeb0cad0, .strerror = NULL}, }; /* loader_header_error(): Display header error information */ int loader_header_error(int const errnum) { return (loader_error(header_error_db, "ELF header", errnum)); } /* loader_header_get(): Get ELF header and check validity */ int loader_header_get( struct smemfs_inode const * restrict const inode, Elf32_Ehdr *header ) { Elf32_Ehdr tmp; if (header == NULL) header = &tmp; /* try to read the ELF header */ if (smemfs_pread(inode, header, sizeof(*header), 0) != sizeof(*header)) return (ld_header_size_error); /* Check magic number */ if (header->e_ident[EI_MAG0] != ELFMAG0 || header->e_ident[EI_MAG1] != ELFMAG1 || header->e_ident[EI_MAG2] != ELFMAG2 || header->e_ident[EI_MAG3] != ELFMAG3) { return (ld_header_magic_error); } /* Check class */ if (header->e_ident[EI_CLASS] != ELFCLASS32) return (ld_header_class_error); /* Check data encoding */ if (header->e_ident[EI_DATA] != ELFDATA2MSB) return (ld_header_indent_error); /* Check ELF type */ if (header->e_type != ET_DYN && header->e_type != ET_EXEC) return (ld_header_type_error); /* Check ELF specifique instruction */ if (header->e_machine != EM_SH) return (ld_header_machine_error); /* Check ELF version */ if (header->e_version != EV_CURRENT) return (ld_header_version_error); return (ld_header_valid); } /* hypervisor_elf_loader_header_check(): Check ELF header validity and dump usefull sections information */ int loader_header_check(struct kernel * const kernel) { Elf32_Shdr *shdr; char * shstrtab; int error; error = loader_header_get(kernel->inode, &kernel->elf.hdr); if (error != ld_header_valid) return (error); kernel->elf.shdr = malloc( kernel->elf.hdr.e_shnum * kernel->elf.hdr.e_shentsize ); smemfs_pread( kernel->inode, kernel->elf.shdr, kernel->elf.hdr.e_shnum * kernel->elf.hdr.e_shentsize, kernel->elf.hdr.e_shoff ); kernel->elf.shstrtab = malloc( kernel->elf.shdr[kernel->elf.hdr.e_shstrndx].sh_size ); smemfs_pread( kernel->inode, kernel->elf.shstrtab, kernel->elf.shdr[kernel->elf.hdr.e_shstrndx].sh_size, kernel->elf.shdr[kernel->elf.hdr.e_shstrndx].sh_offset ); kernel->elf.phdr = malloc(kernel->elf.hdr.e_phnum * sizeof(Elf32_Phdr)); smemfs_pread( kernel->inode, kernel->elf.phdr, kernel->elf.hdr.e_phnum * sizeof(Elf32_Phdr), kernel->elf.hdr.e_phoff ); shdr = kernel->elf.shdr; shstrtab = kernel->elf.shstrtab; kernel->elf.sym.tab = NULL; kernel->elf.sym.nb = 0; kernel->elf.strtab = NULL; kernel->elf.got = NULL; for (int i = 0; i < kernel->elf.hdr.e_shnum; ++i) { if (shdr[i].sh_type == SHT_SYMTAB) { if (kernel->elf.sym.tab == NULL) { kernel->elf.sym.tab = malloc(shdr[i].sh_size); smemfs_pread( kernel->inode, kernel->elf.sym.tab, shdr[i].sh_size, shdr[i].sh_offset ); kernel->elf.sym.nb = shdr[i].sh_size; kernel->elf.sym.nb /= sizeof(Elf32_Sym); } continue; } if (kernel->elf.strtab == NULL) { if (strcmp(".strtab", &shstrtab[shdr[i].sh_name]) == 0){ kernel->elf.strtab = malloc(shdr[i].sh_size); smemfs_pread( kernel->inode, kernel->elf.strtab, shdr[i].sh_size, shdr[i].sh_offset ); continue; } } if (kernel->elf.got == NULL) { if (strcmp(".got", &shstrtab[shdr[i].sh_name]) == 0) { kernel->elf.got = (void*)(uintptr_t)shdr[i].sh_addr; kernel->elf.got_nb = shdr[i].sh_size; kernel->elf.got_nb /= sizeof(uintptr_t); continue; } } } terminal_log( LOG_DEBUG, "symtab = %p with %d entries\n" "shstrtab = %p\n" "strtab = %p\n" "shdr = %p\n" "phdr = %p\n" "got = %p\n", kernel->elf.sym.tab, kernel->elf.sym.nb, kernel->elf.shstrtab, kernel->elf.strtab, kernel->elf.shdr, kernel->elf.phdr, kernel->elf.got ); return (0); }