1ece92f85SJason Jin /**************************************************************************** 2ece92f85SJason Jin * 3ece92f85SJason Jin * BIOS emulator and interface 4ece92f85SJason Jin * to Realmode X86 Emulator Library 5ece92f85SJason Jin * 6ece92f85SJason Jin * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. 7ece92f85SJason Jin * Jason Jin <Jason.jin@freescale.com> 8ece92f85SJason Jin * 9ece92f85SJason Jin * Copyright (C) 1996-1999 SciTech Software, Inc. 10ece92f85SJason Jin * 11ece92f85SJason Jin * ======================================================================== 12ece92f85SJason Jin * 13ece92f85SJason Jin * Permission to use, copy, modify, distribute, and sell this software and 14ece92f85SJason Jin * its documentation for any purpose is hereby granted without fee, 15ece92f85SJason Jin * provided that the above copyright notice appear in all copies and that 16ece92f85SJason Jin * both that copyright notice and this permission notice appear in 17ece92f85SJason Jin * supporting documentation, and that the name of the authors not be used 18ece92f85SJason Jin * in advertising or publicity pertaining to distribution of the software 19ece92f85SJason Jin * without specific, written prior permission. The authors makes no 20ece92f85SJason Jin * representations about the suitability of this software for any purpose. 21ece92f85SJason Jin * It is provided "as is" without express or implied warranty. 22ece92f85SJason Jin * 23ece92f85SJason Jin * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 24ece92f85SJason Jin * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 25ece92f85SJason Jin * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 26ece92f85SJason Jin * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 27ece92f85SJason Jin * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 28ece92f85SJason Jin * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 29ece92f85SJason Jin * PERFORMANCE OF THIS SOFTWARE. 30ece92f85SJason Jin * 31ece92f85SJason Jin * ======================================================================== 32ece92f85SJason Jin * 33ece92f85SJason Jin * Language: ANSI C 34ece92f85SJason Jin * Environment: Any 35ece92f85SJason Jin * Developer: Kendall Bennett 36ece92f85SJason Jin * 37ece92f85SJason Jin * Description: Module implementing the system specific functions. This 38ece92f85SJason Jin * module is always compiled and linked in the OS depedent 39ece92f85SJason Jin * libraries, and never in a binary portable driver. 40ece92f85SJason Jin * 41ece92f85SJason Jin * Jason ported this file to u-boot to run the ATI video card BIOS 42ece92f85SJason Jin * in u-boot. Made all the video memory be emulated during the 43ece92f85SJason Jin * BIOS runing process which may affect the VGA function but the 44ece92f85SJason Jin * frambuffer function can work after run the BIOS. 45ece92f85SJason Jin * 46ece92f85SJason Jin ****************************************************************************/ 47ece92f85SJason Jin 48ece92f85SJason Jin #include "biosemui.h" 49ece92f85SJason Jin #include <malloc.h> 50ece92f85SJason Jin 51*ce981dc8SJason Jin #if defined(CONFIG_BIOSEMU) 52*ce981dc8SJason Jin 53ece92f85SJason Jin BE_sysEnv _BE_env = {{0}}; 54ece92f85SJason Jin static X86EMU_memFuncs _BE_mem __attribute__((section(".got2"))) = { 55ece92f85SJason Jin BE_rdb, 56ece92f85SJason Jin BE_rdw, 57ece92f85SJason Jin BE_rdl, 58ece92f85SJason Jin BE_wrb, 59ece92f85SJason Jin BE_wrw, 60ece92f85SJason Jin BE_wrl, 61ece92f85SJason Jin }; 62ece92f85SJason Jin 63ece92f85SJason Jin static X86EMU_pioFuncs _BE_pio __attribute__((section(".got2"))) = { 64ece92f85SJason Jin BE_inb, 65ece92f85SJason Jin BE_inw, 66ece92f85SJason Jin BE_inl, 67ece92f85SJason Jin BE_outb, 68ece92f85SJason Jin BE_outw, 69ece92f85SJason Jin BE_outl, 70ece92f85SJason Jin }; 71ece92f85SJason Jin 72ece92f85SJason Jin #define OFF(addr) (u16)(((addr) >> 0) & 0xffff) 73ece92f85SJason Jin #define SEG(addr) (u16)(((addr) >> 4) & 0xf000) 74ece92f85SJason Jin 75ece92f85SJason Jin /**************************************************************************** 76ece92f85SJason Jin PARAMETERS: 77ece92f85SJason Jin debugFlags - Flags to enable debugging options (debug builds only) 78ece92f85SJason Jin memSize - Amount of memory to allocate for real mode machine 79ece92f85SJason Jin info - Pointer to default VGA device information 80ece92f85SJason Jin 81ece92f85SJason Jin REMARKS: 82ece92f85SJason Jin This functions initialises the BElib, and uses the passed in 83ece92f85SJason Jin BIOS image as the BIOS that is used and emulated at 0xC0000. 84ece92f85SJason Jin ****************************************************************************/ 85ece92f85SJason Jin int X86API BE_init(u32 debugFlags, int memSize, BE_VGAInfo * info, int shared) 86ece92f85SJason Jin { 87ece92f85SJason Jin #if !defined(__DRIVER__) && !defined(__KERNEL__) 88ece92f85SJason Jin 89ece92f85SJason Jin PM_init(); 90ece92f85SJason Jin #endif 91ece92f85SJason Jin memset(&M, 0, sizeof(M)); 92ece92f85SJason Jin if (memSize < 20480){ 93ece92f85SJason Jin printf("Emulator requires at least 20Kb of memory!\n"); 94ece92f85SJason Jin return 0; 95ece92f85SJason Jin } 96ece92f85SJason Jin 97ece92f85SJason Jin M.mem_base = (unsigned long)malloc(memSize); 98ece92f85SJason Jin 99ece92f85SJason Jin if (M.mem_base == NULL){ 100ece92f85SJason Jin printf("Biosemu:Out of memory!"); 101ece92f85SJason Jin return 0; 102ece92f85SJason Jin } 103ece92f85SJason Jin M.mem_size = memSize; 104ece92f85SJason Jin 105ece92f85SJason Jin _BE_env.emulateVGA = 0; 106ece92f85SJason Jin _BE_env.busmem_base = (unsigned long)malloc(128 * 1024); 107ece92f85SJason Jin if (_BE_env.busmem_base == NULL){ 108ece92f85SJason Jin printf("Biosemu:Out of memory!"); 109ece92f85SJason Jin return 0; 110ece92f85SJason Jin } 111ece92f85SJason Jin M.x86.debug = debugFlags; 112ece92f85SJason Jin _BE_bios_init((u32*)info->LowMem); 113ece92f85SJason Jin X86EMU_setupMemFuncs(&_BE_mem); 114ece92f85SJason Jin X86EMU_setupPioFuncs(&_BE_pio); 115ece92f85SJason Jin BE_setVGA(info); 116ece92f85SJason Jin return 1; 117ece92f85SJason Jin } 118ece92f85SJason Jin 119ece92f85SJason Jin /**************************************************************************** 120ece92f85SJason Jin PARAMETERS: 121ece92f85SJason Jin info - Pointer to VGA device information to make current 122ece92f85SJason Jin 123ece92f85SJason Jin REMARKS: 124ece92f85SJason Jin This function sets the VGA BIOS functions in the emulator to point to the 125ece92f85SJason Jin specific VGA BIOS in use. This includes swapping the BIOS interrupt 126ece92f85SJason Jin vectors, BIOS image and BIOS data area to the new BIOS. This allows the 127ece92f85SJason Jin real mode BIOS to be swapped without resetting the entire emulator. 128ece92f85SJason Jin ****************************************************************************/ 129ece92f85SJason Jin void X86API BE_setVGA(BE_VGAInfo * info) 130ece92f85SJason Jin { 131ece92f85SJason Jin 132ece92f85SJason Jin #ifdef __KERNEL__ 133ece92f85SJason Jin _BE_env.vgaInfo.function = info->function; 134ece92f85SJason Jin _BE_env.vgaInfo.device = info->device; 135ece92f85SJason Jin _BE_env.vgaInfo.bus = info->bus; 136ece92f85SJason Jin _BE_env.vgaInfo.pcidev = info->pcidev; 137ece92f85SJason Jin #else 138ece92f85SJason Jin _BE_env.vgaInfo.pciInfo = info->pciInfo; 139ece92f85SJason Jin #endif 140ece92f85SJason Jin _BE_env.vgaInfo.BIOSImage = info->BIOSImage; 141ece92f85SJason Jin if (info->BIOSImage) { 142ece92f85SJason Jin _BE_env.biosmem_base = (ulong) info->BIOSImage; 143ece92f85SJason Jin _BE_env.biosmem_limit = 0xC0000 + info->BIOSImageLen - 1; 144ece92f85SJason Jin } else { 145ece92f85SJason Jin _BE_env.biosmem_base = _BE_env.busmem_base + 0x20000; 146ece92f85SJason Jin _BE_env.biosmem_limit = 0xC7FFF; 147ece92f85SJason Jin } 148ece92f85SJason Jin if (*((u32 *) info->LowMem) == 0) 149ece92f85SJason Jin _BE_bios_init((u32 *) info->LowMem); 150ece92f85SJason Jin memcpy((u8 *) M.mem_base, info->LowMem, sizeof(info->LowMem)); 151ece92f85SJason Jin } 152ece92f85SJason Jin 153ece92f85SJason Jin /**************************************************************************** 154ece92f85SJason Jin PARAMETERS: 155ece92f85SJason Jin info - Pointer to VGA device information to retrieve current 156ece92f85SJason Jin 157ece92f85SJason Jin REMARKS: 158ece92f85SJason Jin This function returns the VGA BIOS functions currently active in the 159ece92f85SJason Jin emulator, so they can be restored at a later date. 160ece92f85SJason Jin ****************************************************************************/ 161ece92f85SJason Jin void X86API BE_getVGA(BE_VGAInfo * info) 162ece92f85SJason Jin { 163ece92f85SJason Jin #ifdef __KERNEL__ 164ece92f85SJason Jin info->function = _BE_env.vgaInfo.function; 165ece92f85SJason Jin info->device = _BE_env.vgaInfo.device; 166ece92f85SJason Jin info->bus = _BE_env.vgaInfo.bus; 167ece92f85SJason Jin info->pcidev = _BE_env.vgaInfo.pcidev; 168ece92f85SJason Jin #else 169ece92f85SJason Jin info->pciInfo = _BE_env.vgaInfo.pciInfo; 170ece92f85SJason Jin #endif 171ece92f85SJason Jin info->BIOSImage = _BE_env.vgaInfo.BIOSImage; 172ece92f85SJason Jin memcpy(info->LowMem, (u8 *) M.mem_base, sizeof(info->LowMem)); 173ece92f85SJason Jin } 174ece92f85SJason Jin 175ece92f85SJason Jin /**************************************************************************** 176ece92f85SJason Jin PARAMETERS: 177ece92f85SJason Jin r_seg - Segment for pointer to convert 178ece92f85SJason Jin r_off - Offset for pointer to convert 179ece92f85SJason Jin 180ece92f85SJason Jin REMARKS: 181ece92f85SJason Jin This function maps a real mode pointer in the emulator memory to a protected 182ece92f85SJason Jin mode pointer that can be used to directly access the memory. 183ece92f85SJason Jin 184ece92f85SJason Jin NOTE: The memory is *always* in little endian format, son on non-x86 185ece92f85SJason Jin systems you will need to do endian translations to access this 186ece92f85SJason Jin memory. 187ece92f85SJason Jin ****************************************************************************/ 188ece92f85SJason Jin void *X86API BE_mapRealPointer(uint r_seg, uint r_off) 189ece92f85SJason Jin { 190ece92f85SJason Jin u32 addr = ((u32) r_seg << 4) + r_off; 191ece92f85SJason Jin 192ece92f85SJason Jin if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) { 193ece92f85SJason Jin return (void *)(_BE_env.biosmem_base + addr - 0xC0000); 194ece92f85SJason Jin } else if (addr >= 0xA0000 && addr <= 0xFFFFF) { 195ece92f85SJason Jin return (void *)(_BE_env.busmem_base + addr - 0xA0000); 196ece92f85SJason Jin } 197ece92f85SJason Jin return (void *)(M.mem_base + addr); 198ece92f85SJason Jin } 199ece92f85SJason Jin 200ece92f85SJason Jin /**************************************************************************** 201ece92f85SJason Jin PARAMETERS: 202ece92f85SJason Jin len - Return the length of the VESA buffer 203ece92f85SJason Jin rseg - Place to store VESA buffer segment 204ece92f85SJason Jin roff - Place to store VESA buffer offset 205ece92f85SJason Jin 206ece92f85SJason Jin REMARKS: 207ece92f85SJason Jin This function returns the address of the VESA transfer buffer in real 208ece92f85SJason Jin _BE_piomode emulator memory. The VESA transfer buffer is always 1024 bytes long, 209ece92f85SJason Jin and located at 15Kb into the start of the real mode memory (16Kb is where 210ece92f85SJason Jin we put the real mode code we execute for issuing interrupts). 211ece92f85SJason Jin 212ece92f85SJason Jin NOTE: The memory is *always* in little endian format, son on non-x86 213ece92f85SJason Jin systems you will need to do endian translations to access this 214ece92f85SJason Jin memory. 215ece92f85SJason Jin ****************************************************************************/ 216ece92f85SJason Jin void *X86API BE_getVESABuf(uint * len, uint * rseg, uint * roff) 217ece92f85SJason Jin { 218ece92f85SJason Jin *len = 1024; 219ece92f85SJason Jin *rseg = SEG(0x03C00); 220ece92f85SJason Jin *roff = OFF(0x03C00); 221ece92f85SJason Jin return (void *)(M.mem_base + ((u32) * rseg << 4) + *roff); 222ece92f85SJason Jin } 223ece92f85SJason Jin 224ece92f85SJason Jin /**************************************************************************** 225ece92f85SJason Jin REMARKS: 226ece92f85SJason Jin Cleans up and exits the emulator. 227ece92f85SJason Jin ****************************************************************************/ 228ece92f85SJason Jin void X86API BE_exit(void) 229ece92f85SJason Jin { 230ece92f85SJason Jin free(M.mem_base); 231ece92f85SJason Jin free(_BE_env.busmem_base); 232ece92f85SJason Jin } 233ece92f85SJason Jin 234ece92f85SJason Jin /**************************************************************************** 235ece92f85SJason Jin PARAMETERS: 236ece92f85SJason Jin seg - Segment of code to call 237ece92f85SJason Jin off - Offset of code to call 238ece92f85SJason Jin regs - Real mode registers to load 239ece92f85SJason Jin sregs - Real mode segment registers to load 240ece92f85SJason Jin 241ece92f85SJason Jin REMARKS: 242ece92f85SJason Jin This functions calls a real mode far function at the specified address, 243ece92f85SJason Jin and loads all the x86 registers from the passed in registers structure. 244ece92f85SJason Jin On exit the registers returned from the call are returned in the same 245ece92f85SJason Jin structures. 246ece92f85SJason Jin ****************************************************************************/ 247ece92f85SJason Jin void X86API BE_callRealMode(uint seg, uint off, RMREGS * regs, RMSREGS * sregs) 248ece92f85SJason Jin { 249ece92f85SJason Jin M.x86.R_EAX = regs->e.eax; 250ece92f85SJason Jin M.x86.R_EBX = regs->e.ebx; 251ece92f85SJason Jin M.x86.R_ECX = regs->e.ecx; 252ece92f85SJason Jin M.x86.R_EDX = regs->e.edx; 253ece92f85SJason Jin M.x86.R_ESI = regs->e.esi; 254ece92f85SJason Jin M.x86.R_EDI = regs->e.edi; 255ece92f85SJason Jin M.x86.R_DS = sregs->ds; 256ece92f85SJason Jin M.x86.R_ES = sregs->es; 257ece92f85SJason Jin M.x86.R_FS = sregs->fs; 258ece92f85SJason Jin M.x86.R_GS = sregs->gs; 259ece92f85SJason Jin 260ece92f85SJason Jin ((u8 *) M.mem_base)[0x4000] = 0x9A; 261ece92f85SJason Jin ((u8 *) M.mem_base)[0x4001] = (u8) off; 262ece92f85SJason Jin ((u8 *) M.mem_base)[0x4002] = (u8) (off >> 8); 263ece92f85SJason Jin ((u8 *) M.mem_base)[0x4003] = (u8) seg; 264ece92f85SJason Jin ((u8 *) M.mem_base)[0x4004] = (u8) (seg >> 8); 265ece92f85SJason Jin ((u8 *) M.mem_base)[0x4005] = 0xF1; /* Illegal op-code */ 266ece92f85SJason Jin M.x86.R_CS = SEG(0x04000); 267ece92f85SJason Jin M.x86.R_IP = OFF(0x04000); 268ece92f85SJason Jin 269ece92f85SJason Jin M.x86.R_SS = SEG(M.mem_size - 2); 270ece92f85SJason Jin M.x86.R_SP = OFF(M.mem_size - 2) + 2; 271ece92f85SJason Jin 272ece92f85SJason Jin X86EMU_exec(); 273ece92f85SJason Jin 274ece92f85SJason Jin regs->e.cflag = M.x86.R_EFLG & F_CF; 275ece92f85SJason Jin regs->e.eax = M.x86.R_EAX; 276ece92f85SJason Jin regs->e.ebx = M.x86.R_EBX; 277ece92f85SJason Jin regs->e.ecx = M.x86.R_ECX; 278ece92f85SJason Jin regs->e.edx = M.x86.R_EDX; 279ece92f85SJason Jin regs->e.esi = M.x86.R_ESI; 280ece92f85SJason Jin regs->e.edi = M.x86.R_EDI; 281ece92f85SJason Jin sregs->ds = M.x86.R_DS; 282ece92f85SJason Jin sregs->es = M.x86.R_ES; 283ece92f85SJason Jin sregs->fs = M.x86.R_FS; 284ece92f85SJason Jin sregs->gs = M.x86.R_GS; 285ece92f85SJason Jin } 286ece92f85SJason Jin 287ece92f85SJason Jin /**************************************************************************** 288ece92f85SJason Jin PARAMETERS: 289ece92f85SJason Jin intno - Interrupt number to execute 290ece92f85SJason Jin in - Real mode registers to load 291ece92f85SJason Jin out - Place to store resulting real mode registers 292ece92f85SJason Jin 293ece92f85SJason Jin REMARKS: 294ece92f85SJason Jin This functions calls a real mode interrupt function at the specified address, 295ece92f85SJason Jin and loads all the x86 registers from the passed in registers structure. 296ece92f85SJason Jin On exit the registers returned from the call are returned in out stucture. 297ece92f85SJason Jin ****************************************************************************/ 298ece92f85SJason Jin int X86API BE_int86(int intno, RMREGS * in, RMREGS * out) 299ece92f85SJason Jin { 300ece92f85SJason Jin M.x86.R_EAX = in->e.eax; 301ece92f85SJason Jin M.x86.R_EBX = in->e.ebx; 302ece92f85SJason Jin M.x86.R_ECX = in->e.ecx; 303ece92f85SJason Jin M.x86.R_EDX = in->e.edx; 304ece92f85SJason Jin M.x86.R_ESI = in->e.esi; 305ece92f85SJason Jin M.x86.R_EDI = in->e.edi; 306ece92f85SJason Jin ((u8 *) M.mem_base)[0x4000] = 0xCD; 307ece92f85SJason Jin ((u8 *) M.mem_base)[0x4001] = (u8) intno; 308ece92f85SJason Jin ((u8 *) M.mem_base)[0x4002] = 0xF1; 309ece92f85SJason Jin M.x86.R_CS = SEG(0x04000); 310ece92f85SJason Jin M.x86.R_IP = OFF(0x04000); 311ece92f85SJason Jin 312ece92f85SJason Jin M.x86.R_SS = SEG(M.mem_size - 1); 313ece92f85SJason Jin M.x86.R_SP = OFF(M.mem_size - 1) - 1; 314ece92f85SJason Jin 315ece92f85SJason Jin X86EMU_exec(); 316ece92f85SJason Jin out->e.cflag = M.x86.R_EFLG & F_CF; 317ece92f85SJason Jin out->e.eax = M.x86.R_EAX; 318ece92f85SJason Jin out->e.ebx = M.x86.R_EBX; 319ece92f85SJason Jin out->e.ecx = M.x86.R_ECX; 320ece92f85SJason Jin out->e.edx = M.x86.R_EDX; 321ece92f85SJason Jin out->e.esi = M.x86.R_ESI; 322ece92f85SJason Jin out->e.edi = M.x86.R_EDI; 323ece92f85SJason Jin return out->x.ax; 324ece92f85SJason Jin } 325ece92f85SJason Jin 326ece92f85SJason Jin /**************************************************************************** 327ece92f85SJason Jin PARAMETERS: 328ece92f85SJason Jin intno - Interrupt number to execute 329ece92f85SJason Jin in - Real mode registers to load 330ece92f85SJason Jin out - Place to store resulting real mode registers 331ece92f85SJason Jin sregs - Real mode segment registers to load 332ece92f85SJason Jin 333ece92f85SJason Jin REMARKS: 334ece92f85SJason Jin This functions calls a real mode interrupt function at the specified address, 335ece92f85SJason Jin and loads all the x86 registers from the passed in registers structure. 336ece92f85SJason Jin On exit the registers returned from the call are returned in out stucture. 337ece92f85SJason Jin ****************************************************************************/ 338ece92f85SJason Jin int X86API BE_int86x(int intno, RMREGS * in, RMREGS * out, RMSREGS * sregs) 339ece92f85SJason Jin { 340ece92f85SJason Jin M.x86.R_EAX = in->e.eax; 341ece92f85SJason Jin M.x86.R_EBX = in->e.ebx; 342ece92f85SJason Jin M.x86.R_ECX = in->e.ecx; 343ece92f85SJason Jin M.x86.R_EDX = in->e.edx; 344ece92f85SJason Jin M.x86.R_ESI = in->e.esi; 345ece92f85SJason Jin M.x86.R_EDI = in->e.edi; 346ece92f85SJason Jin M.x86.R_DS = sregs->ds; 347ece92f85SJason Jin M.x86.R_ES = sregs->es; 348ece92f85SJason Jin M.x86.R_FS = sregs->fs; 349ece92f85SJason Jin M.x86.R_GS = sregs->gs; 350ece92f85SJason Jin ((u8 *) M.mem_base)[0x4000] = 0xCD; 351ece92f85SJason Jin ((u8 *) M.mem_base)[0x4001] = (u8) intno; 352ece92f85SJason Jin ((u8 *) M.mem_base)[0x4002] = 0xF1; 353ece92f85SJason Jin M.x86.R_CS = SEG(0x04000); 354ece92f85SJason Jin M.x86.R_IP = OFF(0x04000); 355ece92f85SJason Jin 356ece92f85SJason Jin M.x86.R_SS = SEG(M.mem_size - 1); 357ece92f85SJason Jin M.x86.R_SP = OFF(M.mem_size - 1) - 1; 358ece92f85SJason Jin 359ece92f85SJason Jin X86EMU_exec(); 360ece92f85SJason Jin out->e.cflag = M.x86.R_EFLG & F_CF; 361ece92f85SJason Jin out->e.eax = M.x86.R_EAX; 362ece92f85SJason Jin out->e.ebx = M.x86.R_EBX; 363ece92f85SJason Jin out->e.ecx = M.x86.R_ECX; 364ece92f85SJason Jin out->e.edx = M.x86.R_EDX; 365ece92f85SJason Jin out->e.esi = M.x86.R_ESI; 366ece92f85SJason Jin out->e.edi = M.x86.R_EDI; 367ece92f85SJason Jin sregs->ds = M.x86.R_DS; 368ece92f85SJason Jin sregs->es = M.x86.R_ES; 369ece92f85SJason Jin sregs->fs = M.x86.R_FS; 370ece92f85SJason Jin sregs->gs = M.x86.R_GS; 371ece92f85SJason Jin return out->x.ax; 372ece92f85SJason Jin } 373*ce981dc8SJason Jin #endif 374