]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/MAI/bios_emulator/scitech/src/biosemu/biosemu.c
* Patch by Thomas Frieden, 13 Nov 2002:
[karo-tx-uboot.git] / board / MAI / bios_emulator / scitech / src / biosemu / biosemu.c
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
46 BE_sysEnv           _BE_env;
47 #ifdef  __DRIVER__
48 PM_imports  _VARAPI _PM_imports;
49 #endif
50 static 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
59 static 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
68 static 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 /****************************************************************************
84 PARAMETERS:
85 debugFlags  - Flags to enable debugging options (debug builds only)
86 memSize     - Amount of memory to allocate for real mode machine
87 info        - Pointer to default VGA device information
88
89 REMARKS:
90 This functions initialises the BElib, and uses the passed in
91 BIOS image as the BIOS that is used and emulated at 0xC0000.
92 ****************************************************************************/
93 ibool 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)
103         PM_fatalError("Emulator requires at least 20Kb of memory!\n");
104     if ((M.mem_base = (unsigned long)malloc(memSize)) == NULL)
105         PM_fatalError("Out of memory!");
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 /****************************************************************************
117 PARAMETERS:
118 debugFlags  - Flags to enable debugging options (debug builds only)
119
120 REMARKS:
121 This function allows the application to enable logging and debug flags
122 on a function call basis, so we can specifically enable logging only
123 for specific functions that are causing problems in debug mode.
124 ****************************************************************************/
125 void PMAPI BE_setDebugFlags(
126     u32 debugFlags)
127 {
128     M.x86.debug = debugFlags;
129 }
130
131 /****************************************************************************
132 PARAMETERS:
133 info        - Pointer to VGA device information to make current
134
135 REMARKS:
136 This function sets the VGA BIOS functions in the emulator to point to the
137 specific VGA BIOS in use. This includes swapping the BIOS interrupt
138 vectors, BIOS image and BIOS data area to the new BIOS. This allows the
139 real mode BIOS to be swapped without resetting the entire emulator.
140 ****************************************************************************/
141 void 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) {
147         _BE_env.biosmem_base = (ulong)info->BIOSImage;
148         _BE_env.biosmem_limit = 0xC0000 + info->BIOSImageLen-1;
149         }
150     else {
151         _BE_env.biosmem_base = _BE_env.busmem_base + 0x20000;
152         _BE_env.biosmem_limit = 0xC7FFF;
153         }
154     if (*((u32*)info->LowMem) == 0)
155         _BE_bios_init((u32*)info->LowMem);
156     memcpy((u8*)M.mem_base,info->LowMem,sizeof(info->LowMem));
157 }
158
159 /****************************************************************************
160 PARAMETERS:
161 info        - Pointer to VGA device information to retrieve current
162
163 REMARKS:
164 This function returns the VGA BIOS functions currently active in the
165 emulator, so they can be restored at a later date.
166 ****************************************************************************/
167 void 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 /****************************************************************************
176 PARAMETERS:
177 r_seg   - Segment for pointer to convert
178 r_off   - Offset for pointer to convert
179
180 REMARKS:
181 This function maps a real mode pointer in the emulator memory to a protected
182 mode pointer that can be used to directly access the memory.
183
184 NOTE:   The memory is *always* in little endian format, son on non-x86
185         systems you will need to do endian translations to access this
186         memory.
187 ****************************************************************************/
188 void * 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) {
195         return (void*)(_BE_env.biosmem_base + addr - 0xC0000);
196         }
197     else if (addr >= 0xA0000 && addr <= 0xFFFFF) {
198         return (void*)(_BE_env.busmem_base + addr - 0xA0000);
199         }
200     return (void*)(M.mem_base + addr);
201 }
202
203 /****************************************************************************
204 PARAMETERS:
205 len     - Return the length of the VESA buffer
206 rseg    - Place to store VESA buffer segment
207 roff    - Place to store VESA buffer offset
208
209 REMARKS:
210 This function returns the address of the VESA transfer buffer in real
211 mode emulator memory. The VESA transfer buffer is always 1024 bytes long,
212 and located at 15Kb into the start of the real mode memory (16Kb is where
213 we put the real mode code we execute for issuing interrupts).
214
215 NOTE:   The memory is *always* in little endian format, son on non-x86
216         systems you will need to do endian translations to access this
217         memory.
218 ****************************************************************************/
219 void * 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 /****************************************************************************
231 REMARKS:
232 Cleans up and exits the emulator.
233 ****************************************************************************/
234 void PMAPI BE_exit(void)
235 {
236     free((void*)M.mem_base);
237     PM_freePhysicalAddr((void*)_BE_env.busmem_base,0x5FFFF);
238 }
239
240 /****************************************************************************
241 PARAMETERS:
242 seg     - Segment of code to call
243 off     - Offset of code to call
244 regs    - Real mode registers to load
245 sregs   - Real mode segment registers to load
246
247 REMARKS:
248 This functions calls a real mode far function at the specified address,
249 and loads all the x86 registers from the passed in registers structure.
250 On exit the registers returned from the call are returned in the same
251 structures.
252 ****************************************************************************/
253 void 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 /****************************************************************************
288 PARAMETERS:
289 intno   - Interrupt number to execute
290 in      - Real mode registers to load
291 out     - Place to store resulting real mode registers
292
293 REMARKS:
294 This functions calls a real mode interrupt function at the specified address,
295 and loads all the x86 registers from the passed in registers structure.
296 On exit the registers returned from the call are returned in out stucture.
297 ****************************************************************************/
298 int 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 /****************************************************************************
328 PARAMETERS:
329 intno   - Interrupt number to execute
330 in      - Real mode registers to load
331 out     - Place to store resulting real mode registers
332 sregs   - Real mode segment registers to load
333
334 REMARKS:
335 This functions calls a real mode interrupt function at the specified address,
336 and loads all the x86 registers from the passed in registers structure.
337 On exit the registers returned from the call are returned in out stucture.
338 ****************************************************************************/
339 int 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 /****************************************************************************
380 REMARKS:
381 Empty log function for binary portable DLL. The BPD is compiled without
382 debug information, so very little is logged anyway so it is simpler this
383 way.
384 ****************************************************************************/
385 void printk(const char *msg, ...)
386 {
387 }
388
389 /****************************************************************************
390 REMARKS:
391 Fatal error handler called when a non-imported function is called by the
392 driver. We leave this to a runtime error so that older applications and
393 shell drivers will work with newer bpd drivers provided no newer functions
394 are required by the driver itself. If they are, the application or shell
395 driver needs to be recompiled.
396 ****************************************************************************/
397 static void _PM_fatalErrorHandler(void)
398 {
399     PM_fatalError("Unsupported PM_imports import function called! Please re-compile!\n");
400 }
401
402 /****************************************************************************
403 PARAMETERS:
404 beImp   - BE library imports
405 beImp   - Generic emulator imports
406
407 RETURNS:
408 Pointer to exported function list
409
410 REMARKS:
411 This function initialises the BIOS emulator library and returns the list of
412 loader library exported functions.
413 {secret}
414 ****************************************************************************/
415 BE_exports * _CEXPORT BE_initLibrary(
416     PM_imports *pmImp)
417 {
418     static BE_exports _BE_exports = {
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         };
431     int     i,max;
432     ulong   *p;
433
434     // Initialize all default imports to point to fatal error handler
435     // for upwards compatibility.
436     max = sizeof(_PM_imports)/sizeof(BE_initLibrary_t);
437     for (i = 0,p = (ulong*)&_PM_imports; i < max; i++)
438         *p++ = (ulong)_PM_fatalErrorHandler;
439
440     // Now copy all our imported functions
441     memcpy(&_PM_imports,pmImp,MIN(sizeof(_PM_imports),pmImp->dwSize));
442     return &_BE_exports;
443 }
444
445 #endif  /* __DRIVER__ */