Change real mode API to allow passing intXX number or entry point and
some register values from C. This theoretically fixes non-vga option roms, but it also allows to use the same assembler code for option roms and vsm. It will also make using the bootsplash without yabel a lot easier. Factor out and improve BDA setup, do some rom segment setup for those option roms that need it. Don't call the coreboot exception handler if an exception occurs in real mode. It's only partly usable, but mainly the Kontron 986LCD-M (and other i945GM boards) choke on an exception #6 (invalid opcode). This particular issue is not introduced by the changes in this patch but has been around for quite a while at least. Signed-off-by: Stefan Reinauer <stepan@coresystems.de> Acked-by: Patrick Georgi <patrick.georgi@coresystems.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5543 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
48beb82769
commit
841af5e01e
|
@ -34,12 +34,45 @@ struct realmode_idt {
|
||||||
|
|
||||||
void x86_exception(struct eregs *info);
|
void x86_exception(struct eregs *info);
|
||||||
|
|
||||||
|
/* From x86_asm.S */
|
||||||
extern unsigned char __idt_handler, __idt_handler_size;
|
extern unsigned char __idt_handler, __idt_handler_size;
|
||||||
extern unsigned char __realmode_code, __realmode_code_size;
|
extern unsigned char __realmode_code, __realmode_code_size;
|
||||||
extern unsigned char __run_optionrom, __run_interrupt;
|
extern unsigned char __realmode_call, __realmode_interrupt;
|
||||||
|
|
||||||
void (*run_optionrom)(u32 devfn) __attribute__((regparm(0))) = (void *)&__run_optionrom;
|
void (*realmode_call)(u32 addr, u32 eax, u32 ebx, u32 ecx, u32 edx,
|
||||||
void (*vga_enable_console)(void) __attribute__((regparm(0))) = (void *)&__run_interrupt;
|
u32 esi, u32 edi) __attribute__((regparm(0))) = (void *)&__realmode_call;
|
||||||
|
|
||||||
|
void (*realmode_interrupt)(u32 intno, u32 eax, u32 ebx, u32 ecx, u32 edx,
|
||||||
|
u32 esi, u32 edi) __attribute__((regparm(0))) = (void *)&__realmode_interrupt;
|
||||||
|
|
||||||
|
#define FAKE_MEMORY_SIZE (1024*1024) // only 1MB
|
||||||
|
#define INITIAL_EBDA_SEGMENT 0xF600
|
||||||
|
#define INITIAL_EBDA_SIZE 0x400
|
||||||
|
|
||||||
|
static void setup_bda(void)
|
||||||
|
{
|
||||||
|
/* clear BIOS DATA AREA */
|
||||||
|
memset((void *)0x400, 0, 0x200);
|
||||||
|
|
||||||
|
write16(0x413, FAKE_MEMORY_SIZE / 1024);
|
||||||
|
write16(0x40e, INITIAL_EBDA_SEGMENT);
|
||||||
|
|
||||||
|
/* Set up EBDA */
|
||||||
|
memset((void *)(INITIAL_EBDA_SEGMENT << 4), 0, INITIAL_EBDA_SIZE);
|
||||||
|
write16((INITIAL_EBDA_SEGMENT << 4) + 0x0, INITIAL_EBDA_SIZE / 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup_rombios(void)
|
||||||
|
{
|
||||||
|
const char date[] = "06/11/99";
|
||||||
|
memcpy((void *)0xffff5, &date, 8);
|
||||||
|
|
||||||
|
const char ident[] = "PCI_ISA";
|
||||||
|
memcpy((void *)0xfffd9, &ident, 7);
|
||||||
|
|
||||||
|
/* system model: IBM-AT */
|
||||||
|
write8(0xffffe, 0xfc);
|
||||||
|
}
|
||||||
|
|
||||||
int (*intXX_handler[256])(struct eregs *regs) = { NULL };
|
int (*intXX_handler[256])(struct eregs *regs) = { NULL };
|
||||||
|
|
||||||
|
@ -47,7 +80,12 @@ static int intXX_exception_handler(struct eregs *regs)
|
||||||
{
|
{
|
||||||
printk(BIOS_INFO, "Oops, exception %d while executing option rom\n",
|
printk(BIOS_INFO, "Oops, exception %d while executing option rom\n",
|
||||||
regs->vector);
|
regs->vector);
|
||||||
|
#if 0
|
||||||
|
// Odd: The i945GM VGA oprom chokes on a pushl %eax and will
|
||||||
|
// die with an exception #6 if we run the coreboot exception
|
||||||
|
// handler. Just continue, as it executes fine.
|
||||||
x86_exception(regs); // Call coreboot exception handler
|
x86_exception(regs); // Call coreboot exception handler
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0; // Never returns?
|
return 0; // Never returns?
|
||||||
}
|
}
|
||||||
|
@ -138,20 +176,38 @@ static void setup_realmode_idt(void)
|
||||||
|
|
||||||
/* int42 is the relocated int10 */
|
/* int42 is the relocated int10 */
|
||||||
write_idt_stub((void *)0xff065, 0x42);
|
write_idt_stub((void *)0xff065, 0x42);
|
||||||
|
/* BIOS Int 11 Handler F000:F84D */
|
||||||
/* VIA's VBIOS calls f000:f859 instead of int15 */
|
write_idt_stub((void *)0xff84d, 0x11);
|
||||||
|
/* BIOS Int 12 Handler F000:F841 */
|
||||||
|
write_idt_stub((void *)0xff841, 0x12);
|
||||||
|
/* BIOS Int 13 Handler F000:EC59 */
|
||||||
|
write_idt_stub((void *)0xfec59, 0x13);
|
||||||
|
/* BIOS Int 14 Handler F000:E739 */
|
||||||
|
write_idt_stub((void *)0xfe739, 0x14);
|
||||||
|
/* BIOS Int 15 Handler F000:F859 */
|
||||||
write_idt_stub((void *)0xff859, 0x15);
|
write_idt_stub((void *)0xff859, 0x15);
|
||||||
|
/* BIOS Int 16 Handler F000:E82E */
|
||||||
|
write_idt_stub((void *)0xfe82e, 0x16);
|
||||||
|
/* BIOS Int 17 Handler F000:EFD2 */
|
||||||
|
write_idt_stub((void *)0xfefd2, 0x17);
|
||||||
|
/* ROM BIOS Int 1A Handler F000:FE6E */
|
||||||
|
write_idt_stub((void *)0xffe6e, 0x1a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_bios(struct device *dev, unsigned long addr)
|
void run_bios(struct device *dev, unsigned long addr)
|
||||||
{
|
{
|
||||||
/* clear vga bios data area */
|
u32 num_dev = (dev->bus->secondary << 8) | dev->path.pci.devfn;
|
||||||
memset((void *)0x400, 0, 0x200);
|
|
||||||
|
/* Set up BIOS Data Area */
|
||||||
|
setup_bda();
|
||||||
|
|
||||||
|
/* Set up some legacy information in the F segment */
|
||||||
|
setup_rombios();
|
||||||
|
|
||||||
/* Set up C interrupt handlers */
|
/* Set up C interrupt handlers */
|
||||||
setup_interrupt_handlers();
|
setup_interrupt_handlers();
|
||||||
|
|
||||||
/* Setting up realmode IDT */
|
/* Set up real-mode IDT */
|
||||||
setup_realmode_idt();
|
setup_realmode_idt();
|
||||||
|
|
||||||
memcpy(REALMODE_BASE, &__realmode_code, (size_t)&__realmode_code_size);
|
memcpy(REALMODE_BASE, &__realmode_code, (size_t)&__realmode_code_size);
|
||||||
|
@ -159,7 +215,9 @@ void run_bios(struct device *dev, unsigned long addr)
|
||||||
(u32)&__realmode_code_size);
|
(u32)&__realmode_code_size);
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "Calling Option ROM...\n");
|
printk(BIOS_DEBUG, "Calling Option ROM...\n");
|
||||||
run_optionrom((dev->bus->secondary << 8) | dev->path.pci.devfn);
|
/* TODO ES:DI Pointer to System BIOS PnP Installation Check Structure */
|
||||||
|
/* Option ROM entry point is at OPROM start + 3 */
|
||||||
|
realmode_call(addr + 0x0003, num_dev, 0xffff, 0x0000, 0xffff, 0x0, 0x0);
|
||||||
printk(BIOS_DEBUG, "... Option ROM returned.\n");
|
printk(BIOS_DEBUG, "... Option ROM returned.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,9 +226,6 @@ void run_bios(struct device *dev, unsigned long addr)
|
||||||
#include <cpu/amd/vr.h>
|
#include <cpu/amd/vr.h>
|
||||||
#include <cbfs.h>
|
#include <cbfs.h>
|
||||||
|
|
||||||
extern unsigned char __run_vsa;
|
|
||||||
void (*run_vsa)(u32 smm, u32 sysmem) __attribute__((regparm(0))) = (void *)&__run_vsa;
|
|
||||||
|
|
||||||
#define VSA2_BUFFER 0x60000
|
#define VSA2_BUFFER 0x60000
|
||||||
#define VSA2_ENTRY_POINT 0x60020
|
#define VSA2_ENTRY_POINT 0x60020
|
||||||
|
|
||||||
|
@ -198,9 +253,6 @@ void do_vsmbios(void)
|
||||||
{
|
{
|
||||||
printk(BIOS_DEBUG, "Preparing for VSA...\n");
|
printk(BIOS_DEBUG, "Preparing for VSA...\n");
|
||||||
|
|
||||||
/* clear bios data area */
|
|
||||||
memset((void *)0x400, 0, 0x200);
|
|
||||||
|
|
||||||
/* Set up C interrupt handlers */
|
/* Set up C interrupt handlers */
|
||||||
setup_interrupt_handlers();
|
setup_interrupt_handlers();
|
||||||
|
|
||||||
|
@ -229,8 +281,11 @@ void do_vsmbios(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "Calling VSA module...\n");
|
printk(BIOS_DEBUG, "Calling VSA module...\n");
|
||||||
|
|
||||||
/* ECX gets SMM, EDX gets SYSMEM */
|
/* ECX gets SMM, EDX gets SYSMEM */
|
||||||
run_vsa(MSR_GLIU0_SMM, MSR_GLIU0_SYSMEM);
|
realmode_call(VSA2_ENTRY_POINT, 0x0, 0x0, MSR_GLIU0_SMM,
|
||||||
|
MSR_GLIU0_SYSMEM, 0x0, 0x0);
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "... VSA module returned.\n");
|
printk(BIOS_DEBUG, "... VSA module returned.\n");
|
||||||
|
|
||||||
/* Restart timer 1 */
|
/* Restart timer 1 */
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the coreboot project.
|
* This file is part of the coreboot project.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 coresystems GmbH
|
* Copyright (C) 2009-2010 coresystems GmbH
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -57,21 +57,49 @@ __realmode_idt = RELOCATED(.)
|
||||||
__stack = RELOCATED(.)
|
__stack = RELOCATED(.)
|
||||||
.long 0
|
.long 0
|
||||||
|
|
||||||
|
/* Register store for realmode_call and realmode_interrupt */
|
||||||
|
__registers = RELOCATED(.)
|
||||||
|
.long 0 /* 0x00 - EAX */
|
||||||
|
.long 0 /* 0x04 - EBX */
|
||||||
|
.long 0 /* 0x08 - ECX */
|
||||||
|
.long 0 /* 0x0c - EDX */
|
||||||
|
.long 0 /* 0x10 - EDI */
|
||||||
|
.long 0 /* 0x14 - ESI */
|
||||||
|
|
||||||
.code32
|
.code32
|
||||||
.globl __run_optionrom
|
.globl __realmode_call
|
||||||
__run_optionrom = RELOCATED(.)
|
__realmode_call = RELOCATED(.)
|
||||||
/* save all registers to the stack */
|
/* save all registers to the stack */
|
||||||
pushal
|
pushal
|
||||||
|
|
||||||
/* Move the protected mode stack to a safe place */
|
/* Move the protected mode stack to a safe place */
|
||||||
mov %esp, __stack
|
movl %esp, __stack
|
||||||
|
|
||||||
/* Get devfn into %ecx */
|
|
||||||
movl %esp, %ebp
|
movl %esp, %ebp
|
||||||
|
|
||||||
/* This function is called with regparm=0 and we have
|
/* This function is called with regparm=0 and we have
|
||||||
* to skip the 32 byte from pushal:
|
* to skip the 32 byte from pushal. Hence start at 36.
|
||||||
*/
|
*/
|
||||||
movl 36(%ebp), %ecx
|
|
||||||
|
/* entry point */
|
||||||
|
movl 36(%ebp), %eax
|
||||||
|
movw %ax, __lcall_instr + 1
|
||||||
|
andl $0xffff0000, %eax
|
||||||
|
shrl $4, %eax
|
||||||
|
movw %ax, __lcall_instr + 3
|
||||||
|
|
||||||
|
/* initial register values */
|
||||||
|
movl 40(%ebp), %eax
|
||||||
|
movl %eax, __registers + 0x00 /* eax */
|
||||||
|
movl 44(%ebp), %eax
|
||||||
|
movl %eax, __registers + 0x04 /* ebx */
|
||||||
|
movl 48(%ebp), %eax
|
||||||
|
movl %eax, __registers + 0x08 /* ecx */
|
||||||
|
movl 52(%ebp), %eax
|
||||||
|
movl %eax, __registers + 0x0c /* edx */
|
||||||
|
movl 56(%ebp), %eax
|
||||||
|
movl %eax, __registers + 0x10 /* esi */
|
||||||
|
movl 60(%ebp), %eax
|
||||||
|
movl %eax, __registers + 0x14 /* esi */
|
||||||
|
|
||||||
/* Activate the right segment descriptor real mode. */
|
/* Activate the right segment descriptor real mode. */
|
||||||
ljmp $0x28, $RELOCATED(1f)
|
ljmp $0x28, $RELOCATED(1f)
|
||||||
|
@ -120,11 +148,18 @@ __run_optionrom = RELOCATED(.)
|
||||||
mov $0x40, %ax
|
mov $0x40, %ax
|
||||||
mov %ax, %ds
|
mov %ax, %ds
|
||||||
|
|
||||||
|
/* initialize registers for option rom lcall */
|
||||||
|
movl __registers + 0, %eax
|
||||||
|
movl __registers + 4, %ebx
|
||||||
|
movl __registers + 8, %ecx
|
||||||
|
movl __registers + 12, %edx
|
||||||
|
movl __registers + 16, %esi
|
||||||
|
movl __registers + 20, %edi
|
||||||
|
|
||||||
/* ************************************ */
|
/* ************************************ */
|
||||||
mov %cx, %ax // restore ax
|
__lcall_instr = RELOCATED(.)
|
||||||
// TODO this will not work for non-VGA option ROMs
|
.byte 0x9a
|
||||||
/* run VGA BIOS at 0xc000:0003 */
|
.word 0x0000, 0x0000
|
||||||
lcall $0xc000, $0x0003
|
|
||||||
/* ************************************ */
|
/* ************************************ */
|
||||||
|
|
||||||
/* If we got here, just about done.
|
/* If we got here, just about done.
|
||||||
|
@ -151,126 +186,47 @@ __run_optionrom = RELOCATED(.)
|
||||||
lidt idtarg
|
lidt idtarg
|
||||||
|
|
||||||
/* and exit */
|
/* and exit */
|
||||||
mov __stack, %esp
|
movl __stack, %esp
|
||||||
popal
|
popal
|
||||||
|
|
||||||
|
// TODO return AX from OPROM call
|
||||||
ret
|
ret
|
||||||
|
|
||||||
#if defined(CONFIG_GEODE_VSA) && CONFIG_GEODE_VSA
|
.globl __realmode_interrupt
|
||||||
#define VSA2_ENTRY_POINT 0x60020
|
__realmode_interrupt = RELOCATED(.)
|
||||||
|
|
||||||
.globl __run_vsa
|
|
||||||
__run_vsa = RELOCATED(.)
|
|
||||||
/* save all registers to the stack */
|
/* save all registers to the stack */
|
||||||
pushal
|
pushal
|
||||||
|
|
||||||
/* Move the protected mode stack to a safe place */
|
|
||||||
mov %esp, __stack
|
|
||||||
|
|
||||||
movl %esp, %ebp
|
|
||||||
/* This function is called with regparm=0 and we have
|
|
||||||
* to skip the 32 byte from pushal:
|
|
||||||
*/
|
|
||||||
movl 36(%ebp), %ecx
|
|
||||||
movl 40(%ebp), %edx
|
|
||||||
|
|
||||||
/* Activate the right segment descriptor real mode. */
|
|
||||||
ljmp $0x28, $RELOCATED(1f)
|
|
||||||
1:
|
|
||||||
.code16
|
|
||||||
/* 16 bit code from here on... */
|
|
||||||
|
|
||||||
/* Load the segment registers w/ properly configured
|
|
||||||
* segment descriptors. They will retain these
|
|
||||||
* configurations (limits, writability, etc.) once
|
|
||||||
* protected mode is turned off.
|
|
||||||
*/
|
|
||||||
mov $0x30, %ax
|
|
||||||
mov %ax, %ds
|
|
||||||
mov %ax, %es
|
|
||||||
mov %ax, %fs
|
|
||||||
mov %ax, %gs
|
|
||||||
mov %ax, %ss
|
|
||||||
|
|
||||||
/* Turn off protection */
|
|
||||||
movl %cr0, %eax
|
|
||||||
andl $~PE, %eax
|
|
||||||
movl %eax, %cr0
|
|
||||||
|
|
||||||
/* Now really going into real mode */
|
|
||||||
ljmp $0, $RELOCATED(1f)
|
|
||||||
1:
|
|
||||||
/* Setup a stack: Put the stack at the end of page zero.
|
|
||||||
* That way we can easily share it between real and
|
|
||||||
* protected, since the 16 bit ESP at segment 0 will
|
|
||||||
* work for any case. */
|
|
||||||
mov $0x0, %ax
|
|
||||||
mov %ax, %ss
|
|
||||||
movl $0x1000, %eax
|
|
||||||
movl %eax, %esp
|
|
||||||
|
|
||||||
/* Load our 16 bit idt */
|
|
||||||
xor %ax, %ax
|
|
||||||
mov %ax, %ds
|
|
||||||
lidt __realmode_idt
|
|
||||||
|
|
||||||
/* Set all segments to 0x0000, ds to 0x0040 */
|
|
||||||
mov %ax, %es
|
|
||||||
mov %ax, %fs
|
|
||||||
mov %ax, %gs
|
|
||||||
mov $0x40, %ax
|
|
||||||
mov %ax, %ds
|
|
||||||
mov %cx, %ax // restore ax
|
|
||||||
|
|
||||||
/* ************************************ */
|
|
||||||
lcall $((VSA2_ENTRY_POINT & 0xffff0000) >> 4), $(VSA2_ENTRY_POINT & 0xffff)
|
|
||||||
/* ************************************ */
|
|
||||||
|
|
||||||
/* If we got here, just about done.
|
|
||||||
* Need to get back to protected mode
|
|
||||||
*/
|
|
||||||
movl %cr0, %eax
|
|
||||||
orl $PE, %eax
|
|
||||||
movl %eax, %cr0
|
|
||||||
|
|
||||||
/* Now that we are in protected mode
|
|
||||||
* jump to a 32 bit code segment.
|
|
||||||
*/
|
|
||||||
data32 ljmp $0x10, $RELOCATED(1f)
|
|
||||||
1:
|
|
||||||
.code32
|
|
||||||
movw $0x18, %ax
|
|
||||||
mov %ax, %ds
|
|
||||||
mov %ax, %es
|
|
||||||
mov %ax, %fs
|
|
||||||
mov %ax, %gs
|
|
||||||
mov %ax, %ss
|
|
||||||
|
|
||||||
/* restore proper idt */
|
|
||||||
lidt idtarg
|
|
||||||
|
|
||||||
/* and exit */
|
|
||||||
mov __stack, %esp
|
|
||||||
popal
|
|
||||||
ret
|
|
||||||
#endif
|
|
||||||
|
|
||||||
.globl __run_interrupt
|
|
||||||
__run_interrupt = RELOCATED(.)
|
|
||||||
|
|
||||||
pushal
|
|
||||||
/* save the stack */
|
/* save the stack */
|
||||||
mov %esp, __stack
|
movl %esp, __stack
|
||||||
|
movl %esp, %ebp
|
||||||
|
|
||||||
|
/* This function is called with regparm=0 and we have
|
||||||
|
* to skip the 32 byte from pushal. Hence start at 36.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* prepare interrupt calling code */
|
||||||
|
movl 36(%ebp), %eax
|
||||||
|
movb %al, __intXX_instr + 1 /* intno */
|
||||||
|
|
||||||
|
/* initial register values */
|
||||||
|
movl 40(%ebp), %eax
|
||||||
|
movl %eax, __registers + 0x00 /* eax */
|
||||||
|
movl 44(%ebp), %eax
|
||||||
|
movl %eax, __registers + 0x04 /* ebx */
|
||||||
|
movl 48(%ebp), %eax
|
||||||
|
movl %eax, __registers + 0x08 /* ecx */
|
||||||
|
movl 52(%ebp), %eax
|
||||||
|
movl %eax, __registers + 0x0c /* edx */
|
||||||
|
movl 56(%ebp), %eax
|
||||||
|
movl %eax, __registers + 0x10 /* esi */
|
||||||
|
movl 60(%ebp), %eax
|
||||||
|
movl %eax, __registers + 0x14 /* esi */
|
||||||
|
|
||||||
/* This configures CS properly for real mode. */
|
/* This configures CS properly for real mode. */
|
||||||
ljmp $0x28, $RELOCATED(1f)
|
ljmp $0x28, $RELOCATED(1f)
|
||||||
1:
|
1:
|
||||||
.code16 /* 16 bit code from here on... */
|
.code16 /* 16 bit code from here on... */
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
movb $0xec, %al
|
|
||||||
outb %al, $0x80
|
|
||||||
|
|
||||||
/* Load the segment registers w/ properly configured segment
|
/* Load the segment registers w/ properly configured segment
|
||||||
* descriptors. They will retain these configurations (limits,
|
* descriptors. They will retain these configurations (limits,
|
||||||
* writability, etc.) once protected mode is turned off.
|
* writability, etc.) once protected mode is turned off.
|
||||||
|
@ -291,9 +247,9 @@ __run_interrupt = RELOCATED(.)
|
||||||
data32 ljmp $0, $RELOCATED(1f)
|
data32 ljmp $0, $RELOCATED(1f)
|
||||||
1:
|
1:
|
||||||
|
|
||||||
/* put the stack at the end of page zero.
|
/* put the stack at the end of page zero. That way we can easily
|
||||||
* that way we can easily share it between real and protected,
|
* share it between real mode and protected mode, because %esp and
|
||||||
* since the 16-bit ESP at segment 0 will work for any case.
|
* %ss:%sp point to the same memory.
|
||||||
*/
|
*/
|
||||||
/* setup a stack */
|
/* setup a stack */
|
||||||
mov $0x0, %ax
|
mov $0x0, %ax
|
||||||
|
@ -312,18 +268,16 @@ __run_interrupt = RELOCATED(.)
|
||||||
mov %ax, %fs
|
mov %ax, %fs
|
||||||
mov %ax, %gs
|
mov %ax, %gs
|
||||||
|
|
||||||
/* Call VGA BIOS int10 function 0x4f14 to enable main console
|
/* initialize registers for intXX call */
|
||||||
* Epia-M does not always autosence the main console so forcing
|
movl __registers + 0, %eax
|
||||||
* it on is good.
|
movl __registers + 4, %ebx
|
||||||
*/
|
movl __registers + 8, %ecx
|
||||||
|
movl __registers + 12, %edx
|
||||||
|
movl __registers + 16, %esi
|
||||||
|
movl __registers + 20, %edi
|
||||||
|
|
||||||
/* Ask VGA option rom to enable main console */
|
__intXX_instr = RELOCATED(.)
|
||||||
movw $0x4f14,%ax
|
.byte 0xcd, 0x00 /* This becomes intXX */
|
||||||
movw $0x8003,%bx
|
|
||||||
movw $1, %cx
|
|
||||||
movw $0, %dx
|
|
||||||
movw $0, %di
|
|
||||||
int $0x10
|
|
||||||
|
|
||||||
/* Ok, the job is done, now go back to protected mode coreboot */
|
/* Ok, the job is done, now go back to protected mode coreboot */
|
||||||
movl %cr0, %eax
|
movl %cr0, %eax
|
||||||
|
@ -345,13 +299,15 @@ __run_interrupt = RELOCATED(.)
|
||||||
lidt idtarg
|
lidt idtarg
|
||||||
|
|
||||||
/* Exit */
|
/* Exit */
|
||||||
mov __stack, %esp
|
movl __stack, %esp
|
||||||
popal
|
popal
|
||||||
ret
|
ret
|
||||||
|
|
||||||
/* This is the 16-bit interrupt entry point called by the IDT stub code.
|
/* This is the 16-bit interrupt entry point called by the IDT stub code.
|
||||||
|
*
|
||||||
* Before this code code is called, %eax is pushed to the stack, and the
|
* Before this code code is called, %eax is pushed to the stack, and the
|
||||||
* interrupt number is loaded into %al
|
* interrupt number is loaded into %al. On return this function cleans up
|
||||||
|
* for its caller.
|
||||||
*/
|
*/
|
||||||
.code16
|
.code16
|
||||||
__interrupt_handler_16bit = RELOCATED(.)
|
__interrupt_handler_16bit = RELOCATED(.)
|
||||||
|
|
|
@ -144,6 +144,17 @@ static void write_protect_vgabios(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void vga_enable_console(void)
|
||||||
|
{
|
||||||
|
/* Call VGA BIOS int10 function 0x4f14 to enable main console
|
||||||
|
* Epia-M does not always autosense the main console so forcing
|
||||||
|
* it on is good.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* int#, EAX, EBX, ECX, EDX, ESI, EDI */
|
||||||
|
realmode_interrupt(0x10, 0x4f1f, 0x8003, 0x0001, 0x0000, 0x0000, 0x0000);
|
||||||
|
}
|
||||||
|
|
||||||
static void vga_init(device_t dev)
|
static void vga_init(device_t dev)
|
||||||
{
|
{
|
||||||
u8 reg8;
|
u8 reg8;
|
||||||
|
@ -166,9 +177,6 @@ static void vga_init(device_t dev)
|
||||||
if (pci_read_config32(dev, PCI_ROM_ADDRESS) != 0xc0000) return;
|
if (pci_read_config32(dev, PCI_ROM_ADDRESS) != 0xc0000) return;
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "Enable VGA console\n");
|
printk(BIOS_DEBUG, "Enable VGA console\n");
|
||||||
// this is how it should look:
|
|
||||||
// call_bios_interrupt(0x10,0x4f1f,0x8003,1,0);
|
|
||||||
// this is how it looks:
|
|
||||||
vga_enable_console();
|
vga_enable_console();
|
||||||
|
|
||||||
/* It's not clear if these need to be programmed before or after
|
/* It's not clear if these need to be programmed before or after
|
||||||
|
|
|
@ -21,6 +21,6 @@
|
||||||
#define NORTHBRIDGE_VIA_CX700_H
|
#define NORTHBRIDGE_VIA_CX700_H
|
||||||
|
|
||||||
extern unsigned int cx700_scan_root_bus(device_t root, unsigned int max);
|
extern unsigned int cx700_scan_root_bus(device_t root, unsigned int max);
|
||||||
extern void (*vga_enable_console)(void) __attribute__((regparm(0)));
|
extern void (*realmode_interrupt)(u32 intno, u32 eax, u32 ebx, u32 ecx, u32 edx,
|
||||||
|
u32 esi, u32 edi) __attribute__((regparm(0)));
|
||||||
#endif /* NORTHBRIDGE_VIA_CX700_H */
|
#endif /* NORTHBRIDGE_VIA_CX700_H */
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define NORTHBRIDGE_VIA_VT8623_H
|
#define NORTHBRIDGE_VIA_VT8623_H
|
||||||
|
|
||||||
unsigned int vt8623_scan_root_bus(device_t root, unsigned int max);
|
unsigned int vt8623_scan_root_bus(device_t root, unsigned int max);
|
||||||
extern void (*vga_enable_console)(void) __attribute__((regparm(0)));
|
extern void (*realmode_interrupt)(u32 intno, u32 eax, u32 ebx, u32 ecx, u32 edx,
|
||||||
void write_protect_vgabios(void);
|
u32 esi, u32 edi) __attribute__((regparm(0)));
|
||||||
|
|
||||||
#endif /* NORTHBRIDGE_VIA_VT8623_H */
|
#endif /* NORTHBRIDGE_VIA_VT8623_H */
|
||||||
|
|
|
@ -72,7 +72,8 @@ static int via_vt8623_int15_handler(struct eregs *regs)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_protect_vgabios(void)
|
#ifdef UNUSED_CODE
|
||||||
|
static void write_protect_vgabios(void)
|
||||||
{
|
{
|
||||||
device_t dev;
|
device_t dev;
|
||||||
|
|
||||||
|
@ -86,6 +87,7 @@ void write_protect_vgabios(void)
|
||||||
if (dev)
|
if (dev)
|
||||||
pci_write_config8(dev, 0x61, 0xaa);
|
pci_write_config8(dev, 0x61, 0xaa);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void vga_random_fixup(device_t dev)
|
static void vga_random_fixup(device_t dev)
|
||||||
{
|
{
|
||||||
|
@ -96,6 +98,17 @@ static void vga_random_fixup(device_t dev)
|
||||||
pci_write_config32(dev,0x14,0xdc000000);
|
pci_write_config32(dev,0x14,0xdc000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vga_enable_console(void)
|
||||||
|
{
|
||||||
|
/* Call VGA BIOS int10 function 0x4f14 to enable main console
|
||||||
|
* Epia-M does not always autosense the main console so forcing
|
||||||
|
* it on is good.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* int#, EAX, EBX, ECX, EDX, ESI, EDI */
|
||||||
|
realmode_interrupt(0x10, 0x4f1f, 0x8003, 0x0001, 0x0000, 0x0000, 0x0000);
|
||||||
|
}
|
||||||
|
|
||||||
static void vga_init(device_t dev)
|
static void vga_init(device_t dev)
|
||||||
{
|
{
|
||||||
vga_random_fixup(dev);
|
vga_random_fixup(dev);
|
||||||
|
@ -118,9 +131,6 @@ static void vga_init(device_t dev)
|
||||||
pci_dev_init(dev);
|
pci_dev_init(dev);
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "Enable VGA console\n");
|
printk(BIOS_DEBUG, "Enable VGA console\n");
|
||||||
// this is how it should look:
|
|
||||||
// call_bios_interrupt(0x10,0x4f1f,0x8003,1,0);
|
|
||||||
// this is how it looks:
|
|
||||||
vga_enable_console();
|
vga_enable_console();
|
||||||
|
|
||||||
#ifdef MEASURE_VGA_INIT_TIME
|
#ifdef MEASURE_VGA_INIT_TIME
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define NORTHBRIDGE_VIA_VX800_H
|
#define NORTHBRIDGE_VIA_VX800_H
|
||||||
|
|
||||||
extern unsigned int vx800_scan_root_bus(device_t root, unsigned int max);
|
extern unsigned int vx800_scan_root_bus(device_t root, unsigned int max);
|
||||||
extern void (*vga_enable_console)(void) __attribute__((regparm(0)));
|
extern void (*realmode_interrupt)(u32 intno, u32 eax, u32 ebx, u32 ecx, u32 edx,
|
||||||
|
u32 esi, u32 edi) __attribute__((regparm(0)));
|
||||||
|
|
||||||
#endif /* NORTHBRIDGE_VIA_VX800_H */
|
#endif /* NORTHBRIDGE_VIA_VX800_H */
|
||||||
|
|
|
@ -127,7 +127,7 @@ static int via_vx800_int15_handler(struct eregs *regs)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef UNUSED_CODE
|
#ifdef UNUSED_CODE
|
||||||
void write_protect_vgabios(void)
|
static void write_protect_vgabios(void)
|
||||||
{
|
{
|
||||||
device_t dev;
|
device_t dev;
|
||||||
|
|
||||||
|
@ -144,6 +144,17 @@ void write_protect_vgabios(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void vga_enable_console(void)
|
||||||
|
{
|
||||||
|
/* Call VGA BIOS int10 function 0x4f14 to enable main console
|
||||||
|
* Epia-M does not always autosense the main console so forcing
|
||||||
|
* it on is good.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* int#, EAX, EBX, ECX, EDX, ESI, EDI */
|
||||||
|
realmode_interrupt(0x10, 0x4f1f, 0x8003, 0x0001, 0x0000, 0x0000, 0x0000);
|
||||||
|
}
|
||||||
|
|
||||||
extern u8 acpi_sleep_type;
|
extern u8 acpi_sleep_type;
|
||||||
static void vga_init(device_t dev)
|
static void vga_init(device_t dev)
|
||||||
{
|
{
|
||||||
|
@ -170,9 +181,6 @@ static void vga_init(device_t dev)
|
||||||
pci_dev_init(dev);
|
pci_dev_init(dev);
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "Enable VGA console\n");
|
printk(BIOS_DEBUG, "Enable VGA console\n");
|
||||||
// this is how it should look:
|
|
||||||
// call_bios_interrupt(0x10,0x4f1f,0x8003,1,0);
|
|
||||||
// this is how it looks:
|
|
||||||
vga_enable_console();
|
vga_enable_console();
|
||||||
|
|
||||||
if ((acpi_sleep_type == 3)/* || (PAYLOAD_IS_SEABIOS == 0)*/) {
|
if ((acpi_sleep_type == 3)/* || (PAYLOAD_IS_SEABIOS == 0)*/) {
|
||||||
|
|
Loading…
Reference in New Issue