1 // Multiboot interface support.
2 //
3 // Copyright (C) 2015 Vladimir Serbinenko <phcoder@gmail.com>
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6
7 #include "config.h" // CONFIG_*
8 #include "malloc.h" // free
9 #include "output.h" // dprintf
10 #include "romfile.h" // romfile_add
11 #include "std/multiboot.h" // MULTIBOOT_*
12 #include "string.h" // memset
13 #include "util.h" // multiboot_init
14
15 struct mbfs_romfile_s {
16 struct romfile_s file;
17 void *data;
18 };
19
20 static int
extract_filename(char * dest,char * src,size_t lim)21 extract_filename(char *dest, char *src, size_t lim)
22 {
23 char *ptr;
24 for (ptr = src; *ptr; ptr++) {
25 if (!(ptr == src || ptr[-1] == ' ' || ptr[-1] == '\t'))
26 continue;
27 /* memcmp stops early if it encounters \0 as it doesn't match name=. */
28 if (memcmp(ptr, "name=", 5) == 0) {
29 int i;
30 char *optr = dest;
31 for (i = 0, ptr += 5; *ptr && *ptr != ' ' && i < lim; i++) {
32 *optr++ = *ptr++;
33 }
34 *optr++ = '\0';
35 return 1;
36 }
37 }
38 return 0;
39 }
40
41 // Copy a file to memory
42 static int
mbfs_copyfile(struct romfile_s * file,void * dst,u32 maxlen)43 mbfs_copyfile(struct romfile_s *file, void *dst, u32 maxlen)
44 {
45 struct mbfs_romfile_s *cfile;
46 cfile = container_of(file, struct mbfs_romfile_s, file);
47 u32 size = cfile->file.size;
48 void *src = cfile->data;
49
50 // Not compressed.
51 dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst);
52 if (size > maxlen) {
53 warn_noalloc();
54 return -1;
55 }
56 iomemcpy(dst, src, size);
57 return size;
58 }
59
60 u32 __VISIBLE entry_elf_eax, entry_elf_ebx;
61
62 void
multiboot_init(void)63 multiboot_init(void)
64 {
65 struct multiboot_info *mbi;
66 if (!CONFIG_MULTIBOOT)
67 return;
68 dprintf(1, "multiboot: eax=%x, ebx=%x\n", entry_elf_eax, entry_elf_ebx);
69 if (entry_elf_eax != MULTIBOOT_BOOTLOADER_MAGIC)
70 return;
71 mbi = (void *)entry_elf_ebx;
72 dprintf(1, "mbptr=%p\n", mbi);
73 dprintf(1, "flags=0x%x, mods=0x%x, mods_c=%d\n", mbi->flags, mbi->mods_addr,
74 mbi->mods_count);
75 if (!(mbi->flags & MULTIBOOT_INFO_MODS))
76 return;
77 int i;
78 struct multiboot_mod_list *mod = (void *)mbi->mods_addr;
79 for (i = 0; i < mbi->mods_count; i++) {
80 struct mbfs_romfile_s *cfile;
81 u8 *copy;
82 u32 len;
83 if (!mod[i].cmdline)
84 continue;
85 len = mod[i].mod_end - mod[i].mod_start;
86 cfile = malloc_tmp(sizeof(*cfile));
87 if (!cfile) {
88 warn_noalloc();
89 return;
90 }
91 memset(cfile, 0, sizeof(*cfile));
92 dprintf(1, "module %s, size 0x%x\n", (char *)mod[i].cmdline, len);
93 if (!extract_filename(cfile->file.name, (char *)mod[i].cmdline,
94 sizeof(cfile->file.name))) {
95 free(cfile);
96 continue;
97 }
98 dprintf(1, "assigned file name <%s>\n", cfile->file.name);
99 cfile->file.size = len;
100 copy = malloc_tmp(len);
101 if (!copy) {
102 warn_noalloc();
103 free(cfile);
104 return;
105 }
106 memcpy(copy, (void *)mod[i].mod_start, len);
107 cfile->file.copy = mbfs_copyfile;
108 cfile->data = copy;
109 romfile_add(&cfile->file);
110 }
111 }
112