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