Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / seabios / src / romlayout.S
1 // Rom layout and bios assembler to C interface.
2 //
3 // Copyright (C) 2008-2012  Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2002  MandrakeSoft S.A.
5 //
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
7
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_*
13
14         .code16
15
16
17 /****************************************************************
18  * 16bit / 32bit call trampolines
19  ****************************************************************/
20
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
24         DECLFUNC transition32
25 transition32_nmi_off:
26         // transition32 when NMI and A20 are already initialized
27         movl %eax, %ecx
28         jmp 1f
29 transition32:
30         movl %eax, %ecx
31
32         // Disable irqs (and clear direction flag)
33         cli
34         cld
35
36         // Disable nmi
37         movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
38         outb %al, $PORT_CMOS_INDEX
39         inb $PORT_CMOS_DATA, %al
40
41         // enable a20
42         inb $PORT_A20, %al
43         orb $A20_ENABLE_BIT, %al
44         outb %al, $PORT_A20
45
46         // Set segment descriptors
47 1:      lidtw %cs:pmode_IDT_info
48         lgdtw %cs:rombios32_gdt_48
49
50         // Enable protected mode
51         movl %cr0, %eax
52         orl $CR0_PE, %eax
53         movl %eax, %cr0
54
55         // start 32bit protected mode code
56         ljmpl $SEG32_MODE32_CS, $(BUILD_BIOS_ADDR + 2f)
57
58         .code32
59         // init data segments
60 2:      movl $SEG32_MODE32_DS, %eax
61         movw %ax, %ds
62         movw %ax, %es
63         movw %ax, %ss
64         movw %ax, %fs
65         movw %ax, %gs
66
67         movl %ecx, %eax
68         jmpl *%edx
69         .code16
70
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
74         DECLFUNC transition16
75         .global transition16big
76         .code32
77 transition16:
78         movl %eax, %ecx
79
80         // restore data segment limits to 0xffff
81         movl $SEG32_MODE16_DS, %eax
82         movw %ax, %ds
83         movw %ax, %es
84         movw %ax, %ss
85         movw %ax, %fs
86         movw %ax, %gs
87
88 #if CONFIG_DISABLE_A20
89         // disable a20
90         inb $PORT_A20, %al
91         andb $~A20_ENABLE_BIT, %al
92         outb %al, $PORT_A20
93 #endif
94
95         // Jump to 16bit mode
96         ljmpw $SEG32_MODE16_CS, $1f
97
98 transition16big:
99         movl %eax, %ecx
100
101         movl $SEG32_MODE16BIG_DS, %eax
102         movw %ax, %ds
103         movw %ax, %es
104         movw %ax, %ss
105         movw %ax, %fs
106         movw %ax, %gs
107
108         ljmpw $SEG32_MODE16BIG_CS, $1f
109
110         .code16
111 1:
112         // Disable protected mode
113         movl %cr0, %eax
114         andl $~CR0_PE, %eax
115         movl %eax, %cr0
116
117         // far jump to flush CPU queue after transition to real mode
118         ljmpw $SEG_BIOS, $2f
119
120 2:
121         // restore IDT to normal real-mode defaults
122         lidtw %cs:rmode_IDT_info
123
124         // Clear segment registers
125         xorw %ax, %ax
126         movw %ax, %fs
127         movw %ax, %gs
128         movw %ax, %es
129         movw %ax, %ds
130         movw %ax, %ss  // Assume stack is in segment 0
131
132         movl %ecx, %eax
133         jmpl *%edx
134
135
136 /****************************************************************
137  * External calling trampolines
138  ****************************************************************/
139
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
143         DECLFUNC __farcall16
144 __farcall16:
145         // Save %edx/%eax, %ebp
146         pushl %ebp
147         pushl %eax
148         pushl %edx
149
150         // Setup for iretw call
151         movl %edx, %ds
152         pushw %cs
153         pushw $1f                       // return point
154         pushw BREGS_flags(%eax)         // flags
155         pushl BREGS_code(%eax)          // CS:IP
156
157         // Load calling registers and invoke call
158         RESTOREBREGS_DSEAX
159         iretw                           // XXX - just do a lcalll
160 1:
161         // Store flags, es, eax
162         pushfw
163         cli
164         cld
165         pushw %ds
166         pushl %eax
167         movw 0x08(%esp), %ds
168         movl 0x0c(%esp), %eax
169         SAVEBREGS_POP_DSEAX
170         popw BREGS_flags(%eax)
171         movw %ss, %cx
172         movw %cx, %ds                   // Restore %ds == %ss
173
174         // Remove %edx/%eax, restore %ebp
175         popl %edx
176         popl %eax
177         popl %ebp
178
179         retl
180
181 // IRQ trampolines
182         .macro IRQ_TRAMPOLINE num
183         DECLFUNC irq_trampoline_0x\num
184         irq_trampoline_0x\num :
185         int $0x\num
186         lretw
187         .endm
188
189         IRQ_TRAMPOLINE 02
190         IRQ_TRAMPOLINE 10
191         IRQ_TRAMPOLINE 13
192         IRQ_TRAMPOLINE 15
193         IRQ_TRAMPOLINE 16
194         IRQ_TRAMPOLINE 18
195         IRQ_TRAMPOLINE 19
196         IRQ_TRAMPOLINE 1c
197         IRQ_TRAMPOLINE 4a
198
199
200 /****************************************************************
201  * Misc. entry points.
202  ****************************************************************/
203
204 // Entry point for QEMU smi interrupts.
205         DECLFUNC entry_smi
206 entry_smi:
207         // Transition to 32bit mode.
208         movl $1f + BUILD_BIOS_ADDR, %edx
209         jmp transition32_nmi_off
210         .code32
211 1:      movl $BUILD_SMM_ADDR + 0x8000, %esp
212         calll _cfunc32flat_handle_smi - BUILD_BIOS_ADDR
213         rsm
214         .code16
215
216 // Entry point for QEMU smp sipi interrupts.
217         DECLFUNC entry_smp
218 entry_smp:
219         // Transition to 32bit mode.
220         cli
221         cld
222         movl $2f + BUILD_BIOS_ADDR, %edx
223         jmp transition32_nmi_off
224         .code32
225         // Acquire lock and take ownership of shared stack
226 1:      rep ; nop
227 2:      lock btsl $0, SMPLock
228         jc 1b
229         movl SMPStack, %esp
230         // Call handle_smp
231         calll _cfunc32flat_handle_smp - BUILD_BIOS_ADDR
232         // Release lock and halt processor.
233         movl $0, SMPLock
234 3:      hlt
235         jmp 3b
236         .code16
237
238 // Resume (and reboot) entry point - called from entry_post
239         DECLFUNC entry_resume
240 entry_resume:
241         // Disable interrupts
242         cli
243         cld
244         // Use the ExtraStack in low mem.
245         movl $_zonelow_seg, %eax
246         movw %ax, %ds
247         movw %ax, %ss
248         movl $ExtraStack + BUILD_EXTRA_STACK_SIZE, %esp
249         // Call handler.
250         jmp handle_resume
251
252 // PMM entry point
253         DECLFUNC entry_pmm
254 entry_pmm:
255         pushl %esp              // Backup %esp, then clear high bits
256         movzwl %sp, %esp
257         pushfl                  // Save registers clobbered by C code
258         cli
259         cld
260         PUSHBREGS
261         movl %ss, %ecx          // Move %ss to %ds
262         movw %cx, %ds
263         shll $4, %ecx
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
266         movl $-1, %ecx
267         calll call32
268         movw %ax, BREGS_eax(%esp)       // Modify %ax:%dx to return %eax
269         shrl $16, %eax
270         movw %ax, BREGS_edx(%esp)
271         POPBREGS
272         popfl
273         popl %esp
274         lretw
275
276 // PnP entry points
277         DECLFUNC entry_pnp_real
278         .global entry_pnp_prot
279 entry_pnp_prot:
280         pushl %esp
281         jmp 1f
282 entry_pnp_real:
283         pushl %esp              // Backup %esp, then clear high bits
284         movzwl %sp, %esp
285 1:
286         pushfl                  // Save registers clobbered by C code
287         cli
288         cld
289         PUSHBREGS
290         movw %ss, %cx           // Move %ss to %ds
291         movw %cx, %ds
292         leal PUSHBREGS_size+12(%esp), %eax  // %eax points to start of u16 args
293         calll handle_pnp
294         movw %ax, BREGS_eax(%esp)   // Modify %eax to return %ax
295         POPBREGS
296         popfl
297         popl %esp
298         lretw
299
300 // APM entry points
301         DECLFUNC entry_apm16
302 entry_apm16:
303         pushfw          // save flags
304         pushl %eax      // dummy
305         ENTRY_ARG handle_apm
306         addw $4, %sp    // pop dummy
307         popfw           // restore flags
308         lretw
309
310         DECLFUNC entry_apm32
311         .code32
312 entry_apm32:
313         pushfl
314         pushl %gs
315         pushl %cs               // Move second descriptor after %cs to %gs
316         addl $16, (%esp)
317         popl %gs
318         ENTRY_ARG_ESP _cfunc32seg_handle_apm
319         popl %gs
320         popfl
321         lretl
322         .code16
323
324 // PCI-BIOS entry points
325         DECLFUNC entry_pcibios32
326         .code32
327 entry_pcibios32:
328         pushfl
329         pushl %gs               // Backup %gs and set %gs=%ds
330         pushl %ds
331         popl %gs
332         ENTRY_ARG_ESP _cfunc32seg_handle_pcibios
333         popl %gs
334         popfl
335         lretl
336         .code16
337
338         DECLFUNC entry_pcibios16
339 entry_pcibios16:
340         ENTRY_ARG handle_pcibios
341         iretw
342
343 // int 1589 entry point
344         DECLFUNC entry_1589
345 entry_1589:
346         ENTRY_ARG handle_1589
347         iretw
348
349 // BIOS32 support
350         DECLFUNC entry_bios32
351         .code32
352 entry_bios32:
353         pushfl
354 #if CONFIG_PCIBIOS
355         // Check for PCI-BIOS request
356         cmpl $0x49435024, %eax // $PCI
357         jne 1f
358         movl $BUILD_BIOS_ADDR, %ebx
359         movl $BUILD_BIOS_SIZE, %ecx
360         movl $entry_pcibios32, %edx
361         xorb %al, %al
362         jmp 2f
363 #endif
364         // Unknown request
365 1:      movb $0x80, %al
366         // Return to caller
367 2:      popfl
368         lretl
369         .code16
370
371 // 32bit elf entry point
372         DECLFUNC entry_elf
373         .code32
374 entry_elf:
375         cli
376         cld
377         lidtl (BUILD_BIOS_ADDR + pmode_IDT_info)
378         lgdtl (BUILD_BIOS_ADDR + rombios32_gdt_48)
379         movl $SEG32_MODE32_DS, %eax
380         movw %ax, %ds
381         movw %ax, %es
382         movw %ax, %fs
383         movw %ax, %gs
384         movw %ax, %ss
385         movl $BUILD_STACK_ADDR, %esp
386         ljmpl $SEG32_MODE32_CS, $_cfunc32flat_handle_post
387         .code16
388
389 // UEFI Compatibility Support Module (CSM) entry point
390         DECLFUNC entry_csm
391 entry_csm:
392         // Backup register state
393         pushfw
394         cli
395         cld
396         pushl %eax                      // dummy
397         PUSHBREGS
398
399         // Backup stack location and convert to a "flat pointer"
400         movl %ss, %eax
401         movw %ax, BREGS_code+2(%esp)    // Store %ss in bregs->code.seg
402         shll $4, %eax
403         addl %esp, %eax
404
405         // Change to BUILD_STACK_ADDR stack and call handle_csm(bregs)
406         ENTRY_INTO32 _cfunc32flat_handle_csm
407
408         DECLFUNC __csm_return
409         .code32
410 __csm_return:
411         movl $1f, %edx
412         jmp transition16big
413         .code16
414
415         // Switch back to original stack
416 1:      movzwl BREGS_code+2(%eax), %edx
417         movl %edx, %ecx
418         shll $4, %ecx
419         subl %ecx, %eax
420         movl %edx, %ss
421         movl %eax, %esp
422
423         // Restore register state and return.
424         POPBREGS
425         addw $4, %sp                    // pop dummy
426         popfw
427         lretw
428
429
430 /****************************************************************
431  * Interrupt entry points
432  ****************************************************************/
433
434         // Main entry point for hardware interrupts handled on extra stack
435         DECLFUNC irqentry_extrastack
436 irqentry_extrastack:
437         cli
438         cld
439         pushw %ds               // Set %ds:%eax to space on ExtraStack
440         pushl %eax
441         movl $_zonelow_seg, %eax
442         movl %eax, %ds
443         movl StackPos, %eax
444         subl $PUSHBREGS_size+8, %eax
445         SAVEBREGS_POP_DSEAX
446         popl %ecx
447         movl %esp, PUSHBREGS_size(%eax)
448         movw %ss, PUSHBREGS_size+4(%eax)
449
450         movw %ds, %dx           // Setup %ss/%esp and call function
451         movw %dx, %ss
452         movl %eax, %esp
453         calll *%ecx
454
455         movl %esp, %eax         // Restore registers and return
456         movw PUSHBREGS_size+4(%eax), %ss
457         movl PUSHBREGS_size(%eax), %esp
458         RESTOREBREGS_DSEAX
459         iretw
460
461         // Main entry point for software interrupts handled on extra stack
462         DECLFUNC irqentry_arg_extrastack
463 irqentry_arg_extrastack:
464         cli
465         cld
466         pushw %ds               // Set %ds:%eax to space on ExtraStack
467         pushl %eax
468         movl $_zonelow_seg, %eax
469         movl %eax, %ds
470         movl StackPos, %eax
471         subl $PUSHBREGS_size+16, %eax
472         SAVEBREGS_POP_DSEAX     // Save registers on extra stack
473         popl %ecx
474         movl %esp, PUSHBREGS_size+8(%eax)
475         movw %ss, PUSHBREGS_size+12(%eax)
476         popl BREGS_code(%eax)
477         popw BREGS_flags(%eax)
478
479         movw %ds, %dx           // Setup %ss/%esp and call function
480         movw %dx, %ss
481         movl %eax, %esp
482         calll *%ecx
483
484         movl %esp, %eax         // Restore registers and return
485         movw PUSHBREGS_size+12(%eax), %ss
486         movl PUSHBREGS_size+8(%eax), %esp
487         popl %edx
488         popw %dx
489         pushw BREGS_flags(%eax)
490         pushl BREGS_code(%eax)
491         RESTOREBREGS_DSEAX
492         iretw
493
494         // Main entry point for software interrupts (using caller's stack)
495         DECLFUNC irqentry_arg
496 irqentry_arg:
497         ENTRY_ARG_ST
498         iretw
499
500         // Helper macros for hardware interrupt declaration
501         .macro IRQ_ENTRY num
502         .global entry_\num
503         entry_\num :
504         pushl $ handle_\num
505         jmp irqentry_extrastack
506         .endm
507
508         .macro DECL_IRQ_ENTRY num
509         DECLFUNC entry_\num
510         IRQ_ENTRY \num
511         .endm
512
513         // Helper macros for software interrupt declaration
514         .macro IRQ_ENTRY_ARG num
515         .global entry_\num
516         entry_\num :
517         pushl $ handle_\num
518 #if CONFIG_ENTRY_EXTRASTACK
519         jmp irqentry_arg_extrastack
520 #else
521         jmp irqentry_arg
522 #endif
523         .endm
524
525         .macro DECL_IRQ_ENTRY_ARG num
526         DECLFUNC entry_\num
527         IRQ_ENTRY_ARG \num
528         .endm
529
530         // Various entry points (that don't require a fixed location).
531         DECL_IRQ_ENTRY_ARG 13
532         DECL_IRQ_ENTRY 76
533         DECL_IRQ_ENTRY 70
534         DECL_IRQ_ENTRY 74
535         DECL_IRQ_ENTRY 75
536         DECL_IRQ_ENTRY hwpic1
537         DECL_IRQ_ENTRY hwpic2
538
539         // int 18/19 are special - they reset stack and call into 32bit mode.
540         DECLFUNC entry_19
541 entry_19:
542         ENTRY_INTO32 _cfunc32flat_handle_19
543
544         DECLFUNC entry_18
545 entry_18:
546         ENTRY_INTO32 _cfunc32flat_handle_18
547
548
549 /****************************************************************
550  * Fixed position entry points
551  ****************************************************************/
552
553         // Specify a location in the fixed part of bios area.
554         .macro ORG addr
555         .section .fixedaddr.\addr
556         .endm
557
558         ORG 0xe05b
559 entry_post:
560         cmpl $0, %cs:HaveRunPost                // Check for resume/reboot
561         jnz entry_resume
562         ENTRY_INTO32 _cfunc32flat_handle_post   // Normal entry point
563
564         ORG 0xe2c3
565         IRQ_ENTRY 02
566
567         ORG 0xe3fe
568         .global entry_13_official
569 entry_13_official:
570         jmp entry_13
571
572         // 0xe401 - OldFDPT in misc.c
573
574         ORG 0xe6f2
575         .global entry_19_official
576 entry_19_official:
577         jmp entry_19
578
579         // 0xe6f5 - BIOS_CONFIG_TABLE in misc.c
580
581         // 0xe729 - BaudTable in misc.c
582
583         ORG 0xe739
584         IRQ_ENTRY_ARG 14
585
586         ORG 0xe82e
587         IRQ_ENTRY_ARG 16
588
589         ORG 0xe987
590         IRQ_ENTRY 09
591
592         ORG 0xec59
593         IRQ_ENTRY_ARG 40
594
595         ORG 0xef57
596         IRQ_ENTRY 0e
597
598         // 0xefc7 - diskette_param_table in misc.c
599
600         ORG 0xefd2
601         IRQ_ENTRY_ARG 17
602
603         ORG 0xf045
604 entry_10_0x0f:
605         // XXX - INT 10 Functions 0-Fh Entry Point
606         iretw
607
608         ORG 0xf065
609         IRQ_ENTRY_ARG 10
610
611         // 0xf0a4 - VideoParams in misc.c
612
613         ORG 0xf841
614         IRQ_ENTRY_ARG 12
615
616         ORG 0xf84d
617         IRQ_ENTRY_ARG 11
618
619         ORG 0xf859
620         .global entry_15_official
621 entry_15_official:
622         cmpb $0x89, %ah
623         je entry_1589           // 1589 calls return in protected mode
624         IRQ_ENTRY_ARG 15
625
626         // 0xfa6e - vgafont8 in font.c
627
628         ORG 0xfe6e
629         .global entry_1a_official
630 entry_1a_official:
631         cmpb $0xb1, %ah
632         je entry_pcibios16      // PCIBIOS calls can be in protected mode
633         IRQ_ENTRY_ARG 1a
634
635         ORG 0xfea5
636         IRQ_ENTRY 08
637
638         // 0xfef3 - InitVectors in misc.c
639
640         ORG 0xff53
641         .global entry_iret_official
642 entry_iret_official:
643         iretw
644
645         ORG 0xff54
646         IRQ_ENTRY_ARG 05
647
648         ORG 0xfff0 // Power-up Entry Point
649         .global reset_vector
650 reset_vector:
651         ljmpw $SEG_BIOS, $entry_post
652
653         // 0xfff5 - BiosDate in misc.c
654
655         // 0xfffe - BiosModelId in misc.c
656
657         // 0xffff - BiosChecksum in misc.c
658
659         .end