The Pedigree Project  0.1
system/boot/arm/main.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "Elf32.h"
21 
22 #include "autogen.h"
23 
24 #define LOAD_ADDR 0x00100000
25 extern int ByteSet(void *buf, int c, size_t len);
27 {
28  // If we are passed via grub, this information will be completely different
29  // to via the bootstrapper.
30  uint32_t flags;
31 
32  uint32_t mem_lower;
33  uint32_t mem_upper;
34 
35  uint32_t boot_device;
36 
37  uint32_t cmdline;
38 
39  uint32_t mods_count;
40  uint32_t mods_addr;
41 
42  /* ELF information */
43  uint32_t num;
44  uint32_t size;
45  uint32_t addr;
46  uint32_t shndx;
47 
48  uint32_t mmap_length;
49  uint32_t mmap_addr;
50 
51  uint32_t drives_length;
52  uint32_t drives_addr;
53 
54  uint32_t config_table;
55 
56  uint32_t boot_loader_name;
57 
58  uint32_t apm_table;
59 
60  uint32_t vbe_control_info;
61  uint32_t vbe_mode_info;
62  uint32_t vbe_mode;
63  uint32_t vbe_interface_seg;
64  uint32_t vbe_interface_off;
65  uint32_t vbe_interface_len;
66 } __attribute__((packed));
67 
68 inline void writeChar(char c)
69 {
70 #if defined(ARM_VERSATILE)
71  volatile char *p = reinterpret_cast<volatile char *>(0x101f1000);
72 #elif defined(ARM_INTEGRATOR)
73  volatile char *p = reinterpret_cast<volatile char *>(0x16000000);
74 #else
75 #error No valid ARM board!
76 #endif
77  *p = c;
78  asm volatile("" ::: "memory");
79 #ifndef SERIAL_IS_FILE
80  *p = 0;
81  asm volatile("" ::: "memory");
82 #endif
83 }
84 
85 inline void writeStr(const char *str)
86 {
87  char c;
88  while ((c = *str++))
89  writeChar(c);
90 }
91 
92 void writeHex(unsigned int n)
93 {
94  bool noZeroes = true;
95 
96  int i;
97  unsigned int tmp;
98  for (i = 28; i > 0; i -= 4)
99  {
100  tmp = (n >> i) & 0xF;
101  if (tmp == 0 && noZeroes)
102  {
103  continue;
104  }
105 
106  if (tmp >= 0xA)
107  {
108  noZeroes = false;
109  writeChar(tmp - 0xA + 'a');
110  }
111  else
112  {
113  noZeroes = false;
114  writeChar(tmp + '0');
115  }
116  }
117 
118  tmp = n & 0xF;
119  if (tmp >= 0xA)
120  {
121  writeChar(tmp - 0xA + 'a');
122  }
123  else
124  {
125  writeChar(tmp + '0');
126  }
127 }
128 
129 extern "C" void __start();
130 extern "C" void start()
131 {
132  // setup stack space (put the top of the stack at the bottom of this binary)
133  // and jump to the C++ entry
134  asm volatile("mov sp,$0x10000; mov ip, sp; b __start");
135  for (;;)
136  ;
137 }
138 
139 extern "C" void arm_swint_handler()
140 {
141  // what was the interrupt number?
142  uint32_t intnum = 1; //*((uint32_t*) (linkreg-4));
143  asm volatile("mov %0, lr" : "=r"(intnum));
144 
145  writeStr("Link register: ");
146  writeHex(intnum);
147  writeHex(0xdeadbeef);
148  writeChar(':');
149 
150  writeStr("\r\n");
151 
152  writeStr("softint\r\n");
153 
154  // do something
155  switch (intnum)
156  {
157  case 0x1:
158  writeStr("SWI01\r\n");
159  break;
160  }
161 
162  // asm volatile( "mov pc,r14_svc" );
163  // while( 1 );
164 }
165 
166 extern "C" void arm_instundef_handler()
167 {
168  writeStr("undefined instruction!\n");
169  while (1)
170  ;
171 }
172 
173 extern "C" void arm_fiq_handler()
174 {
175  writeStr("fiq\r\n");
176  while (1)
177  ;
178 }
179 
180 extern "C" void arm_irq_handler()
181 {
182  writeStr("irq\r\n");
183  while (1)
184  ;
185 }
186 
187 extern "C" void arm_reset_handler()
188 {
189  writeStr("reset\r\n");
190  while (1)
191  ;
192 }
193 
194 extern "C" void __arm_vector_table();
195 
196 uint32_t arm_get_cpsr()
197 {
198  uint32_t ret = 0;
199  asm volatile("msr cpsr,r0" : "=r"(ret));
200  return ret;
201 }
202 
203 void MemoryCopy(void *dest, const void *src, size_t len);
204 
205 extern "C" void __start()
206 {
207  // 8 entries in the table, plus the literal table holding offsets of C
208  // handlers
209  MemoryCopy((void *) 0, (void *) __arm_vector_table, (4 * 8) + (4 * 6));
210 
211  // TODO: remove this when happy with relevant code
212  writeStr("about to do software interrupt\r\n");
213  asm volatile("swi #1");
214  writeStr("swi done and returned\r\n");
215 
216  writeStr("Loading kernel...\r\n");
217 
218  Elf32 elf("kernel");
219  elf.load((uint8_t *) file, 0);
220  elf.writeSections();
221  int (*main)(struct BootstrapStruct_t *) =
222  (int (*)(struct BootstrapStruct_t *)) elf.getEntryPoint();
223 
224  struct BootstrapStruct_t bs;
225 
226  ByteSet(&bs, 0, sizeof(bs));
227  bs.shndx = elf.m_pHeader->shstrndx;
228  bs.num = elf.m_pHeader->shnum;
229  bs.size = elf.m_pHeader->shentsize;
230  bs.addr = (unsigned int) elf.m_pSectionHeaders;
231 
232  // For every section header, set .addr = .offset + m_pBuffer.
233  for (int i = 0; i < elf.m_pHeader->shnum; i++)
234  {
235  elf.m_pSectionHeaders[i].addr =
236  elf.m_pSectionHeaders[i].offset + (uint32_t) elf.m_pBuffer;
237  }
238 
239  writeStr("Kernel loaded, jumping to entry point...\r\n");
240 
241  main(&bs);
242 
243  writeStr("Kernel returned\r\n");
244 
245  while (1)
246  ;
247 }
Bootstrap structure passed to the kernel entry point.
uint32_t getEntryPoint()
uint8_t * m_pBuffer
Offset of the file in memory.
Definition: arm/Elf32.h:217
bool load(uint8_t *pBuffer, unsigned int nBufferLength)
bool writeSections()