mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
latest greatest vga support
This commit is contained in:
parent
4401103644
commit
ee9d9e75ac
2 changed files with 110 additions and 98 deletions
|
@ -176,7 +176,7 @@ biosint(
|
||||||
printk_debug("\n");
|
printk_debug("\n");
|
||||||
}
|
}
|
||||||
printk_debug("biosint: Bailing out\n");
|
printk_debug("biosint: Bailing out\n");
|
||||||
// "longjmp"
|
// Should be replaced by longjmp for generalization.
|
||||||
vga_exit();
|
vga_exit();
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_PCIBIOS
|
#ifdef CONFIG_PCIBIOS
|
||||||
|
@ -230,14 +230,23 @@ setup_realmode_idt(void) {
|
||||||
*intbyte = i;
|
*intbyte = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fixed entry points
|
// Support for fixed entry points
|
||||||
|
|
||||||
// VGA BIOSes tend to hardcode f000:f065 as the previous handler of
|
// First off, fill 0xCC (breakpoint) from f000:e000 to f000:ffff
|
||||||
// int10.
|
// so we can catch the calls to unimplemented entry points.
|
||||||
|
// This 8KB area is where the fixed entry points are at.
|
||||||
|
// Maybe the original IBM PC had only this much of ROM.
|
||||||
|
memset((void *) 0xfe000, 0xCC, 0x2000);
|
||||||
|
|
||||||
|
// VGA BIOSes tend to hardcode f000:f065 as the default handler for
|
||||||
|
// int10.
|
||||||
// calling convention here is the same as INTs, we can reuse
|
// calling convention here is the same as INTs, we can reuse
|
||||||
// the int entry code.
|
// the int entry code.
|
||||||
codeptr = (char*) 0xff065;
|
codeptr = (char*) 0xff065;
|
||||||
memcpy(codeptr, &idthandle, codesize);
|
memcpy(codeptr, &idthandle, codesize);
|
||||||
intbyte = codeptr + 3;
|
intbyte = codeptr + 3;
|
||||||
*intbyte = 0x42; /* int42 is the relocated int10 */
|
*intbyte = 0x42; /* int42 is the relocated int10 */
|
||||||
|
|
||||||
|
// Clear the BIOS Data Area, not to confuse the realmode code.
|
||||||
|
memset((void *) 0x400, 0, 0x100);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,92 +68,96 @@ static char rcsid[] = "$Id$";
|
||||||
#if (CONFIG_VGABIOS == 1)
|
#if (CONFIG_VGABIOS == 1)
|
||||||
|
|
||||||
|
|
||||||
/* The address arguments to this function are PHYSICAL ADDRESSES */
|
extern void real_mode_switch_call_vga(unsigned long busdevfn);
|
||||||
static void real_mode_switch_call_vga(unsigned long devfn)
|
|
||||||
{
|
|
||||||
__asm__ __volatile__
|
|
||||||
(
|
|
||||||
// paranoia -- does ecx get saved? not sure. This is
|
|
||||||
// the easiest safe thing to do.
|
|
||||||
"pushal\n"
|
|
||||||
/* save the stack */
|
|
||||||
"mov %esp, __stack\n"
|
|
||||||
"jmp 1f\n"
|
|
||||||
"__stack: .long 0\n"
|
|
||||||
"1:\n"
|
|
||||||
/* get devfn into %ecx */
|
|
||||||
"movl %esp, %ebp\n"
|
|
||||||
"movl 8(%ebp), %ecx\n"
|
|
||||||
/* This configures CS properly for real mode. */
|
|
||||||
" ljmp $0x28, $__rms_16bit\n"
|
|
||||||
"__rms_16bit: \n"
|
|
||||||
".code16 \n" /* 16 bit code from here on... */
|
|
||||||
|
|
||||||
/* Load the segment registers w/ properly configured segment
|
__asm__ (
|
||||||
* descriptors. They will retain these configurations (limits,
|
".text\n"
|
||||||
* writability, etc.) once protected mode is turned off. */
|
"__stack:\n"
|
||||||
" mov $0x30, %ax \n"
|
" .long 0\n"
|
||||||
" mov %ax, %ds \n"
|
"real_mode_switch_call_vga:\n"
|
||||||
" mov %ax, %es \n"
|
" pushl %ebp\n"
|
||||||
" mov %ax, %fs \n"
|
" movl %esp, %ebp\n"
|
||||||
" mov %ax, %gs \n"
|
/* Save callee-saved registers, since we don't know what VGABIOS would break */
|
||||||
" mov %ax, %ss \n"
|
" pushl %ebx\n"
|
||||||
|
" pushl %esi\n"
|
||||||
|
" pushl %edi\n"
|
||||||
|
/* Get busdevfn in %ecx */
|
||||||
|
" movl 8(%ebp), %ecx\n"
|
||||||
|
/* Save the stack */
|
||||||
|
" mov %esp, __stack\n"
|
||||||
|
/* This configures CS properly for real mode. */
|
||||||
|
" ljmp $0x28, $1f\n"
|
||||||
|
"1:\n"
|
||||||
|
".code16\n" /* 16 bit code from here on... */
|
||||||
|
|
||||||
/* Turn off protection (bit 0 in CR0) */
|
/* Load the segment registers w/ properly configured segment
|
||||||
" movl %cr0, %eax \n"
|
* descriptors. They will retain these configurations (limits,
|
||||||
" andl $0xFFFFFFFE, %eax \n"
|
* writability, etc.) once protected mode is turned off. */
|
||||||
" movl %eax, %cr0 \n"
|
" movw $0x30, %ax\n"
|
||||||
|
" movw %ax, %ds\n"
|
||||||
|
" movw %ax, %es\n"
|
||||||
|
" movw %ax, %fs\n"
|
||||||
|
" movw %ax, %gs\n"
|
||||||
|
" movw %ax, %ss\n"
|
||||||
|
|
||||||
/* Now really going into real mode */
|
/* Turn off protection (bit 0 in CR0) */
|
||||||
" ljmp $0, $__rms_real \n"
|
" movl %cr0, %eax\n"
|
||||||
"__rms_real: \n"
|
" andl $0xFFFFFFFE, %eax\n"
|
||||||
|
" movl %eax, %cr0\n"
|
||||||
|
|
||||||
// put the stack at the end of page zero.
|
/* Now really going into real mode */
|
||||||
// that way we can easily share it between real and protected,
|
" ljmp $0, $1f\n"
|
||||||
// since the 16-bit ESP at segment 0 will work for any case.
|
"1:\n"
|
||||||
/* Setup a stack */
|
|
||||||
" mov $0x0, %ax \n"
|
|
||||||
" mov %ax, %ss \n"
|
|
||||||
" movl $0x1000, %eax \n"
|
|
||||||
" movl %eax, %esp \n"
|
|
||||||
/* debugging for RGM */
|
|
||||||
" mov $0x11, %al \n"
|
|
||||||
" outb %al, $0x80\n"
|
|
||||||
|
|
||||||
/* Dump zeros in the other segregs */
|
// put the stack at the end of page zero.
|
||||||
" xor %ax, %ax \n"
|
// that way we can easily share it between real and protected,
|
||||||
" mov %ax, %ds \n"
|
// since the 16-bit ESP at segment 0 will work for any case.
|
||||||
" mov %ax, %es \n"
|
/* Setup a stack */
|
||||||
" mov %ax, %fs \n"
|
" xorw %ax, %ax\n"
|
||||||
" mov %ax, %gs \n"
|
" movw %ax, %ss\n"
|
||||||
" mov %cx, %ax \n"
|
" movl $0x1000, %esp\n"
|
||||||
" .byte 0x9a, 0x03, 0, 0, 0xc0 \n"
|
/* debugging for RGM */
|
||||||
" movb $0x55, %al\noutb %al, $0x80\n"
|
" movb $0x11, %al\n"
|
||||||
/* if we got here, just about done.
|
" outb %al, $0x80\n"
|
||||||
* Need to get back to protected mode */
|
|
||||||
"movl %cr0, %eax\n"
|
/* Dump zeros in the other segregs */
|
||||||
// "andl $0x7FFAFFD1, %eax\n" /* PG,AM,WP,NE,TS,EM,MP = 0 */
|
" xorw %ax, %ax\n"
|
||||||
// "orl $0x60000001, %eax\n" /* CD, NW, PE = 1 */
|
" movw %ax, %ds\n"
|
||||||
"orl $0x0000001, %eax\n" /* PE = 1 */
|
" movw %ax, %es\n"
|
||||||
"movl %eax, %cr0\n"
|
" movw %ax, %fs\n"
|
||||||
/* Now that we are in protected mode jump to a 32 bit code segment. */
|
" movw %ax, %gs\n"
|
||||||
"data32 ljmp $0x10, $vgarestart\n"
|
/* Set bus/devfn to %ax */
|
||||||
"vgarestart:\n"
|
" movw %cx, %ax\n"
|
||||||
".code32\n"
|
/* Now do the deed */
|
||||||
" movw $0x18, %ax \n"
|
" lcallw $0xc000, $0x0003\n"
|
||||||
" mov %ax, %ds \n"
|
/* debugging for RGM */
|
||||||
" mov %ax, %es \n"
|
" movb $0x55, %al\n"
|
||||||
" mov %ax, %fs \n"
|
" outb %al, $0x80\n"
|
||||||
" mov %ax, %gs \n"
|
/* if we got here, just about done.
|
||||||
" mov %ax, %ss \n"
|
* Need to get back to protected mode */
|
||||||
".globl vga_exit\n"
|
" movl %cr0, %eax\n"
|
||||||
"vga_exit:\n"
|
" orl $0x0000001, %eax\n" /* PE = 1 */
|
||||||
" mov __stack, %esp\n"
|
" movl %eax, %cr0\n"
|
||||||
" popal\n"
|
/* Now that we are in protected mode jump to a 32 bit code segment. */
|
||||||
);
|
" ljmpl $0x10, $1f\n"
|
||||||
}
|
"1:\n"
|
||||||
__asm__ (".text\n""real_mode_switch_end:\n");
|
".code32\n"
|
||||||
extern char real_mode_switch_end[];
|
" movw $0x18, %ax\n"
|
||||||
|
" movw %ax, %ds\n"
|
||||||
|
" movw %ax, %es\n"
|
||||||
|
" movw %ax, %fs\n"
|
||||||
|
" movw %ax, %gs\n"
|
||||||
|
" movw %ax, %ss\n"
|
||||||
|
/* Emergency exit */
|
||||||
|
".globl vga_exit\n"
|
||||||
|
"vga_exit:\n"
|
||||||
|
" movl __stack, %esp\n"
|
||||||
|
" popl %edi\n"
|
||||||
|
" popl %esi\n"
|
||||||
|
" popl %ebx\n"
|
||||||
|
" popl %ebp\n"
|
||||||
|
" ret\n"
|
||||||
|
);
|
||||||
|
|
||||||
void
|
void
|
||||||
do_vgabios(void)
|
do_vgabios(void)
|
||||||
|
@ -165,15 +169,6 @@ do_vgabios(void)
|
||||||
unsigned int size = 64*1024;
|
unsigned int size = 64*1024;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0x400; i<0x500; i++) {
|
|
||||||
printk_debug("%02x%c", *(unsigned char *)i, i%16==15 ? '\n' : ' ');
|
|
||||||
*(unsigned char *) i = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0x400; i<0x500; i++) {
|
|
||||||
printk_debug("%02x%c", *(unsigned char *)i, i%16==15 ? '\n' : ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
dev = pci_find_class(PCI_CLASS_DISPLAY_VGA <<8, NULL);
|
dev = pci_find_class(PCI_CLASS_DISPLAY_VGA <<8, NULL);
|
||||||
|
|
||||||
if (! dev) {
|
if (! dev) {
|
||||||
|
@ -192,15 +187,23 @@ for (i=0x400; i<0x500; i++) {
|
||||||
pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom|1);
|
pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom|1);
|
||||||
printk_debug("rom base, size: %x\n", rom);
|
printk_debug("rom base, size: %x\n", rom);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
buf = (unsigned char *) rom;
|
buf = (unsigned char *) rom;
|
||||||
if ((buf[0] == 0x55) && (buf[1] = 0xaa)) {
|
if ((buf[0] == 0x55) && (buf[1] == 0xaa)) {
|
||||||
|
|
||||||
memcpy((void *) 0xc0000, buf, size);
|
memcpy((void *) 0xc0000, buf, size);
|
||||||
|
|
||||||
for(i = 0; i < 16; i++)
|
for(i = 0; i < 16; i++)
|
||||||
printk_debug("0x%x ", buf[i]);
|
printk_debug("0x%x ", buf[i]);
|
||||||
// check signature here later!
|
// check signature again
|
||||||
busdevfn = (dev->bus->secondary << 8) | dev->devfn;
|
buf = (unsigned char *) 0xc0000;
|
||||||
real_mode_switch_call_vga(busdevfn);
|
if (buf[0]==0x55 && buf[1]==0xAA) {
|
||||||
|
busdevfn = (dev->bus->secondary << 8) | dev->devfn;
|
||||||
|
printk_debug("bus/devfn = %#x\n", busdevfn);
|
||||||
|
|
||||||
|
real_mode_switch_call_vga(busdevfn);
|
||||||
|
} else
|
||||||
|
printk_debug("Failed to copy VGA BIOS to 0xc0000\n");
|
||||||
} else
|
} else
|
||||||
printk_debug("BAD SIGNATURE 0x%x 0x%x\n", buf[0], buf[1]);
|
printk_debug("BAD SIGNATURE 0x%x 0x%x\n", buf[0], buf[1]);
|
||||||
#ifndef VGABIOS_START
|
#ifndef VGABIOS_START
|
||||||
|
|
Loading…
Add table
Reference in a new issue