1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <string.h>
15
16#include <types.h>
17#ifndef COREBOOT_V2
18#include <cpu.h>
19#endif
20
21#include "debug.h"
22
23#include <x86emu/x86emu.h>
24#include <x86emu/regs.h>
25#ifdef COREBOOT_V2
26#include "../x86emu/prim_ops.h"
27#else
28#include <x86emu/prim_ops.h>
29#endif
30
31#include "biosemu.h"
32#include "io.h"
33#include "mem.h"
34#include "interrupt.h"
35#include "device.h"
36#include "pmm.h"
37
38#ifdef COREBOOT_V2
39#include "compat/rtas.h"
40#else
41#include <rtas.h>
42#endif
43
44#include <device/device.h>
45
46static X86EMU_memFuncs my_mem_funcs = {
47 my_rdb, my_rdw, my_rdl,
48 my_wrb, my_wrw, my_wrl
49};
50
51static X86EMU_pioFuncs my_pio_funcs = {
52 my_inb, my_inw, my_inl,
53 my_outb, my_outw, my_outl
54};
55
56
57yabel_handleIntFunc yabel_intFuncArray[256];
58
59void dump(u8 * addr, u32 len);
60
61
62
63
64
65
66
67
68u32
69biosemu(u8 *biosmem, u32 biosmem_size, struct device * dev, unsigned long rom_addr)
70{
71 u8 *rom_image;
72 int i = 0;
73#ifdef DEBUG
74 debug_flags = 0;
75
76
77
78
79 debug_flags |= CONFIG_YABEL_DEBUG_FLAGS;
80#endif
81 if (biosmem_size < MIN_REQUIRED_VMEM_SIZE) {
82 printf("Error: Not enough virtual memory: %x, required: %x!\n",
83 biosmem_size, MIN_REQUIRED_VMEM_SIZE);
84 return -1;
85 }
86 if (biosemu_dev_init(dev) != 0) {
87 printf("Error initializing device!\n");
88 return -1;
89 }
90 if (biosemu_dev_check_exprom(rom_addr) != 0) {
91 printf("Error: Device Expansion ROM invalid!\n");
92 return -1;
93 }
94 rom_image = (u8 *) bios_device.img_addr;
95 DEBUG_PRINTF("executing rom_image from %p\n", rom_image);
96 DEBUG_PRINTF("biosmem at %p\n", biosmem);
97
98 DEBUG_PRINTF("Image Size: %d\n", bios_device.img_size);
99
100
101
102 memset(biosmem, 0xf4, biosmem_size);
103
104 M.mem_base = (long) biosmem;
105 M.mem_size = biosmem_size;
106 DEBUG_PRINTF("membase set: %08x, size: %08x\n", (int) M.mem_base,
107 (int) M.mem_size);
108
109
110
111
112 u8 *mem_img = biosmem + (OPTION_ROM_CODE_SEGMENT << 4);
113 u8 copy_count = 0;
114 u8 cmp_result = 0;
115 do {
116#if 0
117 set_ci();
118 memcpy(mem_img, rom_image, len);
119 clr_ci();
120#else
121
122 u8 c;
123 for (i = 0; i < bios_device.img_size; i++) {
124 set_ci();
125 c = *(rom_image + i);
126 if (c != *(rom_image + i)) {
127 clr_ci();
128 printf("Copy failed at: %x/%x\n", i,
129 bios_device.img_size);
130 printf("rom_image(%x): %x, mem_img(%x): %x\n",
131 i, *(rom_image + i), i, *(mem_img + i));
132 break;
133 }
134 clr_ci();
135 *(mem_img + i) = c;
136 }
137#endif
138 copy_count++;
139 set_ci();
140 cmp_result = memcmp(mem_img, rom_image, bios_device.img_size);
141 clr_ci();
142 }
143 while ((copy_count < 5) && (cmp_result != 0));
144 if (cmp_result != 0) {
145 printf
146 ("\nCopying Expansion ROM Image to Memory failed after %d retries! (%x)\n",
147 copy_count, cmp_result);
148 dump(rom_image, 0x20);
149 dump(mem_img, 0x20);
150 return 0;
151 }
152
153
154
155
156 my_wrl(0x10 * 4, 0xf000f065);
157 my_wrb(0x000ff065, 0xcf);
158
159 my_wrl(0x11 * 4, 0xf000f84d);
160 my_wrb(0x000ff84d, 0xcf);
161
162 my_wrl(0x12 * 4, 0xf000f841);
163 my_wrb(0x000ff841, 0xcf);
164
165 my_wrl(0x13 * 4, 0xf000ec59);
166 my_wrb(0x000fec59, 0xcf);
167
168 my_wrl(0x14 * 4, 0xf000e739);
169 my_wrb(0x000fe739, 0xcf);
170
171 my_wrl(0x15 * 4, 0xf000f859);
172 my_wrb(0x000ff859, 0xcf);
173
174 my_wrl(0x16 * 4, 0xf000e82e);
175 my_wrb(0x000fe82e, 0xcf);
176
177 my_wrl(0x17 * 4, 0xf000efd2);
178 my_wrb(0x000fefd2, 0xcf);
179
180 my_wrl(0x1a * 4, 0xf000fe6e);
181 my_wrb(0x000ffe6e, 0xcf);
182
183
184
185
186 memset(biosmem + 0x400, 0x0, 0x100);
187
188
189 my_wrw(0x413, biosmem_size / 1024);
190
191
192 my_wrw(0x40e, INITIAL_EBDA_SEGMENT);
193
194
195
196
197
198
199
200
201
202
203
204
205 memset(biosmem + (INITIAL_EBDA_SEGMENT << 4), 0, INITIAL_EBDA_SIZE);
206
207 my_wrw((INITIAL_EBDA_SEGMENT << 4) + 0x0, INITIAL_EBDA_SIZE / 1024);
208
209
210
211 char *date = "06/11/99";
212 for (i = 0; date[i]; i++)
213 my_wrb(0xffff5 + i, date[i]);
214
215 char *ident = "PCI_ISA";
216 for (i = 0; ident[i]; i++)
217 my_wrb(0xfffd9 + i, ident[i]);
218
219
220
221
222 my_wrb(0xFFFFE, 0xfc);
223
224
225 X86EMU_intrFuncs intrFuncs[256];
226 for (i = 0; i < 256; i++)
227 intrFuncs[i] = handleInterrupt;
228 X86EMU_setupIntrFuncs(intrFuncs);
229 X86EMU_setupPioFuncs(&my_pio_funcs);
230 X86EMU_setupMemFuncs(&my_mem_funcs);
231
232
233 u8 pmm_length = pmm_setup(BIOS_DATA_SEGMENT, 0x0);
234 if (pmm_length <= 0) {
235 printf ("\nYABEL: Warning: PMM Area could not be setup. PMM not available (%x)\n",
236 pmm_length);
237 return 0;
238 } else {
239 CHECK_DBG(DEBUG_PMM) {
240
241 pmm_test();
242
243 pmm_length = pmm_setup(BIOS_DATA_SEGMENT, 0x0);
244 }
245 }
246
247 M.x86.R_AH = bios_device.bus;
248 M.x86.R_AL = bios_device.devfn;
249 M.x86.R_DX = 0x80;
250 M.x86.R_EIP = 3;
251 M.x86.R_CS = OPTION_ROM_CODE_SEGMENT;
252
253
254 M.x86.R_SS = STACK_SEGMENT;
255 M.x86.R_SP = STACK_START_OFFSET;
256 M.x86.R_DS = DATA_SEGMENT;
257
258
259
260
261 push_word(0xf4f4);
262 push_word(M.x86.R_SS);
263 push_word(M.x86.R_SP + 2);
264
265 CHECK_DBG(DEBUG_TRACE_X86EMU) {
266 X86EMU_trace_on();
267 } else {
268#ifdef DEBUG
269 M.x86.debug |= DEBUG_SAVE_IP_CS_F;
270 M.x86.debug |= DEBUG_DECODE_F;
271 M.x86.debug |= DEBUG_DECODE_NOPRINT_F;
272#endif
273 }
274 CHECK_DBG(DEBUG_JMP) {
275 M.x86.debug |= DEBUG_TRACEJMP_F;
276 M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
277 M.x86.debug |= DEBUG_TRACECALL_F;
278 M.x86.debug |= DEBUG_TRACECALL_REGS_F;
279 }
280
281 DEBUG_PRINTF("Executing Initialization Vector...\n");
282 X86EMU_exec();
283 DEBUG_PRINTF("done\n");
284
285
286
287
288 DEBUG_PRINTF_CS_IP("Option ROM Exit Status: %04x\n", M.x86.R_AX);
289#ifdef DEBUG
290 DEBUG_PRINTF("Exit Status Decode:\n");
291 if (M.x86.R_AX & 0x100) {
292 DEBUG_PRINTF
293 (" IPL Device supporting INT 13h Block Device Format:\n");
294 switch (((M.x86.R_AX >> 4) & 0x3)) {
295 case 0:
296 DEBUG_PRINTF(" No IPL Device attached\n");
297 break;
298 case 1:
299 DEBUG_PRINTF(" IPL Device status unknown\n");
300 break;
301 case 2:
302 DEBUG_PRINTF(" IPL Device attached\n");
303 break;
304 case 3:
305 DEBUG_PRINTF(" IPL Device status RESERVED!!\n");
306 break;
307 }
308 }
309 if (M.x86.R_AX & 0x80) {
310 DEBUG_PRINTF
311 (" Output Device supporting INT 10h Character Output:\n");
312 switch (((M.x86.R_AX >> 4) & 0x3)) {
313 case 0:
314 DEBUG_PRINTF(" No Display Device attached\n");
315 break;
316 case 1:
317 DEBUG_PRINTF(" Display Device status unknown\n");
318 break;
319 case 2:
320 DEBUG_PRINTF(" Display Device attached\n");
321 break;
322 case 3:
323 DEBUG_PRINTF(" Display Device status RESERVED!!\n");
324 break;
325 }
326 }
327 if (M.x86.R_AX & 0x40) {
328 DEBUG_PRINTF
329 (" Input Device supporting INT 9h Character Input:\n");
330 switch (((M.x86.R_AX >> 4) & 0x3)) {
331 case 0:
332 DEBUG_PRINTF(" No Input Device attached\n");
333 break;
334 case 1:
335 DEBUG_PRINTF(" Input Device status unknown\n");
336 break;
337 case 2:
338 DEBUG_PRINTF(" Input Device attached\n");
339 break;
340 case 3:
341 DEBUG_PRINTF(" Input Device status RESERVED!!\n");
342 break;
343 }
344 }
345#endif
346
347
348
349
350
351 if ((pop_word() == 0xf4f4) && (M.x86.R_SS == STACK_SEGMENT)
352 && (M.x86.R_SP == STACK_START_OFFSET)) {
353 DEBUG_PRINTF("Stack is clean, initialization successfull!\n");
354 } else {
355 DEBUG_PRINTF
356 ("Stack unclean, initialization probably NOT COMPLETE!!\n");
357 DEBUG_PRINTF("SS:SP = %04x:%04x, expected: %04x:%04x\n",
358 M.x86.R_SS, M.x86.R_SP, STACK_SEGMENT,
359 STACK_START_OFFSET);
360 }
361
362
363
364
365
366
367 return 0;
368}
369