Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / board-js2x / llfw / stage2.c
1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * All rights reserved.
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
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12
13 #include <stdint.h>
14 #include <xvect.h>
15 #include <hw.h>
16 #include <stdio.h>
17 #include <romfs.h>
18 #include "memmap.h"
19 #include "stage2.h"
20 #include <termctrl.h>
21 #include "product.h"
22 #include "calculatecrc.h"
23 #include <cpu.h>
24 #include <libelf.h>
25 #include <string.h>
26
27 uint64_t uart;
28 uint64_t gVecNum;
29 uint8_t u4Flag;
30
31 uint64_t exception_stack_frame;
32
33 typedef void (*pInterruptFunc_t) (void);
34
35 pInterruptFunc_t vectorTable[0x2E << 1];
36
37 extern void proceedInterrupt(void);
38
39 /* Prototypes for functions in this file: */
40 void c_interrupt(uint64_t vecNum);
41 void set_exceptionVector(int num, void *func);
42 int io_getchar(char *ch);
43 void early_c_entry(uint64_t start_addr);
44
45
46 static void
47 exception_forward(void)
48 {
49         uint64_t val;
50
51         if (*(uint64_t *) XVECT_M_HANDLER) {
52                 proceedInterrupt();
53         }
54
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);
60
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);
65         while (1);
66 }
67
68 void
69 c_interrupt(uint64_t vecNum)
70 {
71         gVecNum = vecNum;
72         if (vectorTable[vecNum >> 7]) {
73                 vectorTable[vecNum >> 7] ();
74         } else {
75                 exception_forward();
76         }
77 }
78
79 void
80 set_exceptionVector(int num, void *func)
81 {
82         vectorTable[num >> 7] = (pInterruptFunc_t) func;
83 }
84
85 static void
86 io_init(void)
87 {
88         // read ID register: only if it is a PC87427, enable serial2
89         store8_ci(0xf400002e, 0x20);
90         if (load8_ci(0xf400002f) != 0xf2) {
91                 uart = 0xf40003f8;
92                 u4Flag = 0;
93         } else {
94                 uart = 0xf40002f8;
95                 u4Flag = 1;
96         }
97 }
98
99 int
100 io_getchar(char *ch)
101 {
102         int retVal = 0;
103         if ((load8_ci(uart + 5) & 0x01)) {
104                 *ch = load8_ci(uart);
105                 retVal = 1;
106         }
107         return retVal;
108 }
109
110
111 void copy_from_flash(uint64_t cnt, uint64_t src, uint64_t dest);
112
113 const uint32_t CrcTableHigh[16] = {
114         0x00000000, 0x4C11DB70, 0x9823B6E0, 0xD4326D90,
115         0x34867077, 0x7897AB07, 0xACA5C697, 0xE0B41DE7,
116         0x690CE0EE, 0x251D3B9E, 0xF12F560E, 0xBD3E8D7E,
117         0x5D8A9099, 0x119B4BE9, 0xC5A92679, 0x89B8FD09
118 };
119 const uint32_t CrcTableLow[16] = {
120         0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
121         0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
122         0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
123         0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
124 };
125
126 static unsigned long
127 check_flash_image(unsigned long rombase, unsigned long length,
128                   unsigned long start_crc)
129 {
130
131         uint32_t AccumCRC = start_crc;
132         char val;
133         uint32_t Temp;
134         while (length-- > 0) {
135                 val = load8_ci(rombase++);
136                 Temp = ((AccumCRC >> 24) ^ val) & 0x000000ff;
137                 AccumCRC <<= 8;
138                 AccumCRC ^= CrcTableHigh[Temp / 16];
139                 AccumCRC ^= CrcTableLow[Temp % 16];
140         }
141
142         return AccumCRC;
143 }
144
145 static void
146 load_file(uint64_t destAddr, char *name, uint64_t maxSize, uint64_t romfs_base)
147 {
148         uint64_t *src, *dest, cnt;
149         struct romfs_lookup_t fileInfo;
150         c_romfs_lookup(name, romfs_base, &fileInfo);
151         if (maxSize) {
152                 cnt = maxSize / 8;
153         } else {
154                 cnt = (fileInfo.size_data + 7) / 8;
155         }
156         dest = (uint64_t *) destAddr;
157         src = (uint64_t *) fileInfo.addr_data;
158         while (cnt--) {
159                 store64_ci((uint64_t) dest, *src);
160                 dest++;
161                 src++;
162         }
163         flush_cache((void *) destAddr, fileInfo.size_data);
164 }
165
166 /***************************************************************************
167  * Function: early_c_entry
168  * Input   : start_addr
169  *
170  * Description:
171  **************************************************************************/
172 void
173 early_c_entry(uint64_t start_addr)
174 {
175         struct romfs_lookup_t fileInfo;
176         uint32_t crc;
177         void (*ofw_start) (uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
178         uint64_t *boot_info;
179         exception_stack_frame = 0;
180         /* destination for the flash image; we copy it to RAM
181          * because from flash it is much too slow
182          * the flash is copied at 224MB - 4MB (max flash size)
183          * at 224MB starts SLOF
184          * at 256MB is the SLOF load-base */
185         uint64_t romfs_base = 0xe000000 - 0x400000;
186         // romfs header values
187         struct stH *header = (struct stH *) (start_addr + 0x28);
188         //since we cannot read the fh_magic directly from flash as a string, we need to copy it to memory
189         uint64_t magic_val = 0;
190         uint64_t startVal = 0;
191         uint64_t flashlen = 0;
192         unsigned long ofw_addr;
193
194         io_init();
195
196         flashlen = load64_ci((uint64_t) (&header->flashlen));
197
198         //copy fh_magic to magic_val since, we cannot use it as a string from flash
199         magic_val = load64_ci((uint64_t) (header->magic));
200
201         printf(" Check ROM  = ");
202         if (strncmp((char *) &magic_val, FLASHFS_MAGIC, 8) == 0) {
203                 // somehow, the first 8 bytes in flashfs are overwritten, if booting from drone...
204                 // so if we find "IMG1" in the first 4 bytes, we skip the CRC check...
205                 startVal = load64_ci((uint64_t) start_addr);
206                 if (strncmp((char *) &startVal, "IMG1", 4) == 0) {
207                         printf
208                             ("start from RAM detected, skipping CRC check!\r\n");
209                         // for romfs accesses (c_romfs_lookup) to work, we must fix the first uint64_t to the value we expect...
210                         store64_ci((uint64_t) start_addr, 0xd8);
211                 } else {
212                         //checking CRC in flash, we must use cache_inhibit
213                         // since the crc is included as the last 32 bits in the image, the resulting crc should be 0
214                         crc =
215                             check_flash_image((uint64_t) start_addr,
216                                               load64_ci((uint64_t)
217                                                         (&header->flashlen)),
218                                               0);
219                         if (crc == 0) {
220                                 printf("OK\r\n");
221                         } else {
222                                 printf("failed!\r\n");
223                                 while (1);
224                         }
225                 }
226         } else {
227                 printf
228                     ("failed (magic string is \"%.8s\" should be \"%.8s\")\r\n",
229                      (char *) &magic_val, FLASHFS_MAGIC);
230                 while (1);
231         }
232
233         printf(" Press \"s\" to enter Open Firmware.\r\n\r\n");
234
235         if ((start_addr > 0xF0000000) && u4Flag)
236                 u4memInit();
237
238         /* here we have real ram avail -> hopefully
239          * copy flash to ram; size is in 64 byte blocks */
240         flashlen /= 64;
241         /* align it a bit */
242         flashlen += 7;
243         flashlen &= ~7;
244         copy_from_flash(flashlen, start_addr, romfs_base);
245         /* takeover sometimes fails if the image running on the system
246          * has a different size; flushing the cache helps, because it is
247          * the right thing to do anyway */
248         flush_cache((void *) romfs_base, flashlen * 64);
249
250         c_romfs_lookup("bootinfo", romfs_base, &fileInfo);
251         boot_info = (uint64_t *) fileInfo.addr_data;
252         boot_info[1] = start_addr;
253         load_file(0x100, "xvect", 0, romfs_base);
254         load_file(SLAVELOOP_LOADBASE, "stageS", 0, romfs_base);
255         c_romfs_lookup("ofw_main", romfs_base, &fileInfo);
256
257         elf_load_file((void *) fileInfo.addr_data, &ofw_addr,
258                       NULL, flush_cache);
259         ofw_start =
260             (void (*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t))
261             &ofw_addr;
262         // re-enable the cursor
263         printf("%s%s", TERM_CTRL_RESET, TERM_CTRL_CRSON);
264         /* ePAPR 0.5
265          * r3 = R3 Effective address of the device tree image. Note: this
266          *      address must be 8-byte aligned in memory.
267          * r4 = implementation dependent
268          * r5 = 0
269          * r6 = 0x65504150 -- ePAPR magic value-to distinguish from
270          *      non-ePAPR-compliant firmware
271          * r7 = implementation dependent
272          */
273         asm volatile("isync; sync;" : : : "memory");
274         ofw_start(0, romfs_base, 0, 0, 0);
275         // never return
276 }