Skip to content

Commit

Permalink
multiboot: abstract ELF handling away into context
Browse files Browse the repository at this point in the history
  • Loading branch information
fabianfreyer committed Feb 22, 2018
1 parent d4fb303 commit 93e27b0
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 36 deletions.
34 changes: 15 additions & 19 deletions multiboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@

#include <allocator.h>

void *entry = NULL;

uint32_t
multiboot_info_set_meminfo(struct multiboot_info* info,
uint32_t mem_lower, uint32_t mem_upper)
Expand Down Expand Up @@ -223,8 +221,7 @@ mb_scan(void *kernel, size_t kernsz)
}

enum LOAD_TYPE
multiboot_load_type (void* kernel, size_t kernsz, Elf **kernel_elf,
struct multiboot *mb)
multiboot_load_type (void* kernel, size_t kernsz, struct multiboot *mb)
{
struct multiboot_header *mbh = mb->header.mb.header;

Expand All @@ -235,12 +232,12 @@ multiboot_load_type (void* kernel, size_t kernsz, Elf **kernel_elf,
}

/* Check if the file is an ELF */
if (((*kernel_elf = elf_memory(kernel, kernsz)) == NULL)
|| (elf_kind(*kernel_elf) != ELF_K_ELF))
if (((mb->kernel_elf = elf_memory(kernel, kernsz)) == NULL)
|| (elf_kind(mb->kernel_elf) != ELF_K_ELF))
{
/* Not an ELF. Try loading it as an a.out. */
elf_end(*kernel_elf);
*kernel_elf = NULL;
elf_end(mb->kernel_elf);
mb->kernel_elf = NULL;
return LOAD_AOUT;
}

Expand Down Expand Up @@ -344,26 +341,26 @@ multiboot_load_aout(void* kernel, size_t kernsz, struct multiboot *mb)
*/
}

entry = (void*) (uintptr_t) mbh->entry_addr;
mb->entry = (void*) (uintptr_t) mbh->entry_addr;

return 0;
}

