]> git.ipfire.org Git - u-boot.git/blame - board/MAI/bios_emulator/scitech/src/biosemu/biosemu.c
* Code cleanup:
[u-boot.git] / board / MAI / bios_emulator / scitech / src / biosemu / biosemu.c
CommitLineData
c7de829c
WD
1/****************************************************************************
2*
3* BIOS emulator and interface
4* to Realmode X86 Emulator Library
5*
6* Copyright (C) 1996-1999 SciTech Software, Inc.
7*
8* ========================================================================
9*
10* Permission to use, copy, modify, distribute, and sell this software and
11* its documentation for any purpose is hereby granted without fee,
12* provided that the above copyright notice appear in all copies and that
13* both that copyright notice and this permission notice appear in
14* supporting documentation, and that the name of the authors not be used
15* in advertising or publicity pertaining to distribution of the software
16* without specific, written prior permission. The authors makes no
17* representations about the suitability of this software for any purpose.
18* It is provided "as is" without express or implied warranty.
19*
20* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
21* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
22* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
23* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
24* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
25* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
26* PERFORMANCE OF THIS SOFTWARE.
27*
28* ========================================================================
29*
30* Language: ANSI C
31* Environment: Any
32* Developer: Kendall Bennett
33*
34* Description: Module implementing the system specific functions. This
35* module is always compiled and linked in the OS depedent
36* libraries, and never in a binary portable driver.
37*
38****************************************************************************/
39
40#include "biosemui.h"
41#include <string.h>
42#include <stdlib.h>
43
44/*------------------------- Global Variables ------------------------------*/
45
46BE_sysEnv _BE_env;
47#ifdef __DRIVER__
48PM_imports _VARAPI _PM_imports;
49#endif
50static X86EMU_memFuncs _BE_mem = {
51 BE_rdb,
52 BE_rdw,
53 BE_rdl,
54 BE_wrb,
55 BE_wrw,
56 BE_wrl,
57 };
58#ifdef DEBUG
59static X86EMU_pioFuncs _BE_pio = {
60 BE_inb,
61 BE_inw,
62 BE_inl,
63 BE_outb,
64 BE_outw,
65 BE_outl,
66 };
67#else
68static X86EMU_pioFuncs _BE_pio = {
69 (void*)PM_inpb,
70 (void*)PM_inpw,
71 (void*)PM_inpd,
72 (void*)PM_outpb,
73 (void*)PM_outpw,
74 (void*)PM_outpd,
75 };
76#endif
77
78/*-------------------------- Implementation -------------------------------*/
79
80#define OFF(addr) (u16)(((addr) >> 0) & 0xffff)
81#define SEG(addr) (u16)(((addr) >> 4) & 0xf000)
82
83/****************************************************************************
84PARAMETERS:
85debugFlags - Flags to enable debugging options (debug builds only)
86memSize - Amount of memory to allocate for real mode machine
87info - Pointer to default VGA device information
88
89REMARKS:
90This functions initialises the BElib, and uses the passed in
91BIOS image as the BIOS that is used and emulated at 0xC0000.
92****************************************************************************/
93ibool PMAPI BE_init(
94 u32 debugFlags,
95 int memSize,
96 BE_VGAInfo *info)
97{
98#ifndef __DRIVER__
99 PM_init();
100#endif
101 memset(&M,0,sizeof(M));
102 if (memSize < 20480)
8bde7f77 103 PM_fatalError("Emulator requires at least 20Kb of memory!\n");
c7de829c 104 if ((M.mem_base = (unsigned long)malloc(memSize)) == NULL)
8bde7f77 105 PM_fatalError("Out of memory!");
c7de829c
WD
106 M.mem_size = memSize;
107 _BE_env.busmem_base = (ulong)PM_mapPhysicalAddr(0xA0000,0x5FFFF,true);
108 M.x86.debug = debugFlags;
109 _BE_bios_init((u32*)info->LowMem);
110 X86EMU_setupMemFuncs(&_BE_mem);
111 X86EMU_setupPioFuncs(&_BE_pio);
112 BE_setVGA(info);
113 return true;
114}
115
116/****************************************************************************
117PARAMETERS:
118debugFlags - Flags to enable debugging options (debug builds only)
119
120REMARKS:
121This function allows the application to enable logging and debug flags
122on a function call basis, so we can specifically enable logging only
123for specific functions that are causing problems in debug mode.
124****************************************************************************/
125void PMAPI BE_setDebugFlags(
126 u32 debugFlags)
127{
128 M.x86.debug = debugFlags;
129}
130
131/****************************************************************************
132PARAMETERS:
133info - Pointer to VGA device information to make current
134
135REMARKS:
136This function sets the VGA BIOS functions in the emulator to point to the
137specific VGA BIOS in use. This includes swapping the BIOS interrupt
138vectors, BIOS image and BIOS data area to the new BIOS. This allows the
139real mode BIOS to be swapped without resetting the entire emulator.
140****************************************************************************/
141void PMAPI BE_setVGA(
142 BE_VGAInfo *info)
143{
144 _BE_env.vgaInfo.pciInfo = info->pciInfo;
145 _BE_env.vgaInfo.BIOSImage = info->BIOSImage;
146 if (info->BIOSImage) {
8bde7f77
WD
147 _BE_env.biosmem_base = (ulong)info->BIOSImage;
148 _BE_env.biosmem_limit = 0xC0000 + info->BIOSImageLen-1;
149 }
c7de829c 150 else {
8bde7f77
WD
151 _BE_env.biosmem_base = _BE_env.busmem_base + 0x20000;
152 _BE_env.biosmem_limit = 0xC7FFF;
153 }
c7de829c 154 if (*((u32*)info->LowMem) == 0)
8bde7f77 155 _BE_bios_init((u32*)info->LowMem);
c7de829c
WD
156 memcpy((u8*)M.mem_base,info->LowMem,sizeof(info->LowMem));
157}
158
159/****************************************************************************
160PARAMETERS:
161info - Pointer to VGA device information to retrieve current
162
163REMARKS:
164This function returns the VGA BIOS functions currently active in the
165emulator, so they can be restored at a later date.
166****************************************************************************/
167void PMAPI BE_getVGA(
168 BE_VGAInfo *info)
169{
170 info->pciInfo = _BE_env.vgaInfo.pciInfo;
171 info->BIOSImage = _BE_env.vgaInfo.BIOSImage;
172 memcpy(info->LowMem,(u8*)M.mem_base,sizeof(info->LowMem));
173}
174
175/****************************************************************************
176PARAMETERS:
177r_seg - Segment for pointer to convert
178r_off - Offset for pointer to convert
179
180REMARKS:
181This function maps a real mode pointer in the emulator memory to a protected
182mode pointer that can be used to directly access the memory.
183
184NOTE: The memory is *always* in little endian format, son on non-x86
8bde7f77
WD
185 systems you will need to do endian translations to access this
186 memory.
c7de829c
WD
187****************************************************************************/
188void * PMAPI BE_mapRealPointer(
189 uint r_seg,
190 uint r_off)
191{
192 u32 addr = ((u32)r_seg << 4) + r_off;
193
194 if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
8bde7f77
WD
195 return (void*)(_BE_env.biosmem_base + addr - 0xC0000);
196 }
c7de829c 197 else if (addr >= 0xA0000 && addr <= 0xFFFFF) {
8bde7f77
WD
198 return (void*)(_BE_env.busmem_base + addr - 0xA0000);
199 }
c7de829c
WD
200 return (void*)(M.mem_base + addr);
201}
202
203/****************************************************************************
204PARAMETERS:
205len - Return the length of the VESA buffer
206rseg - Place to store VESA buffer segment
207roff - Place to store VESA buffer offset
208
209REMARKS:
210This function returns the address of the VESA transfer buffer in real
211mode emulator memory. The VESA transfer buffer is always 1024 bytes long,
212and located at 15Kb into the start of the real mode memory (16Kb is where
213we put the real mode code we execute for issuing interrupts).
214
215NOTE: The memory is *always* in little endian format, son on non-x86
8bde7f77
WD
216 systems you will need to do endian translations to access this
217 memory.
c7de829c
WD
218****************************************************************************/
219void * PMAPI BE_getVESABuf(
220 uint *len,
221 uint *rseg,
222 uint *roff)
223{
224 *len = 1024;
225 *rseg = SEG(0x03C00);
226 *roff = OFF(0x03C00);
227 return (void*)(M.mem_base + ((u32)*rseg << 4) + *roff);
228}
229
230/****************************************************************************
231REMARKS:
232Cleans up and exits the emulator.
233****************************************************************************/
234void PMAPI BE_exit(void)
235{
236 free((void*)M.mem_base);
237 PM_freePhysicalAddr((void*)_BE_env.busmem_base,0x5FFFF);
238}
239
240/****************************************************************************
241PARAMETERS:
242seg - Segment of code to call
243off - Offset of code to call
244regs - Real mode registers to load
245sregs - Real mode segment registers to load
246
247REMARKS:
248This functions calls a real mode far function at the specified address,
249and loads all the x86 registers from the passed in registers structure.
250On exit the registers returned from the call are returned in the same
251structures.
252****************************************************************************/
253void PMAPI BE_callRealMode(
254 uint seg,
255 uint off,
256 RMREGS *regs,
257 RMSREGS *sregs)
258{
259 M.x86.R_EAX = regs->e.eax;
260 M.x86.R_EBX = regs->e.ebx;
261 M.x86.R_ECX = regs->e.ecx;
262 M.x86.R_EDX = regs->e.edx;
263 M.x86.R_ESI = regs->e.esi;
264 M.x86.R_EDI = regs->e.edi;
265 M.x86.R_DS = sregs->ds;
266 M.x86.R_ES = sregs->es;
267 M.x86.R_FS = sregs->fs;
268 M.x86.R_GS = sregs->gs;
269 M.x86.R_CS = (u16)seg;
270 M.x86.R_IP = (u16)off;
271 M.x86.R_SS = SEG(M.mem_size - 1);
272 M.x86.R_SP = OFF(M.mem_size - 1);
273 X86EMU_exec();
274 regs->e.cflag = M.x86.R_EFLG & F_CF;
275 regs->e.eax = M.x86.R_EAX;
276 regs->e.ebx = M.x86.R_EBX;
277 regs->e.ecx = M.x86.R_ECX;
278 regs->e.edx = M.x86.R_EDX;
279 regs->e.esi = M.x86.R_ESI;
280 regs->e.edi = M.x86.R_EDI;
281 sregs->ds = M.x86.R_DS;
282 sregs->es = M.x86.R_ES;
283 sregs->fs = M.x86.R_FS;
284 sregs->gs = M.x86.R_GS;
285}
286
287/****************************************************************************
288PARAMETERS:
289intno - Interrupt number to execute
290in - Real mode registers to load
291out - Place to store resulting real mode registers
292
293REMARKS:
294This functions calls a real mode interrupt function at the specified address,
295and loads all the x86 registers from the passed in registers structure.
296On exit the registers returned from the call are returned in out stucture.
297****************************************************************************/
298int PMAPI BE_int86(
299 int intno,
300 RMREGS *in,
301 RMREGS *out)
302{
303 M.x86.R_EAX = in->e.eax;
304 M.x86.R_EBX = in->e.ebx;
305 M.x86.R_ECX = in->e.ecx;
306 M.x86.R_EDX = in->e.edx;
307 M.x86.R_ESI = in->e.esi;
308 M.x86.R_EDI = in->e.edi;
309 ((u8*)M.mem_base)[0x4000] = 0xCD;
310 ((u8*)M.mem_base)[0x4001] = (u8)intno;
311 ((u8*)M.mem_base)[0x4002] = 0xC3;
312 M.x86.R_CS = SEG(0x04000);
313 M.x86.R_IP = OFF(0x04000);
314 M.x86.R_SS = SEG(M.mem_size - 1);
315 M.x86.R_SP = OFF(M.mem_size - 1);
316 X86EMU_exec();
317 out->e.cflag = M.x86.R_EFLG & F_CF;
318 out->e.eax = M.x86.R_EAX;
319 out->e.ebx = M.x86.R_EBX;
320 out->e.ecx = M.x86.R_ECX;
321 out->e.edx = M.x86.R_EDX;
322 out->e.esi = M.x86.R_ESI;
323 out->e.edi = M.x86.R_EDI;
324 return out->x.ax;
325}
326
327/****************************************************************************
328PARAMETERS:
329intno - Interrupt number to execute
330in - Real mode registers to load
331out - Place to store resulting real mode registers
332sregs - Real mode segment registers to load
333
334REMARKS:
335This functions calls a real mode interrupt function at the specified address,
336and loads all the x86 registers from the passed in registers structure.
337On exit the registers returned from the call are returned in out stucture.
338****************************************************************************/
339int PMAPI BE_int86x(
340 int intno,
341 RMREGS *in,
342 RMREGS *out,
343 RMSREGS *sregs)
344{
345 M.x86.R_EAX = in->e.eax;
346 M.x86.R_EBX = in->e.ebx;
347 M.x86.R_ECX = in->e.ecx;
348 M.x86.R_EDX = in->e.edx;
349 M.x86.R_ESI = in->e.esi;
350 M.x86.R_EDI = in->e.edi;
351 M.x86.R_DS = sregs->ds;
352 M.x86.R_ES = sregs->es;
353 M.x86.R_FS = sregs->fs;
354 M.x86.R_GS = sregs->gs;
355 ((u8*)M.mem_base)[0x4000] = 0xCD;
356 ((u8*)M.mem_base)[0x4001] = (u8)intno;
357 ((u8*)M.mem_base)[0x4002] = 0xC3;
358 M.x86.R_CS = SEG(0x04000);
359 M.x86.R_IP = OFF(0x04000);
360 M.x86.R_SS = SEG(M.mem_size - 1);
361 M.x86.R_SP = OFF(M.mem_size - 1);
362 X86EMU_exec();
363 out->e.cflag = M.x86.R_EFLG & F_CF;
364 out->e.eax = M.x86.R_EAX;
365 out->e.ebx = M.x86.R_EBX;
366 out->e.ecx = M.x86.R_ECX;
367 out->e.edx = M.x86.R_EDX;
368 out->e.esi = M.x86.R_ESI;
369 out->e.edi = M.x86.R_EDI;
370 sregs->ds = M.x86.R_DS;
371 sregs->es = M.x86.R_ES;
372 sregs->fs = M.x86.R_FS;
373 sregs->gs = M.x86.R_GS;
374 return out->x.ax;
375}
376
377#ifdef __DRIVER__
378
379/****************************************************************************
380REMARKS:
381Empty log function for binary portable DLL. The BPD is compiled without
382debug information, so very little is logged anyway so it is simpler this
383way.
384****************************************************************************/
385void printk(const char *msg, ...)
386{
387}
388
389/****************************************************************************
390REMARKS:
391Fatal error handler called when a non-imported function is called by the
392driver. We leave this to a runtime error so that older applications and
393shell drivers will work with newer bpd drivers provided no newer functions
394are required by the driver itself. If they are, the application or shell
395driver needs to be recompiled.
396****************************************************************************/
397static void _PM_fatalErrorHandler(void)
398{
399 PM_fatalError("Unsupported PM_imports import function called! Please re-compile!\n");
400}
401
402/****************************************************************************
403PARAMETERS:
404beImp - BE library imports
405beImp - Generic emulator imports
406
407RETURNS:
408Pointer to exported function list
409
410REMARKS:
411This function initialises the BIOS emulator library and returns the list of
412loader library exported functions.
413{secret}
414****************************************************************************/
415BE_exports * _CEXPORT BE_initLibrary(
416 PM_imports *pmImp)
417{
418 static BE_exports _BE_exports = {
8bde7f77
WD
419 sizeof(BE_exports),
420 BE_init,
421 BE_setVGA,
422 BE_getVGA,
423 BE_mapRealPointer,
424 BE_getVESABuf,
425 BE_callRealMode,
426 BE_int86,
427 BE_int86x,
428 NULL,
429 BE_exit,
430 };
c7de829c
WD
431 int i,max;
432 ulong *p;
433
8bde7f77
WD
434 /* Initialize all default imports to point to fatal error handler */
435 /* for upwards compatibility. */
c7de829c
WD
436 max = sizeof(_PM_imports)/sizeof(BE_initLibrary_t);
437 for (i = 0,p = (ulong*)&_PM_imports; i < max; i++)
8bde7f77 438 *p++ = (ulong)_PM_fatalErrorHandler;
c7de829c 439
8bde7f77 440 /* Now copy all our imported functions */
c7de829c
WD
441 memcpy(&_PM_imports,pmImp,MIN(sizeof(_PM_imports),pmImp->dwSize));
442 return &_BE_exports;
443}
444
445#endif /* __DRIVER__ */