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
26 // transition32 when NMI and A20 are already initialized
32 // Disable irqs (and clear direction flag)
37 movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
38 outb %al, $PORT_CMOS_INDEX
39 inb $PORT_CMOS_DATA, %al
43 orb $A20_ENABLE_BIT, %al
46 // Set segment descriptors
47 1: lidtw %cs:pmode_IDT_info
48 lgdtw %cs:rombios32_gdt_48
50 // Enable protected mode
55 // start 32bit protected mode code
56 ljmpl $SEG32_MODE32_CS, $(BUILD_BIOS_ADDR + 2f)
60 2: movl $SEG32_MODE32_DS, %eax
71 // Place CPU into 16bit mode from 32bit mode.
72 // %edx = return location (in 16bit mode)
73 // Clobbers: ecx, flags, segment registers, cr0, idt/gdt
75 .global transition16big
80 // restore data segment limits to 0xffff
81 movl $SEG32_MODE16_DS, %eax
88 #if CONFIG_DISABLE_A20
91 andb $~A20_ENABLE_BIT, %al
96 ljmpw $SEG32_MODE16_CS, $1f
101 movl $SEG32_MODE16BIG_DS, %eax
108 ljmpw $SEG32_MODE16BIG_CS, $1f
112 // Disable protected mode
117 // far jump to flush CPU queue after transition to real mode
121 // restore IDT to normal real-mode defaults
122 lidtw %cs:rmode_IDT_info
124 // Clear segment registers
130 movw %ax, %ss // Assume stack is in segment 0
136 /****************************************************************
137 * External calling trampolines
138 ****************************************************************/
140 // Far call a 16bit function from 16bit mode with a specified cpu register state
141 // %eax = address of struct bregs, %edx = segment of struct bregs
142 // Clobbers: %e[bc]x, %e[ds]i, flags
145 // Save %edx/%eax, %ebp
150 // Setup for iretw call
153 pushw $1f // return point
154 pushw BREGS_flags(%eax) // flags
155 pushl BREGS_code(%eax) // CS:IP
157 // Load calling registers and invoke call
159 iretw // XXX - just do a lcalll
161 // Store flags, es, eax
168 movl 0x0c(%esp), %eax
170 popw BREGS_flags(%eax)
172 movw %cx, %ds // Restore %ds == %ss
174 // Remove %edx/%eax, restore %ebp
182 .macro IRQ_TRAMPOLINE num
183 DECLFUNC irq_trampoline_0x\num
184 irq_trampoline_0x\num :
200 /****************************************************************
201 * Misc. entry points.
202 ****************************************************************/
204 // Entry point for QEMU smi interrupts.
207 // Transition to 32bit mode.
208 movl $1f + BUILD_BIOS_ADDR, %edx
209 jmp transition32_nmi_off
211 1: movl $BUILD_SMM_ADDR + 0x8000, %esp
212 calll _cfunc32flat_handle_smi - BUILD_BIOS_ADDR
216 // Entry point for QEMU smp sipi interrupts.
219 // Transition to 32bit mode.
222 movl $2f + BUILD_BIOS_ADDR, %edx
223 jmp transition32_nmi_off
225 // Acquire lock and take ownership of shared stack
227 2: lock btsl $0, SMPLock
231 calll _cfunc32flat_handle_smp - BUILD_BIOS_ADDR
232 // Release lock and halt processor.
238 // Resume (and reboot) entry point - called from entry_post
239 DECLFUNC entry_resume
241 // Disable interrupts
244 // Use the ExtraStack in low mem.
245 movl $_zonelow_seg, %eax
248 movl $ExtraStack + BUILD_EXTRA_STACK_SIZE, %esp
255 pushl %esp // Backup %esp, then clear high bits
257 pushfl // Save registers clobbered by C code
261 movl %ss, %ecx // Move %ss to %ds
264 movl $_cfunc32flat_handle_pmm, %eax // Setup: call32(handle_pmm, args, -1)
265 leal PUSHBREGS_size+12(%esp, %ecx), %edx // %edx points to start of args
268 movw %ax, BREGS_eax(%esp) // Modify %ax:%dx to return %eax
270 movw %ax, BREGS_edx(%esp)
277 DECLFUNC entry_pnp_real
278 .global entry_pnp_prot
283 pushl %esp // Backup %esp, then clear high bits
286 pushfl // Save registers clobbered by C code
290 movw %ss, %cx // Move %ss to %ds
292 leal PUSHBREGS_size+12(%esp), %eax // %eax points to start of u16 args
294 movw %ax, BREGS_eax(%esp) // Modify %eax to return %ax
306 addw $4, %sp // pop dummy
307 popfw // restore flags
315 pushl %cs // Move second descriptor after %cs to %gs
318 ENTRY_ARG_ESP _cfunc32seg_handle_apm
324 // PCI-BIOS entry points
325 DECLFUNC entry_pcibios32
329 pushl %gs // Backup %gs and set %gs=%ds
332 ENTRY_ARG_ESP _cfunc32seg_handle_pcibios
338 DECLFUNC entry_pcibios16
340 ENTRY_ARG handle_pcibios
343 // int 1589 entry point
346 ENTRY_ARG handle_1589
350 DECLFUNC entry_bios32
355 // Check for PCI-BIOS request
356 cmpl $0x49435024, %eax // $PCI
358 movl $BUILD_BIOS_ADDR, %ebx
359 movl $BUILD_BIOS_SIZE, %ecx
360 movl $entry_pcibios32, %edx
371 // 32bit elf entry point
377 lidtl (BUILD_BIOS_ADDR + pmode_IDT_info)
378 lgdtl (BUILD_BIOS_ADDR + rombios32_gdt_48)
379 movl $SEG32_MODE32_DS, %eax
385 movl $BUILD_STACK_ADDR, %esp
386 ljmpl $SEG32_MODE32_CS, $_cfunc32flat_handle_post
389 // UEFI Compatibility Support Module (CSM) entry point
392 // Backup register state
399 // Backup stack location and convert to a "flat pointer"
401 movw %ax, BREGS_code+2(%esp) // Store %ss in bregs->code.seg
405 // Change to BUILD_STACK_ADDR stack and call handle_csm(bregs)
406 ENTRY_INTO32 _cfunc32flat_handle_csm
408 DECLFUNC __csm_return
415 // Switch back to original stack
416 1: movzwl BREGS_code+2(%eax), %edx
423 // Restore register state and return.
425 addw $4, %sp // pop dummy
430 /****************************************************************
431 * Interrupt entry points
432 ****************************************************************/
434 // Main entry point for hardware interrupts handled on extra stack
435 DECLFUNC irqentry_extrastack
439 pushw %ds // Set %ds:%eax to space on ExtraStack
441 movl $_zonelow_seg, %eax
444 subl $PUSHBREGS_size+8, %eax
447 movl %esp, PUSHBREGS_size(%eax)
448 movw %ss, PUSHBREGS_size+4(%eax)
450 movw %ds, %dx // Setup %ss/%esp and call function
455 movl %esp, %eax // Restore registers and return
456 movw PUSHBREGS_size+4(%eax), %ss
457 movl PUSHBREGS_size(%eax), %esp
461 // Main entry point for software interrupts handled on extra stack
462 DECLFUNC irqentry_arg_extrastack
463 irqentry_arg_extrastack:
466 pushw %ds // Set %ds:%eax to space on ExtraStack
468 movl $_zonelow_seg, %eax
471 subl $PUSHBREGS_size+16, %eax
472 SAVEBREGS_POP_DSEAX // Save registers on extra stack
474 movl %esp, PUSHBREGS_size+8(%eax)
475 movw %ss, PUSHBREGS_size+12(%eax)
476 popl BREGS_code(%eax)
477 popw BREGS_flags(%eax)
479 movw %ds, %dx // Setup %ss/%esp and call function
484 movl %esp, %eax // Restore registers and return
485 movw PUSHBREGS_size+12(%eax), %ss
486 movl PUSHBREGS_size+8(%eax), %esp
489 pushw BREGS_flags(%eax)
490 pushl BREGS_code(%eax)
494 // Main entry point for software interrupts (using caller's stack)
495 DECLFUNC irqentry_arg
500 // Helper macros for hardware interrupt declaration
505 jmp irqentry_extrastack
508 .macro DECL_IRQ_ENTRY num
513 // Helper macros for software interrupt declaration
514 .macro IRQ_ENTRY_ARG num
518 #if CONFIG_ENTRY_EXTRASTACK
519 jmp irqentry_arg_extrastack
525 .macro DECL_IRQ_ENTRY_ARG num
530 // Various entry points (that don't require a fixed location).
531 DECL_IRQ_ENTRY_ARG 13
536 DECL_IRQ_ENTRY hwpic1
537 DECL_IRQ_ENTRY hwpic2
539 // int 18/19 are special - they reset stack and call into 32bit mode.
542 ENTRY_INTO32 _cfunc32flat_handle_19
546 ENTRY_INTO32 _cfunc32flat_handle_18
549 /****************************************************************
550 * Fixed position entry points
551 ****************************************************************/
553 // Specify a location in the fixed part of bios area.
555 .section .fixedaddr.\addr
560 cmpl $0, %cs:HaveRunPost // Check for resume/reboot
562 ENTRY_INTO32 _cfunc32flat_handle_post // Normal entry point
568 .global entry_13_official
572 // 0xe401 - OldFDPT in misc.c
575 .global entry_19_official
579 // 0xe6f5 - BIOS_CONFIG_TABLE in misc.c
581 // 0xe729 - BaudTable in misc.c
598 // 0xefc7 - diskette_param_table in misc.c
605 // XXX - INT 10 Functions 0-Fh Entry Point
611 // 0xf0a4 - VideoParams in misc.c
620 .global entry_15_official
623 je entry_1589 // 1589 calls return in protected mode
626 // 0xfa6e - vgafont8 in font.c
629 .global entry_1a_official
632 je entry_pcibios16 // PCIBIOS calls can be in protected mode
638 // 0xfef3 - InitVectors in misc.c
641 .global entry_iret_official
648 ORG 0xfff0 // Power-up Entry Point
651 ljmpw $SEG_BIOS, $entry_post
653 // 0xfff5 - BiosDate in misc.c
655 // 0xfffe - BiosModelId in misc.c
657 // 0xffff - BiosChecksum in misc.c