1 /******************************************************************************
2 * Copyright (c) 2004, 2011 IBM Corporation
4 * This program and the accompanying materials
5 * are made available under the terms of the BSD License
6 * which accompanies this distribution, and is available at
7 * http://www.opensource.org/licenses/bsd-license.php
10 * IBM Corporation - initial implementation
11 *****************************************************************************/
22 #include "calculatecrc.h"
26 #include "../lib/libhvcall/libhvcall.h"
29 //#define DEBUG(fmt...) printf(fmt)
33 uint64_t exception_stack_frame;
35 typedef void (*pInterruptFunc_t) (void);
37 pInterruptFunc_t vectorTable[0x2E << 1];
39 extern void proceedInterrupt(void);
41 /* Prototypes for functions of this file */
42 void c_interrupt(uint64_t vecNum);
43 void set_exceptionVector(int num, void *func);
44 void early_c_entry(uint64_t start_addr, uint64_t fdt_addr);
47 static void exception_forward(void)
51 if (*(uint64_t *) XVECT_M_HANDLER) {
55 printf("\r\n exception %llx ", gVecNum);
56 asm volatile ("mfsrr0 %0":"=r" (val):);
57 printf("\r\nSRR0 = %08llx%08llx ", val >> 32, val);
58 asm volatile ("mfsrr1 %0":"=r" (val):);
59 printf(" SRR1 = %08llx%08llx ", val >> 32, val);
61 asm volatile ("mfsprg %0,2":"=r" (val):);
62 printf("\r\nSPRG2 = %08llx%08llx ", val >> 32, val);
63 asm volatile ("mfsprg %0,3":"=r" (val):);
64 printf(" SPRG3 = %08llx%08llx \r\n", val >> 32, val);
68 void c_interrupt(uint64_t vecNum)
71 if (vectorTable[vecNum >> 7]) {
72 vectorTable[vecNum >> 7] ();
78 void set_exceptionVector(int num, void *func)
80 vectorTable[num >> 7] = (pInterruptFunc_t) func;
83 static void load_file(uint64_t destAddr, char *name, uint64_t maxSize,
87 struct romfs_lookup_t fileInfo;
90 rc = c_romfs_lookup(name, romfs_base, &fileInfo);
92 printf("Cannot find romfs file %s\n", name);
95 DEBUG("Found romfs file %s\n", name);
99 cnt = fileInfo.size_data;
101 memcpy((void *)destAddr, (void *)fileInfo.addr_data, cnt);
102 flush_cache((void *) destAddr, fileInfo.size_data);
105 extern void print_version(void);
107 /***************************************************************************
108 * Function: early_c_entry
112 **************************************************************************/
113 void early_c_entry(uint64_t start_addr, uint64_t fdt_addr)
115 struct romfs_lookup_t fileInfo;
116 void (*ofw_start) (uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
118 uint64_t romfs_base, paflof_base;
119 // romfs header values
120 // struct stH *header = (struct stH *) (start_addr + 0x28);
121 // uint64_t flashlen = header->flashlen;
122 unsigned long ofw_addr[2];
124 extern char __executable_start;
128 * If we run on a broken environment, we need to patch our own sc 1
129 * calls to be able to trap hypercalls. This does not cover RTAS or
130 * any payload we will load yet.
132 if (patch_broken_sc1(&__executable_start, &__etext, NULL)) {
133 /* We are running in PR KVM on top of pHyp. Print all output
134 we missed to print so far again to fake identical behavior */
135 printf("\n\r\nSLOF");
140 puts("ERROR: Flatten device tree not available!");
143 /* Hack: Determine base for "ROM filesystem" in memory...
144 * QEMU loads the FDT at the top of the available RAM, so we place
145 * the ROMFS just underneath. */
146 romfs_base = (fdt_addr - 0x410000) & ~0xffffLL;
147 memcpy((char *)romfs_base, 0, 0x400000);
149 exception_stack_frame = 0;
151 printf(" Press \"s\" to enter Open Firmware.\r\n\r\n");
153 DEBUG(" [c_romfs_lookup at %p]\n", c_romfs_lookup);
154 rc = c_romfs_lookup("bootinfo", romfs_base, &fileInfo);
156 printf(" !!! roomfs lookup(bootinfo) = %d\n", rc);
157 boot_info = (uint64_t *) fileInfo.addr_data;
158 boot_info[1] = start_addr;
159 load_file(0x100, "xvect", 0, romfs_base);
160 rc = c_romfs_lookup("ofw_main", romfs_base, &fileInfo);
162 printf(" !!! roomfs lookup(bootinfo) = %d\n", rc);
164 DEBUG(" [ofw_main addr hdr 0x%lx]\n", fileInfo.addr_header);
165 DEBUG(" [ofw_main addr data 0x%lx]\n", fileInfo.addr_data);
166 DEBUG(" [ofw_main size data 0x%lx]\n", fileInfo.size_data);
167 DEBUG(" [ofw_main flags 0x%lx]\n", fileInfo.flags);
168 DEBUG(" [hdr: 0x%08lx 0x%08lx]\n [ 0x%08lx 0x%08lx]\n",
169 ((uint64_t *)fileInfo.addr_header)[0],
170 ((uint64_t *)fileInfo.addr_header)[1],
171 ((uint64_t *)fileInfo.addr_header)[2],
172 ((uint64_t *)fileInfo.addr_header)[3]);
174 /* Assume that paflof and SNK need ca. 31 MiB RAM right now.
175 * TODO: Use value from ELF file instead */
176 paflof_base = romfs_base - 0x1F00000 + 0x100;
177 if ((int64_t)paflof_base <= 0LL) {
178 puts("ERROR: Not enough memory for Open Firmware");
180 rc = elf_load_file_to_addr((void *)fileInfo.addr_data, (void*)paflof_base,
181 ofw_addr, NULL, flush_cache);
182 DEBUG(" [load_elf_file returned %d]\n", rc);
185 (void (*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t))
187 // re-enable the cursor
188 printf("%s%s", TERM_CTRL_RESET, TERM_CTRL_CRSON);
189 DEBUG(" [ofw_start=%p ofw_addr=0x%lx]\n", ofw_start, ofw_addr[0]);
190 ofw_addr[1] = ofw_addr[0];
191 /* Call the Open Firmware layer with ePAPR-style calling conventions:
192 * r3 = R3 Effective address of the device tree image. Note: this
193 * address must be 8-byte aligned in memory.
194 * r4 = implementation dependent, we use it for ROMFS base address
196 * r6 = 0x65504150 -- ePAPR magic value-to distinguish from
197 * non-ePAPR-compliant firmware
198 * r7 = size of Initially Mapped Area
199 * (right now we assume everything from 0 to the FDT is the IMA)
201 asm volatile("isync; sync;" : : : "memory");
202 ofw_start(fdt_addr, romfs_base, 0, 0x65504150, fdt_addr);
203 asm volatile("isync; sync;" : : : "memory");