~ubuntu-branches/ubuntu/maverick/u-boot-omap3/maverick

« back to all changes in this revision

Viewing changes to drivers/bios_emulator/biosemu.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2010-03-22 15:06:23 UTC
  • Revision ID: james.westby@ubuntu.com-20100322150623-i21g8rgiyl5dohag
Tags: upstream-2010.3git20100315
ImportĀ upstreamĀ versionĀ 2010.3git20100315

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
*
 
3
*                        BIOS emulator and interface
 
4
*                      to Realmode X86 Emulator Library
 
5
*
 
6
*  Copyright (C) 2007 Freescale Semiconductor, Inc.
 
7
*  Jason Jin <Jason.jin@freescale.com>
 
8
*
 
9
*               Copyright (C) 1996-1999 SciTech Software, Inc.
 
10
*
 
11
*  ========================================================================
 
12
*
 
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.
 
22
*
 
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.
 
30
*
 
31
*  ========================================================================
 
32
*
 
33
* Language:     ANSI C
 
34
* Environment:  Any
 
35
* Developer:    Kendall Bennett
 
36
*
 
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.
 
40
*
 
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.
 
45
*
 
46
****************************************************************************/
 
47
 
 
48
#include <malloc.h>
 
49
#include <common.h>
 
50
#include "biosemui.h"
 
51
 
 
52
BE_sysEnv _BE_env = {{0}};
 
53
static X86EMU_memFuncs _BE_mem __attribute__((section(GOT2_TYPE))) = {
 
54
        BE_rdb,
 
55
        BE_rdw,
 
56
        BE_rdl,
 
57
        BE_wrb,
 
58
        BE_wrw,
 
59
        BE_wrl,
 
60
        };
 
61
 
 
62
static X86EMU_pioFuncs _BE_pio __attribute__((section(GOT2_TYPE))) = {
 
63
        BE_inb,
 
64
        BE_inw,
 
65
        BE_inl,
 
66
        BE_outb,
 
67
        BE_outw,
 
68
        BE_outl,
 
69
        };
 
70
 
 
71
#define OFF(addr)       (u16)(((addr) >> 0) & 0xffff)
 
72
#define SEG(addr)       (u16)(((addr) >> 4) & 0xf000)
 
73
 
 
74
/****************************************************************************
 
75
PARAMETERS:
 
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
 
79
 
 
80
REMARKS:
 
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)
 
85
{
 
86
#if !defined(__DRIVER__)  && !defined(__KERNEL__)
 
87
 
 
88
        PM_init();
 
89
#endif
 
90
        memset(&M, 0, sizeof(M));
 
91
        if (memSize < 20480){
 
92
                printf("Emulator requires at least 20Kb of memory!\n");
 
93
                return 0;
 
94
        }
 
95
 
 
96
        M.mem_base = malloc(memSize);
 
97
 
 
98
        if (M.mem_base == NULL){
 
99
                printf("Biosemu:Out of memory!");
 
100
                return 0;
 
101
        }
 
102
        M.mem_size = memSize;
 
103
 
 
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!");
 
108
                return 0;
 
109
        }
 
110
        M.x86.debug = debugFlags;
 
111
        _BE_bios_init((u32*)info->LowMem);
 
112
        X86EMU_setupMemFuncs(&_BE_mem);
 
113
        X86EMU_setupPioFuncs(&_BE_pio);
 
114
        BE_setVGA(info);
 
115
        return 1;
 
116
}
 
117
 
 
118
/****************************************************************************
 
119
PARAMETERS:
 
120
info        - Pointer to VGA device information to make current
 
121
 
 
122
REMARKS:
 
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)
 
129
{
 
130
 
 
131
#ifdef __KERNEL__
 
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;
 
136
#else
 
137
        _BE_env.vgaInfo.pciInfo = info->pciInfo;
 
138
#endif
 
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;
 
143
        } else {
 
144
                _BE_env.biosmem_base = _BE_env.busmem_base + 0x20000;
 
145
                _BE_env.biosmem_limit = 0xC7FFF;
 
146
        }
 
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));
 
151
}
 
152
 
 
153
/****************************************************************************
 
154
PARAMETERS:
 
155
info        - Pointer to VGA device information to retrieve current
 
156
 
 
157
REMARKS:
 
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)
 
162
{
 
163
#ifdef __KERNEL__
 
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;
 
168
#else
 
169
        info->pciInfo = _BE_env.vgaInfo.pciInfo;
 
170
#endif
 
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 *X86API BE_mapRealPointer(uint r_seg, uint r_off)
 
189
{
 
190
        u32 addr = ((u32) r_seg << 4) + r_off;
 
191
 
 
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);
 
196
        }
 
197
        return (void *)(M.mem_base + addr);
 
198
}
 
199
 
 
200
/****************************************************************************
 
201
PARAMETERS:
 
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
 
205
 
 
206
REMARKS:
 
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).
 
211
 
 
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
 
214
        memory.
 
215
****************************************************************************/
 
216
void *X86API BE_getVESABuf(uint * len, uint * rseg, uint * roff)
 
217
{
 
218
        *len = 1024;
 
219
        *rseg = SEG(0x03C00);
 
220
        *roff = OFF(0x03C00);
 
221
        return (void *)(M.mem_base + ((u32) * rseg << 4) + *roff);
 
222
}
 
223
 
 
224
/****************************************************************************
 
225
REMARKS:
 
226
Cleans up and exits the emulator.
 
227
****************************************************************************/
 
228
void X86API BE_exit(void)
 
229
{
 
230
        free(M.mem_base);
 
231
        free((void *)_BE_env.busmem_base);
 
232
}
 
233
 
 
234
/****************************************************************************
 
235
PARAMETERS:
 
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
 
240
 
 
241
REMARKS:
 
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
 
245
structures.
 
246
****************************************************************************/
 
247
void X86API BE_callRealMode(uint seg, uint off, RMREGS * regs, RMSREGS * sregs)
 
248
{
 
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;
 
259
 
 
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);
 
268
 
 
269
        M.x86.R_SS = SEG(M.mem_size - 2);
 
270
        M.x86.R_SP = OFF(M.mem_size - 2) + 2;
 
271
 
 
272
        X86EMU_exec();
 
273
 
 
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 X86API BE_int86(int intno, RMREGS * in, RMREGS * out)
 
299
{
 
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);
 
311
 
 
312
        M.x86.R_SS = SEG(M.mem_size - 1);
 
313
        M.x86.R_SP = OFF(M.mem_size - 1) - 1;
 
314
 
 
315
        X86EMU_exec();
 
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;
 
323
        return out->x.ax;
 
324
}
 
325
 
 
326
/****************************************************************************
 
327
PARAMETERS:
 
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
 
332
 
 
333
REMARKS:
 
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)
 
339
{
 
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);
 
355
 
 
356
        M.x86.R_SS = SEG(M.mem_size - 1);
 
357
        M.x86.R_SP = OFF(M.mem_size - 1) - 1;
 
358
 
 
359
        X86EMU_exec();
 
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;
 
371
        return out->x.ax;
 
372
}