blob: d9df06764c2a8b70ef2f7576bce9aa64bd4a67d6 [file] [log] [blame]
// Multiboot interface support.
//
// Copyright (C) 2015 Vladimir Serbinenko <phcoder@gmail.com>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "config.h" // CONFIG_*
#include "malloc.h" // free
#include "output.h" // dprintf
#include "romfile.h" // romfile_add
#include "std/multiboot.h" // MULTIBOOT_*
#include "string.h" // memset
#include "util.h" // multiboot_init
struct mbfs_romfile_s {
struct romfile_s file;
void *data;
};
static int
extract_filename(char *dest, char *src, size_t lim)
{
char *ptr;
for (ptr = src; *ptr; ptr++) {
if (!(ptr == src || ptr[-1] == ' ' || ptr[-1] == '\t'))
continue;
/* memcmp stops early if it encounters \0 as it doesn't match name=. */
if (memcmp(ptr, "name=", 5) == 0) {
int i;
char *optr = dest;
for (i = 0, ptr += 5; *ptr && *ptr != ' ' && i < lim; i++) {
*optr++ = *ptr++;
}
*optr++ = '\0';
return 1;
}
}
return 0;
}
// Copy a file to memory
static int
mbfs_copyfile(struct romfile_s *file, void *dst, u32 maxlen)
{
struct mbfs_romfile_s *cfile;
cfile = container_of(file, struct mbfs_romfile_s, file);
u32 size = cfile->file.size;
void *src = cfile->data;
// Not compressed.
dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst);
if (size > maxlen) {
warn_noalloc();
return -1;
}
iomemcpy(dst, src, size);
return size;
}
u32 __VISIBLE entry_elf_eax, entry_elf_ebx;
void
multiboot_init(void)
{
struct multiboot_info *mbi;
if (!CONFIG_MULTIBOOT)
return;
dprintf(1, "multiboot: eax=%x, ebx=%x\n", entry_elf_eax, entry_elf_ebx);
if (entry_elf_eax != MULTIBOOT_BOOTLOADER_MAGIC)
return;
mbi = (void *)entry_elf_ebx;
dprintf(1, "mbptr=%p\n", mbi);
dprintf(1, "flags=0x%x, mods=0x%x, mods_c=%d\n", mbi->flags, mbi->mods_addr,
mbi->mods_count);
if (!(mbi->flags & MULTIBOOT_INFO_MODS))
return;
int i;
struct multiboot_mod_list *mod = (void *)mbi->mods_addr;
for (i = 0; i < mbi->mods_count; i++) {
struct mbfs_romfile_s *cfile;
u8 *copy;
u32 len;
if (!mod[i].cmdline)
continue;
len = mod[i].mod_end - mod[i].mod_start;
cfile = malloc_tmp(sizeof(*cfile));
if (!cfile) {
warn_noalloc();
return;
}
memset(cfile, 0, sizeof(*cfile));
dprintf(1, "module %s, size 0x%x\n", (char *)mod[i].cmdline, len);
if (!extract_filename(cfile->file.name, (char *)mod[i].cmdline,
sizeof(cfile->file.name))) {
free(cfile);
continue;
}
dprintf(1, "assigned file name <%s>\n", cfile->file.name);
cfile->file.size = len;
copy = malloc_tmp(len);
if (!copy) {
warn_noalloc();
free(cfile);
return;
}
memcpy(copy, (void *)mod[i].mod_start, len);
cfile->file.copy = mbfs_copyfile;
cfile->data = copy;
romfile_add(&cfile->file);
}
}