Foo
[wikipediardware.git] / bootloader / elf32.c
blobca402eec900a0c3d643418b27b2cbb7d5446d530
1 /*
2 e07 bootloader suite
3 Copyright (c) 2008 Daniel Mack <daniel@caiaq.de>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "regs.h"
20 #include "types.h"
21 #include "wikireader.h"
22 #include "misc.h"
23 #include <tff.h>
24 #include <string.h>
26 #define ET_EXEC 2
27 #define EM_C33 0x6b
29 #define ELFMAG0 0x7f
30 #define ELFMAG1 0x45
31 #define ELFMAG2 0x4c
32 #define ELFMAG3 0x46
34 typedef struct {
35 u8 e_ident[16]; /* ELF "magic number" */
36 u16 e_type; /* Identifies object file type */
37 u16 e_machine; /* Specifies required architecture */
38 u32 e_version; /* Identifies object file version */
39 u32 e_entry; /* Entry point virtual address */
40 u32 e_phoff; /* Program header table file offset */
41 u32 e_shoff; /* Section header table file offset */
42 u32 e_flags; /* Processor-specific flags */
43 u16 e_ehsize; /* ELF header size in bytes */
44 u16 e_phentsize; /* Program header table entry size */
45 u16 e_phnum; /* Program header table entry count */
46 u16 e_shentsize; /* Section header table entry size */
47 u16 e_shnum; /* Section header table entry count */
48 u16 e_shstrndx; /* Section header string table index */
49 } __attribute__((packed)) elf32_hdr;
51 typedef struct {
52 u32 sh_name; /* Section name, index in string tbl */
53 u32 sh_type; /* Type of section */
54 u32 sh_flags; /* Miscellaneous section attributes */
55 u32 sh_addr; /* Section virtual addr at execution */
56 u32 sh_offset; /* Section file offset */
57 u32 sh_size; /* Size of section in bytes */
58 u32 sh_link; /* Index of another section */
59 u32 sh_info; /* Additional section information */
60 u32 sh_addralign; /* Section alignment */
61 u32 sh_entsize; /* Entry size if section holds table */
62 } __attribute__((packed)) elf32_sec;
64 #define SHT_NULL 0 /* Section header table entry unused */
65 #define SHT_PROGBITS 1 /* Program specific (private) data */
66 #define SHT_SYMTAB 2 /* Link editing symbol table */
67 #define SHT_STRTAB 3 /* A string table */
68 #define SHT_RELA 4 /* Relocation entries with addends */
69 #define SHT_HASH 5 /* A symbol hash table */
70 #define SHT_DYNAMIC 6 /* Information for dynamic linking */
71 #define SHT_NOTE 7 /* Information that marks file */
72 #define SHT_NOBITS 8 /* Section occupies no space in file */
73 #define SHT_REL 9 /* Relocation entries, no addends */
74 #define SHT_SHLIB 10 /* Reserved, unspecified semantics */
75 #define SHT_DYNSYM 11 /* Dynamic linking symbol table */
78 int elf_exec(const u8 *filename)
80 elf32_hdr hdr;
81 elf32_sec sec;
82 u32 i, r;
83 void *exec;
84 FATFS fatfs;
85 FIL file;
86 int rc = 0;
88 if (f_mount(0, &fatfs) != FR_OK) {
89 rc = -1;
90 goto abort_umount;
93 if (f_open(&file, filename, FA_READ) != FR_OK) {
94 rc = -2;
95 goto abort_umount;
98 if (f_read(&file, &hdr, sizeof(hdr), &r) || r != sizeof(hdr)) {
99 rc = -3;
100 goto abort_close;
103 if (hdr.e_ident[0] != ELFMAG0 ||
104 hdr.e_ident[1] != ELFMAG1 ||
105 hdr.e_ident[2] != ELFMAG2 ||
106 hdr.e_ident[3] != ELFMAG3) {
107 /* print("invalid ELF magic\n"); */
108 rc = -4;
109 goto abort_close;
112 if (hdr.e_type != ET_EXEC) {
113 /* print("invalid ELF file type\n"); */
114 rc = -5;
115 goto abort_close;
118 if (hdr.e_machine != EM_C33) {
119 print("FAIL: machine\n");
120 rc = -6;
121 goto abort_close;
124 for (i = 0; i < hdr.e_shnum; i++) {
125 f_lseek(&file, hdr.e_shoff + sizeof(sec) * i);
126 if (f_read(&file, (u8 *) &sec, sizeof(sec), &r) || r != sizeof(sec))
127 continue;
129 switch (sec.sh_type) {
130 case SHT_PROGBITS:
131 f_lseek(&file, sec.sh_offset);
132 if (f_read(&file, (u8 *) sec.sh_addr, sec.sh_size, &r) || r != sec.sh_size) {
133 print("FAIL: load\n");
134 rc = -7;
135 goto abort_close;
136 } else {
137 print("PROG: ");
138 print_u32(sec.sh_addr);
139 print("\n");
141 break;
142 case SHT_NOBITS:
143 /* clean .bss sections */
144 memset((u8 *) sec.sh_addr, 0, sec.sh_size);
145 break;
146 default:
147 break;
151 f_close(&file);
152 print("EXEC: ");
153 print_u32(hdr.e_entry);
154 print("\n");
155 disable_card_power();
157 exec = (void *) hdr.e_entry;
158 ((void (*) (void)) exec) ();
159 goto abort_umount;
161 // make sure every thing is cleaned up if the load fails fail
162 abort_close:
163 f_close(&file);
164 abort_umount:
165 SDCARD_CS_HI();
166 disable_card_power();
167 return rc;