1 // Rom layout and bios assembler to C interface.
3 // Copyright (C) 2008-2012 Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2002 MandrakeSoft S.A.
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
8 #include "asm-offsets.h" // BREGS_*
9 #include "config.h" // CONFIG_*
10 #include "entryfuncs.S" // ENTRY_*
11 #include "hw/rtc.h" // CMOS_RESET_CODE
12 #include "x86.h" // CR0_*
17 /****************************************************************
18 * 16bit / 32bit call trampolines
19 ****************************************************************/
21 // Place CPU into 32bit mode from 16bit mode.
22 // %edx = return location (in 32bit mode)
23 // Clobbers: ecx, flags, segment registers, cr0, idt/gdt
25 .global transition32_nmi_off
27 // Disable irqs (and clear direction flag)
33 movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
34 outb %al, $PORT_CMOS_INDEX
35 inb $PORT_CMOS_DATA, %al
39 orb $A20_ENABLE_BIT, %al
44 // Set segment descriptors
45 lidtw %cs:pmode_IDT_info
46 lgdtw %cs:rombios32_gdt_48
48 // Enable protected mode
50 andl $~(CR0_PG|CR0_CD|CR0_NW), %ecx
54 // start 32bit protected mode code
55 ljmpl $SEG32_MODE32_CS, $(BUILD_BIOS_ADDR + 1f)
59 1: movl $SEG32_MODE32_DS, %ecx
69 // Place CPU into 16bit mode from 32bit mode.
70 // %edx = return location (in 16bit mode)
71 // Clobbers: ecx, flags, segment registers, cr0, idt/gdt
73 .global transition16big
76 // Reset data segment limits
77 movl $SEG32_MODE16_DS, %ecx
85 ljmpw $SEG32_MODE16_CS, $1f
88 movl $SEG32_MODE16BIG_DS, %ecx
95 ljmpw $SEG32_MODE16BIG_CS, $1f
98 // Disable protected mode
103 // far jump to flush CPU queue after transition to real mode
106 // restore IDT to normal real-mode defaults
107 2: lidtw %cs:rmode_IDT_info
109 // Clear segment registers
115 movw %cx, %ss // Assume stack is in segment 0
120 /****************************************************************
121 * External calling trampolines
122 ****************************************************************/
124 // Far call a 16bit function from 16bit mode with a specified cpu register state
125 // %eax = address of struct bregs, %edx = segment of struct bregs
126 // Clobbers: %e[bc]x, %e[ds]i, flags
129 // Save %edx/%eax, %ebp
134 // Setup for iretw call
137 pushw $1f // return point
138 pushw BREGS_flags(%eax) // flags
139 pushl BREGS_code(%eax) // CS:IP
141 // Load calling registers and invoke call
143 iretw // XXX - just do a lcalll
145 // Store flags, es, eax
152 movl 0x0c(%esp), %eax
154 popw BREGS_flags(%eax)
156 movw %cx, %ds // Restore %ds == %ss
158 // Remove %edx/%eax, restore %ebp
166 .macro IRQ_TRAMPOLINE num
167 DECLFUNC irq_trampoline_0x\num
168 irq_trampoline_0x\num :
184 /****************************************************************
185 * Misc. entry points.
186 ****************************************************************/
188 // Entry point for QEMU smi interrupts.
191 // Transition to 32bit mode.
192 movl $1f + BUILD_BIOS_ADDR, %edx
193 jmp transition32_nmi_off
195 1: movl $BUILD_SMM_ADDR + 0x8000, %esp
196 calll _cfunc32flat_handle_smi - BUILD_BIOS_ADDR
200 // Entry point for QEMU smp sipi interrupts.
203 // Transition to 32bit mode.
206 movl $2f + BUILD_BIOS_ADDR, %edx
207 jmp transition32_nmi_off
209 // Acquire lock and take ownership of shared stack
211 2: lock btsl $0, SMPLock
215 calll _cfunc32flat_handle_smp - BUILD_BIOS_ADDR
216 // Release lock and halt processor.
222 // Resume (and reboot) entry point - called from entry_post
223 DECLFUNC entry_resume
225 // Disable interrupts
228 // Use the ExtraStack in low mem.
229 movl $_zonelow_seg, %eax
232 movl $ExtraStack + BUILD_EXTRA_STACK_SIZE, %esp
239 pushl %esp // Backup %esp, then clear high bits
241 pushfl // Save registers clobbered by C code
245 movl %ss, %ecx // Move %ss to %ds
248 movl $_cfunc32flat_handle_pmm, %eax // Setup: call32(handle_pmm, args, -1)
249 leal PUSHBREGS_size+12(%esp, %ecx), %edx // %edx points to start of args
252 movw %ax, BREGS_eax(%esp) // Modify %ax:%dx to return %eax
254 movw %ax, BREGS_edx(%esp)
261 DECLFUNC entry_pnp_real
262 .global entry_pnp_prot
267 pushl %esp // Backup %esp, then clear high bits
270 pushfl // Save registers clobbered by C code
274 movw %ss, %cx // Move %ss to %ds
276 leal PUSHBREGS_size+12(%esp), %eax // %eax points to start of u16 args
278 movw %ax, BREGS_eax(%esp) // Modify %eax to return %ax
290 addw $4, %sp // pop dummy
291 popfw // restore flags
299 pushl %cs // Move second descriptor after %cs to %gs
302 ENTRY_ARG_ESP _cfunc32seg_handle_apm
308 // PCI-BIOS entry points
309 DECLFUNC entry_pcibios32
313 pushl %gs // Backup %gs and set %gs=%ds
316 ENTRY_ARG_ESP _cfunc32seg_handle_pcibios
322 DECLFUNC entry_pcibios16
324 ENTRY_ARG handle_pcibios
327 // int 1589 entry point
330 ENTRY_ARG handle_1589
334 DECLFUNC entry_bios32
339 // Check for PCI-BIOS request
340 cmpl $0x49435024, %eax // $PCI
342 movl $BUILD_BIOS_ADDR, %ebx
343 movl $BUILD_BIOS_SIZE, %ecx
344 movl $entry_pcibios32, %edx
355 // 32bit elf entry point
361 movl %eax, entry_elf_eax
362 movl %ebx, entry_elf_ebx
363 lidtl (BUILD_BIOS_ADDR + pmode_IDT_info)
364 lgdtl (BUILD_BIOS_ADDR + rombios32_gdt_48)
365 movl $SEG32_MODE32_DS, %eax
371 movl $BUILD_STACK_ADDR, %esp
372 ljmpl $SEG32_MODE32_CS, $_cfunc32flat_handle_post
375 // UEFI Compatibility Support Module (CSM) entry point
378 // Backup register state
385 // Backup stack location and convert to a "flat pointer"
387 movw %ax, BREGS_code+2(%esp) // Store %ss in bregs->code.seg
391 // Change to BUILD_STACK_ADDR stack and call handle_csm(bregs)
392 ENTRY_INTO32 _cfunc32flat_handle_csm
394 DECLFUNC __csm_return
401 // Switch back to original stack
402 1: movzwl BREGS_code+2(%eax), %edx
409 // Restore register state and return.
411 addw $4, %sp // pop dummy
416 /****************************************************************
417 * Interrupt entry points
418 ****************************************************************/
420 // Main entry point for hardware interrupts handled on extra stack
421 DECLFUNC irqentry_extrastack
425 pushw %ds // Set %ds:%eax to space on ExtraStack
427 movl $_zonelow_seg, %eax
430 subl $PUSHBREGS_size+8, %eax
433 movl %esp, PUSHBREGS_size(%eax)
434 movw %ss, PUSHBREGS_size+4(%eax)
436 movw %ds, %dx // Setup %ss/%esp and call function
441 movl %esp, %eax // Restore registers and return
442 movw PUSHBREGS_size+4(%eax), %ss
443 movl PUSHBREGS_size(%eax), %esp
447 // Main entry point for software interrupts handled on extra stack
448 DECLFUNC irqentry_arg_extrastack
449 irqentry_arg_extrastack:
452 pushw %ds // Set %ds:%eax to space on ExtraStack
454 movl $_zonelow_seg, %eax
457 subl $PUSHBREGS_size+16, %eax
458 SAVEBREGS_POP_DSEAX // Save registers on extra stack
460 movl %esp, PUSHBREGS_size+8(%eax)
461 movw %ss, PUSHBREGS_size+12(%eax)
462 popl BREGS_code(%eax)
463 popw BREGS_flags(%eax)
465 movw %ds, %dx // Setup %ss/%esp and call function
470 movl %esp, %eax // Restore registers and return
471 movw PUSHBREGS_size+12(%eax), %ss
472 movl PUSHBREGS_size+8(%eax), %esp
475 pushw BREGS_flags(%eax)
476 pushl BREGS_code(%eax)
480 // Main entry point for software interrupts (using caller's stack)
481 DECLFUNC irqentry_arg
486 // Helper macros for hardware interrupt declaration
491 jmp irqentry_extrastack
494 .macro DECL_IRQ_ENTRY num
499 // Helper macros for software interrupt declaration
500 .macro IRQ_ENTRY_ARG num
504 #if CONFIG_ENTRY_EXTRASTACK
505 jmp irqentry_arg_extrastack
511 .macro DECL_IRQ_ENTRY_ARG num
516 // Various entry points (that don't require a fixed location).
517 DECL_IRQ_ENTRY_ARG 13
522 DECL_IRQ_ENTRY hwpic1
523 DECL_IRQ_ENTRY hwpic2
525 // int 18/19 are special - they reset stack and call into 32bit mode.
528 ENTRY_INTO32 _cfunc32flat_handle_19
532 ENTRY_INTO32 _cfunc32flat_handle_18
535 /****************************************************************
536 * Fixed position entry points
537 ****************************************************************/
539 // Specify a location in the fixed part of bios area.
541 .section .fixedaddr.\addr
546 cmpl $0, %cs:HaveRunPost // Check for resume/reboot
548 ENTRY_INTO32 _cfunc32flat_handle_post // Normal entry point
553 ENTRY handle_02 // NMI handler does not switch onto extra stack
557 .global entry_13_official
561 // 0xe401 - OldFDPT in misc.c
564 .global entry_19_official
568 // 0xe6f5 - BIOS_CONFIG_TABLE in misc.c
570 // 0xe729 - BaudTable in misc.c
587 // 0xefc7 - diskette_param_table in misc.c
594 // XXX - INT 10 Functions 0-Fh Entry Point
600 // 0xf0a4 - VideoParams in misc.c
609 .global entry_15_official
612 je entry_1589 // 1589 calls return in protected mode
615 // 0xfa6e - vgafont8 in font.c
618 .global entry_1a_official
621 je entry_pcibios16 // PCIBIOS calls can be in protected mode
627 // 0xfef3 - InitVectors in misc.c
630 .global entry_iret_official
637 ORG 0xfff0 // Power-up Entry Point
640 ljmpw $SEG_BIOS, $entry_post
642 // 0xfff5 - BiosDate in misc.c
644 // 0xfffe - BiosModelId in misc.c
646 // 0xffff - BiosChecksum in misc.c