1
/****************************************************************************
3
* BIOS emulator and interface
4
* to Realmode X86 Emulator Library
6
* Copyright (C) 2007 Freescale Semiconductor, Inc.
7
* Jason Jin <Jason.jin@freescale.com>
9
* Copyright (C) 1996-1999 SciTech Software, Inc.
11
* ========================================================================
13
* Permission to use, copy, modify, distribute, and sell this software and
14
* its documentation for any purpose is hereby granted without fee,
15
* provided that the above copyright notice appear in all copies and that
16
* both that copyright notice and this permission notice appear in
17
* supporting documentation, and that the name of the authors not be used
18
* in advertising or publicity pertaining to distribution of the software
19
* without specific, written prior permission. The authors makes no
20
* representations about the suitability of this software for any purpose.
21
* It is provided "as is" without express or implied warranty.
23
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
25
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
26
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
27
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
28
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
29
* PERFORMANCE OF THIS SOFTWARE.
31
* ========================================================================
35
* Developer: Kendall Bennett
37
* Description: Module implementing the system specific functions. This
38
* module is always compiled and linked in the OS depedent
39
* libraries, and never in a binary portable driver.
41
* Jason ported this file to u-boot to run the ATI video card BIOS
42
* in u-boot. Made all the video memory be emulated during the
43
* BIOS runing process which may affect the VGA function but the
44
* frambuffer function can work after run the BIOS.
46
****************************************************************************/
52
BE_sysEnv _BE_env = {{0}};
53
static X86EMU_memFuncs _BE_mem __attribute__((section(GOT2_TYPE))) = {
62
static X86EMU_pioFuncs _BE_pio __attribute__((section(GOT2_TYPE))) = {
71
#define OFF(addr) (u16)(((addr) >> 0) & 0xffff)
72
#define SEG(addr) (u16)(((addr) >> 4) & 0xf000)
74
/****************************************************************************
76
debugFlags - Flags to enable debugging options (debug builds only)
77
memSize - Amount of memory to allocate for real mode machine
78
info - Pointer to default VGA device information
81
This functions initialises the BElib, and uses the passed in
82
BIOS image as the BIOS that is used and emulated at 0xC0000.
83
****************************************************************************/
84
int X86API BE_init(u32 debugFlags, int memSize, BE_VGAInfo * info, int shared)
86
#if !defined(__DRIVER__) && !defined(__KERNEL__)
90
memset(&M, 0, sizeof(M));
92
printf("Emulator requires at least 20Kb of memory!\n");
96
M.mem_base = malloc(memSize);
98
if (M.mem_base == NULL){
99
printf("Biosemu:Out of memory!");
102
M.mem_size = memSize;
104
_BE_env.emulateVGA = 0;
105
_BE_env.busmem_base = (unsigned long)malloc(128 * 1024);
106
if ((void *)_BE_env.busmem_base == NULL){
107
printf("Biosemu:Out of memory!");
110
M.x86.debug = debugFlags;
111
_BE_bios_init((u32*)info->LowMem);
112
X86EMU_setupMemFuncs(&_BE_mem);
113
X86EMU_setupPioFuncs(&_BE_pio);
118
/****************************************************************************
120
info - Pointer to VGA device information to make current
123
This function sets the VGA BIOS functions in the emulator to point to the
124
specific VGA BIOS in use. This includes swapping the BIOS interrupt
125
vectors, BIOS image and BIOS data area to the new BIOS. This allows the
126
real mode BIOS to be swapped without resetting the entire emulator.
127
****************************************************************************/
128
void X86API BE_setVGA(BE_VGAInfo * info)
132
_BE_env.vgaInfo.function = info->function;
133
_BE_env.vgaInfo.device = info->device;
134
_BE_env.vgaInfo.bus = info->bus;
135
_BE_env.vgaInfo.pcidev = info->pcidev;
137
_BE_env.vgaInfo.pciInfo = info->pciInfo;
139
_BE_env.vgaInfo.BIOSImage = info->BIOSImage;
140
if (info->BIOSImage) {
141
_BE_env.biosmem_base = (ulong) info->BIOSImage;
142
_BE_env.biosmem_limit = 0xC0000 + info->BIOSImageLen - 1;
144
_BE_env.biosmem_base = _BE_env.busmem_base + 0x20000;
145
_BE_env.biosmem_limit = 0xC7FFF;
147
if ((info->LowMem[0] == 0) && (info->LowMem[1] == 0) &&
148
(info->LowMem[2] == 0) && (info->LowMem[3] == 0))
149
_BE_bios_init((u32 *) info->LowMem);
150
memcpy((u8 *) M.mem_base, info->LowMem, sizeof(info->LowMem));
153
/****************************************************************************
155
info - Pointer to VGA device information to retrieve current
158
This function returns the VGA BIOS functions currently active in the
159
emulator, so they can be restored at a later date.
160
****************************************************************************/
161
void X86API BE_getVGA(BE_VGAInfo * info)
164
info->function = _BE_env.vgaInfo.function;
165
info->device = _BE_env.vgaInfo.device;
166
info->bus = _BE_env.vgaInfo.bus;
167
info->pcidev = _BE_env.vgaInfo.pcidev;
169
info->pciInfo = _BE_env.vgaInfo.pciInfo;
171
info->BIOSImage = _BE_env.vgaInfo.BIOSImage;
172
memcpy(info->LowMem, (u8 *) M.mem_base, sizeof(info->LowMem));
175
/****************************************************************************
177
r_seg - Segment for pointer to convert
178
r_off - Offset for pointer to convert
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.
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
187
****************************************************************************/
188
void *X86API BE_mapRealPointer(uint r_seg, uint r_off)
190
u32 addr = ((u32) r_seg << 4) + r_off;
192
if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
193
return (void *)(_BE_env.biosmem_base + addr - 0xC0000);
194
} else if (addr >= 0xA0000 && addr <= 0xFFFFF) {
195
return (void *)(_BE_env.busmem_base + addr - 0xA0000);
197
return (void *)(M.mem_base + addr);
200
/****************************************************************************
202
len - Return the length of the VESA buffer
203
rseg - Place to store VESA buffer segment
204
roff - Place to store VESA buffer offset
207
This function returns the address of the VESA transfer buffer in real
208
_BE_piomode emulator memory. The VESA transfer buffer is always 1024 bytes long,
209
and located at 15Kb into the start of the real mode memory (16Kb is where
210
we put the real mode code we execute for issuing interrupts).
212
NOTE: The memory is *always* in little endian format, son on non-x86
213
systems you will need to do endian translations to access this
215
****************************************************************************/
216
void *X86API BE_getVESABuf(uint * len, uint * rseg, uint * roff)
219
*rseg = SEG(0x03C00);
220
*roff = OFF(0x03C00);
221
return (void *)(M.mem_base + ((u32) * rseg << 4) + *roff);
224
/****************************************************************************
226
Cleans up and exits the emulator.
227
****************************************************************************/
228
void X86API BE_exit(void)
231
free((void *)_BE_env.busmem_base);
234
/****************************************************************************
236
seg - Segment of code to call
237
off - Offset of code to call
238
regs - Real mode registers to load
239
sregs - Real mode segment registers to load
242
This functions calls a real mode far function at the specified address,
243
and loads all the x86 registers from the passed in registers structure.
244
On exit the registers returned from the call are returned in the same
246
****************************************************************************/
247
void X86API BE_callRealMode(uint seg, uint off, RMREGS * regs, RMSREGS * sregs)
249
M.x86.R_EAX = regs->e.eax;
250
M.x86.R_EBX = regs->e.ebx;
251
M.x86.R_ECX = regs->e.ecx;
252
M.x86.R_EDX = regs->e.edx;
253
M.x86.R_ESI = regs->e.esi;
254
M.x86.R_EDI = regs->e.edi;
255
M.x86.R_DS = sregs->ds;
256
M.x86.R_ES = sregs->es;
257
M.x86.R_FS = sregs->fs;
258
M.x86.R_GS = sregs->gs;
260
((u8 *) M.mem_base)[0x4000] = 0x9A;
261
((u8 *) M.mem_base)[0x4001] = (u8) off;
262
((u8 *) M.mem_base)[0x4002] = (u8) (off >> 8);
263
((u8 *) M.mem_base)[0x4003] = (u8) seg;
264
((u8 *) M.mem_base)[0x4004] = (u8) (seg >> 8);
265
((u8 *) M.mem_base)[0x4005] = 0xF1; /* Illegal op-code */
266
M.x86.R_CS = SEG(0x04000);
267
M.x86.R_IP = OFF(0x04000);
269
M.x86.R_SS = SEG(M.mem_size - 2);
270
M.x86.R_SP = OFF(M.mem_size - 2) + 2;
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;
287
/****************************************************************************
289
intno - Interrupt number to execute
290
in - Real mode registers to load
291
out - Place to store resulting real mode registers
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 X86API BE_int86(int intno, RMREGS * in, RMREGS * out)
300
M.x86.R_EAX = in->e.eax;
301
M.x86.R_EBX = in->e.ebx;
302
M.x86.R_ECX = in->e.ecx;
303
M.x86.R_EDX = in->e.edx;
304
M.x86.R_ESI = in->e.esi;
305
M.x86.R_EDI = in->e.edi;
306
((u8 *) M.mem_base)[0x4000] = 0xCD;
307
((u8 *) M.mem_base)[0x4001] = (u8) intno;
308
((u8 *) M.mem_base)[0x4002] = 0xF1;
309
M.x86.R_CS = SEG(0x04000);
310
M.x86.R_IP = OFF(0x04000);
312
M.x86.R_SS = SEG(M.mem_size - 1);
313
M.x86.R_SP = OFF(M.mem_size - 1) - 1;
316
out->e.cflag = M.x86.R_EFLG & F_CF;
317
out->e.eax = M.x86.R_EAX;
318
out->e.ebx = M.x86.R_EBX;
319
out->e.ecx = M.x86.R_ECX;
320
out->e.edx = M.x86.R_EDX;
321
out->e.esi = M.x86.R_ESI;
322
out->e.edi = M.x86.R_EDI;
326
/****************************************************************************
328
intno - Interrupt number to execute
329
in - Real mode registers to load
330
out - Place to store resulting real mode registers
331
sregs - Real mode segment registers to load
334
This functions calls a real mode interrupt function at the specified address,
335
and loads all the x86 registers from the passed in registers structure.
336
On exit the registers returned from the call are returned in out stucture.
337
****************************************************************************/
338
int X86API BE_int86x(int intno, RMREGS * in, RMREGS * out, RMSREGS * sregs)
340
M.x86.R_EAX = in->e.eax;
341
M.x86.R_EBX = in->e.ebx;
342
M.x86.R_ECX = in->e.ecx;
343
M.x86.R_EDX = in->e.edx;
344
M.x86.R_ESI = in->e.esi;
345
M.x86.R_EDI = in->e.edi;
346
M.x86.R_DS = sregs->ds;
347
M.x86.R_ES = sregs->es;
348
M.x86.R_FS = sregs->fs;
349
M.x86.R_GS = sregs->gs;
350
((u8 *) M.mem_base)[0x4000] = 0xCD;
351
((u8 *) M.mem_base)[0x4001] = (u8) intno;
352
((u8 *) M.mem_base)[0x4002] = 0xF1;
353
M.x86.R_CS = SEG(0x04000);
354
M.x86.R_IP = OFF(0x04000);
356
M.x86.R_SS = SEG(M.mem_size - 1);
357
M.x86.R_SP = OFF(M.mem_size - 1) - 1;
360
out->e.cflag = M.x86.R_EFLG & F_CF;
361
out->e.eax = M.x86.R_EAX;
362
out->e.ebx = M.x86.R_EBX;
363
out->e.ecx = M.x86.R_ECX;
364
out->e.edx = M.x86.R_EDX;
365
out->e.esi = M.x86.R_ESI;
366
out->e.edi = M.x86.R_EDI;
367
sregs->ds = M.x86.R_DS;
368
sregs->es = M.x86.R_ES;
369
sregs->fs = M.x86.R_FS;
370
sregs->gs = M.x86.R_GS;