X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fdevices%2Foprom%2Fx86_asm.S;h=488bfa6b912e625eae5b56cc4319a053e0e78839;hb=5ff7c13e858a31addf1558731a12cf6c753b576d;hp=616aa8675f7a6b3c4cbededa8a3fbabc05b14ca9;hpb=859e94a30420c726a0043a00a73abb946cfb94c3;p=coreboot.git diff --git a/src/devices/oprom/x86_asm.S b/src/devices/oprom/x86_asm.S index 616aa8675..488bfa6b9 100644 --- a/src/devices/oprom/x86_asm.S +++ b/src/devices/oprom/x86_asm.S @@ -1,7 +1,7 @@ /* * 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 * it under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ /* This is the intXX interrupt handler stub code. It gets copied * to the IDT and to some fixed addresses in the F segment. Before - * the code can used, it gets patched up by the C function copying + * the code can used, it gets patched up by the C function copying * it: byte 3 (the $0 in movb $0, %al) is overwritten with the int#. */ @@ -49,29 +49,62 @@ __realmode_code: /* Realmode IDT pointer structure. */ .globl __realmode_idt __realmode_idt = RELOCATED(.) - .word 1023 /* 16-bit limit */ - .long 0 /* 24-bit base */ + .word 1023 /* 16 bit limit */ + .long 0 /* 24 bit base */ .word 0 /* Preserve old stack */ __stack = RELOCATED(.) .long 0 +/* Register store for realmode_call and realmode_interrupt */ +__registers = RELOCATED(.) + .long 0 /* 0 - EAX */ + .long 0 /* 4 - EBX */ + .long 0 /* 8 - ECX */ + .long 0 /* 12 - EDX */ + .long 0 /* 16 - ESI */ + .long 0 /* 20 - EDI */ + +/* 256 byte buffer, used by int10 */ + .globl __buffer +__buffer = RELOCATED(.) + .skip 256 + .code32 - .globl __run_optionrom -__run_optionrom = RELOCATED(.) + .globl __realmode_call +__realmode_call = RELOCATED(.) /* save all registers to the stack */ pushal /* Move the protected mode stack to a safe place */ - mov %esp, __stack - - /* Get devfn into %ecx */ + movl %esp, __stack movl %esp, %ebp + /* 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 + mov %ax, __lcall_instr + 1 + andl $0xffff0000, %eax + shrl $4, %eax + mov %ax, __lcall_instr + 3 + + /* initial register values */ + movl 40(%ebp), %eax + movl %eax, __registers + 0 /* eax */ + movl 44(%ebp), %eax + movl %eax, __registers + 4 /* ebx */ + movl 48(%ebp), %eax + movl %eax, __registers + 8 /* ecx */ + movl 52(%ebp), %eax + movl %eax, __registers + 12 /* edx */ + movl 56(%ebp), %eax + movl %eax, __registers + 16 /* esi */ + movl 60(%ebp), %eax + movl %eax, __registers + 20 /* edi */ /* Activate the right segment descriptor real mode. */ ljmp $0x28, $RELOCATED(1f) @@ -85,11 +118,11 @@ __run_optionrom = RELOCATED(.) * protected mode is turned off. */ mov $0x30, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - mov %ax, %ss + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + mov %ax, %ss /* Turn off protection */ movl %cr0, %eax @@ -101,34 +134,44 @@ __run_optionrom = RELOCATED(.) 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 + * 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 */ + /* Load 16 bit IDT */ xor %ax, %ax mov %ax, %ds lidt __realmode_idt + /* 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 + /* Set all segments to 0x0000, ds to 0x0040 */ - mov %ax, %es - mov %ax, %fs - mov %ax, %gs + push %ax + xor %ax, %ax + mov %ax, %es + mov %ax, %fs + mov %ax, %gs mov $0x40, %ax mov %ax, %ds - mov %cx, %ax // restore ax + pop %ax /* ************************************ */ - // TODO this will not work for non-VGA option ROMs - /* run VGA BIOS at 0xc000:0003 */ - lcall $0xc000, $0x0003 +__lcall_instr = RELOCATED(.) + .byte 0x9a + .word 0x0000, 0x0000 /* ************************************ */ - /* If we got here, just about done. - * Need to get back to protected mode + /* If we got here, we are just about done. + * Need to get back to protected mode. */ movl %cr0, %eax orl $PE, %eax @@ -140,8 +183,8 @@ __run_optionrom = RELOCATED(.) data32 ljmp $0x10, $RELOCATED(1f) 1: .code32 - movw $0x18, %ax - mov %ax, %ds + mov $0x18, %ax + mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %gs @@ -151,52 +194,70 @@ __run_optionrom = RELOCATED(.) lidt idtarg /* and exit */ - mov __stack, %esp + movl __stack, %esp popal - ret - .globl __run_interrupt -__run_interrupt = RELOCATED(.) + // TODO return AX from OPROM call + ret - /* paranoia -- does ecx get saved? not sure. This is - * the easiest safe thing to do. */ + .globl __realmode_interrupt +__realmode_interrupt = RELOCATED(.) + /* save all registers to the stack */ pushal /* 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 + 0 /* eax */ + movl 44(%ebp), %eax + movl %eax, __registers + 4 /* ebx */ + movl 48(%ebp), %eax + movl %eax, __registers + 8 /* ecx */ + movl 52(%ebp), %eax + movl %eax, __registers + 12 /* edx */ + movl 56(%ebp), %eax + movl %eax, __registers + 16 /* esi */ + movl 60(%ebp), %eax + movl %eax, __registers + 20 /* edi */ /* This configures CS properly for real mode. */ ljmp $0x28, $RELOCATED(1f) 1: .code16 /* 16 bit code from here on... */ - // DEBUG - movb $0xec, %al - outb %al, $0x80 - /* 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 + mov $0x30, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + mov %ax, %ss /* Turn off protected mode */ - movl %cr0, %eax + movl %cr0, %eax andl $~PE, %eax - movl %eax, %cr0 + movl %eax, %cr0 /* Now really going into real mode */ data32 ljmp $0, $RELOCATED(1f) 1: - /* 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. + /* put the stack at the end of page zero. That way we can easily + * share it between real mode and protected mode, because %esp and + * %ss:%sp point to the same memory. */ /* setup a stack */ mov $0x0, %ax @@ -205,28 +266,29 @@ __run_interrupt = RELOCATED(.) movl %eax, %esp /* Load 16-bit intXX IDT */ - xor %ax, %ax + xor %ax, %ax mov %ax, %ds lidt __realmode_idt + /* initialize registers for intXX call */ + movl __registers + 0, %eax + movl __registers + 4, %ebx + movl __registers + 8, %ecx + movl __registers + 12, %edx + movl __registers + 16, %esi + movl __registers + 20, %edi + /* Set all segments to 0x0000 */ + push %ax + xor %ax, %ax mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %gs + pop %ax - /* Call VGA BIOS int10 function 0x4f14 to enable main console - * Epia-M does not always autosence the main console so forcing - * it on is good. - */ - - /* Ask VGA option rom to enable main console */ - movw $0x4f14,%ax - movw $0x8003,%bx - movw $1, %cx - movw $0, %dx - movw $0, %di - int $0x10 +__intXX_instr = RELOCATED(.) + .byte 0xcd, 0x00 /* This becomes intXX */ /* Ok, the job is done, now go back to protected mode coreboot */ movl %cr0, %eax @@ -237,7 +299,7 @@ __run_interrupt = RELOCATED(.) data32 ljmp $0x10, $RELOCATED(1f) 1: .code32 - movw $0x18, %ax + mov $0x18, %ax mov %ax, %ds mov %ax, %es mov %ax, %fs @@ -248,13 +310,15 @@ __run_interrupt = RELOCATED(.) lidt idtarg /* Exit */ - mov __stack, %esp + movl __stack, %esp popal ret /* 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 - * interrupt number is loaded into %al + * interrupt number is loaded into %al. On return this function cleans up + * for its caller. */ .code16 __interrupt_handler_16bit = RELOCATED(.) @@ -278,7 +342,7 @@ __interrupt_handler_16bit = RELOCATED(.) data32 ljmp $0x10, $RELOCATED(1f) 1: .code32 - movw $0x18, %ax + mov $0x18, %ax mov %ax, %ds mov %ax, %es mov %ax, %fs @@ -318,18 +382,11 @@ __interrupt_handler_16bit = RELOCATED(.) mov $0x0, %ax mov %ax, %ss - /* Restore 16-bit IDT */ + /* Restore 16 bit IDT */ xor %ax, %ax mov %ax, %ds lidt __realmode_idt - /* Set up our segment registers to segment 0x0000 */ - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - mov $0x40, %ax - mov %ax, %ds - /* Restore all registers, including those * manipulated by the C handler */