4 #include <cstdio> // for FILE *
7 class Multiboot_module;
12 static unsigned int phys_base;
13 static char const *errors[];
16 static FILE *open_module (const char * const path);
18 static char const * load_module (const char * const path,
19 Multiboot_module *module,
20 unsigned long int memsize,
25 static char const * copy_module (const char * const path,
26 Multiboot_module *module,
38 #include <sys/types.h>
40 #include "initcalls.h"
41 #include "mem_layout.h"
42 #include "multiboot.h"
44 unsigned int Loader::phys_base = Mem_layout::Physmem;
46 char const *Loader::errors[] FIASCO_INITDATA =
48 "Failed to open file",
49 "Failed to load ELF header",
50 "Failed ELF magic check",
51 "Failed ELF version check",
52 "Failed to load program header",
53 "Failed to fit program section into memory",
54 "Failed to load program section from file",
55 "Failed to read module, out of memory?"
60 Loader::open_module (const char * const path)
62 char magic[3]; // 2 + 1 for the terminating \0
65 if ((fp = fopen (path, "r")) == NULL)
68 fgets (magic, sizeof (magic), fp);
70 if (magic[0] == '\037' && magic[1] == '\213') // GZIP
78 snprintf (pipecmd, sizeof (pipecmd), "zcat %s", path);
80 if ((pp = popen (pipecmd, "r")) == NULL)
83 if ((fp = tmpfile()) == NULL)
89 while ((c = fgetc (pp)) != EOF)
100 IMPLEMENT FIASCO_INIT
102 Loader::load_module (const char * const path,
103 Multiboot_module *module,
104 unsigned long int memsize,
106 unsigned long *start,
115 if ((fp = open_module (path)) == NULL)
119 if (fread (&eh, sizeof (eh), 1, fp) != 1)
125 // Check if valid ELF magic, 32bit, little endian
126 if (memcmp(eh.e_ident, ELFMAG, 4) != 0 ||
127 eh.e_ident[EI_CLASS] != ELFCLASS32 ||
128 eh.e_ident[EI_DATA] != ELFDATA2LSB)
134 // Check if executable, i386 format, current ELF version
135 if (eh.e_type != ET_EXEC ||
136 eh.e_machine != EM_386 ||
137 eh.e_version != EV_CURRENT)
143 // Record entry point (initial EIP)
144 module->reserved = eh.e_entry;
148 // Load all program sections
149 for (i = 0, offset = eh.e_phoff; i < eh.e_phnum; i++) {
151 // Load Program Header
152 if (fseek (fp, offset, SEEK_SET) == -1 ||
153 fread (&ph, sizeof (ph), 1, fp) != 1)
159 offset += sizeof (ph);
161 // Only consider non-empty load-sections
162 if (ph.p_type != PT_LOAD || !ph.p_memsz)
165 // Check if section fits into memory
166 if (ph.p_paddr + ph.p_memsz > memsize)
172 // Load Section with non-zero filesize
173 if (ph.p_filesz && (fseek (fp, ph.p_offset, SEEK_SET) == -1 ||
174 fread ((void *)(phys_base + ph.p_paddr), ph.p_filesz, 1, fp) != 1))
180 // Zero-pad uninitialized data if filesize < memsize
181 if (ph.p_filesz < ph.p_memsz)
182 memset ((void *)(phys_base + ph.p_paddr + ph.p_filesz), 0,
183 ph.p_memsz - ph.p_filesz);
185 if (ph.p_paddr < *start)
187 if (ph.p_paddr + ph.p_memsz > *end)
188 *end = ph.p_paddr + ph.p_memsz;
192 printf ("Loading Module 0x"L4_PTR_FMT"-0x"L4_PTR_FMT" [%s]\n",
193 (Address)*start, (Address)*end, path);
199 IMPLEMENT FIASCO_INIT
201 Loader::copy_module (const char * const path,
202 Multiboot_module *module,
209 if ((fp = open_module (path)) == NULL)
212 if (fstat (fileno (fp), &s) == -1)
218 *load_addr -= s.st_size;
219 *load_addr &= Config::PAGE_MASK; // this may not be necessary
221 if (fread ((void *)(phys_base + *load_addr), s.st_size, 1, fp) != 1)
227 module->mod_start = *load_addr;
228 module->mod_end = *load_addr + s.st_size;
231 printf ("Copying Module 0x"L4_PTR_FMT"-0x"L4_PTR_FMT" [%s]\n",
232 (Address)module->mod_start, (Address)module->mod_end, path);