]> Joshua Wise's Git repositories - netwatch.git/blob - grubload/loader.c
2b86a75d80f21c7542530c9aba52dd5dfce793e8
[netwatch.git] / grubload / loader.c
1 /* loader.c
2  * ELF loading subroutines
3  * NetWatch multiboot loader
4  *
5  * Copyright (c) 2008 Jacob Potter and Joshua Wise.  All rights reserved.
6  * This program is free software; you can redistribute and/or modify it under
7  * the terms found in the file LICENSE in the root of this source tree. 
8  *
9  */
10
11 #include <elf.h>
12 #include <output.h>
13 #include <minilib.h>
14
15 static const unsigned char elf_ident[4] = { 0x7F, 'E', 'L', 'F' }; 
16
17 int load_elf (char * buf, int size) {
18
19         Elf32_Ehdr * elf_hdr = (Elf32_Ehdr *) buf;
20         Elf32_Shdr * elf_sec_hdrs = (Elf32_Shdr *) (buf + elf_hdr->e_shoff);
21
22         /* Sanity check on ELF file */
23         if (memcmp((void *)elf_hdr->e_ident, (void *)elf_ident, sizeof(elf_ident))) return -1;
24         if (elf_hdr->e_type != ET_EXEC) return -1;
25         if (elf_hdr->e_machine != EM_386) return -1;
26         if (elf_hdr->e_version != EV_CURRENT) return -1;
27         if (size < sizeof(Elf32_Ehdr)) return -1;
28         if (((char *)&elf_sec_hdrs[elf_hdr->e_shnum]) > (buf + size)) return -1;
29
30         char * string_table = buf + elf_sec_hdrs[elf_hdr->e_shstrndx].sh_offset;
31
32         if (string_table > (buf + size)) return -1;
33
34         int i;
35         for (i = 0; i < elf_hdr->e_shnum; i++) {
36
37                 if (elf_sec_hdrs[i].sh_name == SHN_UNDEF) {
38                         continue;
39                 }
40
41                 char * section_name = string_table + elf_sec_hdrs[i].sh_name;
42
43                 if ((elf_sec_hdrs[i].sh_type != SHT_PROGBITS) || !(elf_sec_hdrs[i].sh_flags & SHF_ALLOC)) {
44                         outputf("Skipping %s", section_name);
45                         continue;
46                 }
47
48                 outputf("Loading %s at %08x", section_name, elf_sec_hdrs[i].sh_addr);
49
50                 memcpy((void *)elf_sec_hdrs[i].sh_addr,
51                        buf + elf_sec_hdrs[i].sh_offset,
52                        elf_sec_hdrs[i].sh_size);
53         }
54
55         return 0;
56 }
This page took 0.023236 seconds and 4 git commands to generate.