uint32_t
multiboot_load_elf(void *kernel, size_t kernsz, Elf *kernel_elf) {
multiboot_load_elf(void *kernel, size_t kernsz, struct multiboot *mb) {
size_t elf_phnum = 0;
int elf_phidx = 0;
GElf_Ehdr elf_ehdr;
GElf_Phdr elf_phdr;

/* Get the elf Ehdr */
if (!gelf_getehdr(kernel_elf, &elf_ehdr)) {
if (!gelf_getehdr(mb->kernel_elf, &elf_ehdr)) {
ERROR(EINVAL, "Could not get number of ELF headers");
return EINVAL;
}

/* Get the number of ELF program headers. */
if (!elf_getphnum(kernel_elf, &elf_phnum)) {
if (!elf_getphnum(mb->kernel_elf, &elf_phnum)) {
ERROR(EINVAL, "Could not get number of ELF program headers.");
return EINVAL;
}
Expand All @@ -382,7 +379,7 @@ multiboot_load_elf(void *kernel, size_t kernsz, Elf *kernel_elf) {
}

for (elf_phidx = 0; elf_phidx < elf_phnum; elf_phidx++) {
gelf_getphdr(kernel_elf, elf_phidx, &elf_phdr);
gelf_getphdr(mb->kernel_elf, elf_phidx, &elf_phdr);

if (elf_phdr.p_type != PT_LOAD)
continue;
Expand Down Expand Up @@ -439,25 +436,24 @@ multiboot_load_elf(void *kernel, size_t kernsz, Elf *kernel_elf) {
*/
}

entry = (void*) elf_ehdr.e_entry;
mb->entry = (void*) elf_ehdr.e_entry;
return 0;
}

uint32_t
multiboot_load(void* kernel, size_t kernsz, struct multiboot *mb)
{
Elf *kernel_elf = NULL;
uint32_t error = 0;

switch (multiboot_load_type(kernel, kernsz, &kernel_elf, mb)) {
switch (multiboot_load_type(kernel, kernsz, mb)) {
case LOAD_AOUT:
error = multiboot_load_aout(kernel, kernsz, mb);
return error;

case LOAD_ELF:
error = multiboot_load_elf(kernel, kernsz, kernel_elf);
if (kernel_elf)
elf_end(kernel_elf);
error = multiboot_load_elf(kernel, kernsz, mb);
if (mb->kernel_elf)
elf_end(mb->kernel_elf);
return error;
}
}
Expand Down
13 changes: 6 additions & 7 deletions multiboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
#include <libelf.h>

#define MULTIBOOT1_MAGIC 0x1BADB002
#define MULTIBOOT1_BOOTLOADER_MAGICC 0x2BADB002
#define MULTIBOOT1_BOOTLOADER_MAGIC 0x2BADB002
#define MULTIBOOT2_MAGIC 0xE85250D6

#define MULTIBOOT_AOUT_KLUDGE (1<<16)
Expand Down Expand Up @@ -174,6 +174,8 @@ struct multiboot {
struct multiboot2_header* header;
} mb2;
} header;
void* entry;
Elf *kernel_elf;
struct multiboot_info info;
};

Expand All @@ -194,14 +196,11 @@ struct multiboot* mb_scan(void *kernel, size_t kernsz);
*
* @param kernel pointer to the kernel
* @param kernsz size of the kernel
* @param kernel_elf pointer to the ELF object to initialize if loading as an
* ELF.
* @param mb pointer to the multiboot context
* @return enum LOAD_TYPE
*/
enum LOAD_TYPE
multiboot_load_type (void* kernel, size_t kernsz, Elf **kernel_elf,
struct multiboot *mb);
multiboot_load_type (void* kernel, size_t kernsz, struct multiboot *mb);

/**
* @brief Attempt to load a file as an a.out object.
Expand All @@ -219,11 +218,11 @@ multiboot_load_aout(void* kernel, size_t kernsz, struct multiboot *mb);
*
* @param kernel pointer to the kernel
* @param kernsz size of the kernel
* @param kernel_elf kernel ELF object
* @param mb pointer to the multiboot context
* @return uint32_t 0 on success, error code on failure.
*/
uint32_t
multiboot_load_elf(void *kernel, size_t kernsz, Elf *kernel_elf);
multiboot_load_elf(void *kernel, size_t kernsz, struct multiboot *mb);

/**
* @brief Load a kernel into guest memory.
Expand Down
16 changes: 6 additions & 10 deletions tests/test-multiboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,15 @@ ATF_TC_BODY(loadtype, tc)
void *kernel = MB_TESTDATA_START(mmap);
size_t kernsz = MB_TESTDATA_SIZE(mmap);
enum LOAD_TYPE type;
Elf *kernelf;

mb = mb_scan(kernel, kernsz);

type = multiboot_load_type(kernel, kernsz, &kernelf, mb);
type = multiboot_load_type(kernel, kernsz, mb);
ATF_CHECK_EQ_MSG(type, LOAD_ELF, "mmap test kernel not loaded as ELF");

ATF_CHECK(urandom = fopen("/dev/urandom", "r"));
ATF_CHECK_MSG(random_buffer = malloc(128*kiB), "could not allocate memory");
elf_end(kernelf);
elf_end(mb->kernel_elf);

/* Craft a valid multiboot header */
ATF_CHECK(fread(random_buffer, 128*kiB, 1, urandom));
Expand All @@ -179,11 +178,9 @@ ATF_TC_BODY(loadtype, tc)
ATF_CHECK_EQ_MSG(mb->header.mb.header, mbh,
"did not find crafted valid header");
mbh = NULL;
type = multiboot_load_type(random_buffer, 128*kiB,
&kernelf, mb);
type = multiboot_load_type(random_buffer, 128*kiB, mb);
ATF_CHECK_EQ_MSG(type, LOAD_AOUT,
"random test data not loaded as a.out kludge");
ATF_CHECK_EQ_MSG(NULL, kernelf, "ELF resources not freed");

free(random_buffer);
fclose(urandom);
Expand Down Expand Up @@ -293,19 +290,18 @@ ATF_TC_BODY(load_elf_direct, tc)
size_t highmem = 0;
void *kernel = MB_TESTDATA_START(mmap);
size_t kernsz = MB_TESTDATA_SIZE(mmap);
Elf *kernelf;

setmem(4*MiB, 0);
callbacks->getmem(callbacks_arg, &lowmem, &highmem);
init_allocator(lowmem, highmem);

mb = mb_scan(kernel, kernsz);
mbh = mb->header.mb.header;
multiboot_load_type(kernel, kernsz, &kernelf, mb);
error = multiboot_load_elf(kernel, kernsz, kernelf);
multiboot_load_type(kernel, kernsz, mb);
error = multiboot_load_elf(kernel, kernsz, mb);
ATF_CHECK_EQ_MSG(0, error, "multiboot_load_elf failed");

elf_end(kernelf);
elf_end(mb->kernel_elf);
}

ATF_TC(load_elf);
Expand Down

0 comments on commit 93e27b0

Please sign in to comment.