Register int02 handler (nmi); disable NMI by default.
[seabios.git] / src / romlayout.S
1 // Rom layout and bios assembler to C interface.
2 //
3 // Copyright (C) 2008  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 "config.h" // CONFIG_*
9 #include "ioport.h" // PORT_A20
10 #include "bregs.h" // CR0_*
11 #include "cmos.h" // CMOS_RESET_CODE
12 #include "../out/asm-offsets.h" // BREGS_*
13
14
15 /****************************************************************
16  * Include of 16bit C code
17  ****************************************************************/
18
19         .code16gcc
20 .include "out/ccode.16.s"
21
22
23 /****************************************************************
24  * Entry macros
25  ****************************************************************/
26
27         // Call a C function - this does the minimal work necessary to
28         // call into C.  It sets up %ds, backs up %es, and backs up
29         // those registers that are call clobbered by the C compiler.
30         .macro ENTRY cfunc
31         cli         // In case something far-calls instead of using "int"
32         cld
33         pushl %eax              // Save registers clobbered by C code
34         pushl %ecx
35         pushl %edx
36         pushw %es
37         pushw %ds
38         movw %ss, %ax           // Move %ss to %ds
39         movw %ax, %ds
40         pushl %esp              // Backup %esp, then clear high bits
41         movzwl %sp, %esp
42         calll \cfunc
43         popl %esp               // Restore %esp (including high bits)
44         popw %ds                // Restore registers saved above
45         popw %es
46         popl %edx
47         popl %ecx
48         popl %eax
49         .endm
50
51         // Call a C function with current register list as an
52         // argument.  This backs up the registers and sets %eax
53         // to point to the backup.  On return, the registers are
54         // restored from the structure.
55         .macro ENTRY_ARG cfunc
56         cli
57         cld
58         pushl %eax              // Save registers (matches struct bregs)
59         pushl %ecx
60         pushl %edx
61         pushl %ebx
62         pushl %esi
63         pushl %edi
64         pushw %es
65         pushw %ds
66         movw %ss, %ax           // Move %ss to %ds
67         movw %ax, %ds
68         movl %esp, %ebx         // Backup %esp, then zero high bits
69         movzwl %sp, %esp
70         movl %esp, %eax         // First arg is pointer to struct bregs
71         calll \cfunc
72         movl %ebx, %esp         // Restore %esp (including high bits)
73         popw %ds                // Restore registers (from struct bregs)
74         popw %es
75         popl %edi
76         popl %esi
77         popl %ebx
78         popl %edx
79         popl %ecx
80         popl %eax
81         .endm
82
83         // As above, but don't mangle %esp
84         .macro ENTRY_ARG_ESP cfunc
85         cli
86         cld
87         pushl %eax              // Save registers (matches struct bregs)
88         pushl %ecx
89         pushl %edx
90         pushl %ebx
91         pushl %esi
92         pushl %edi
93         pushw %es
94         pushw %ds
95         movw %ss, %ax           // Move %ss to %ds
96         movw %ax, %ds
97         movl %esp, %eax         // First arg is pointer to struct bregs
98         calll \cfunc
99         popw %ds                // Restore registers (from struct bregs)
100         popw %es
101         popl %edi
102         popl %esi
103         popl %ebx
104         popl %edx
105         popl %ecx
106         popl %eax
107         .endm
108
109         // Reset stack, transition to 32bit mode, and call a C function.
110         // Clobbers %ax
111         .macro ENTRY_INTO32 cfunc
112         xorw %ax, %ax
113         movw %ax, %ss
114         movl $ BUILD_STACK_ADDR , %esp
115         pushl $ \cfunc
116         jmp transition32
117         .endm
118
119         // Declare a function
120         .macro DECLFUNC func
121         .section .text.asm.\func
122         .global \func
123         .endm
124
125
126 /****************************************************************
127  * POST handler
128  ****************************************************************/
129
130         DECLFUNC entry_post
131 entry_post:
132         // Enable cache
133         movl %cr0, %eax
134         andl $~(CR0_CD|CR0_NW), %eax
135         movl %eax, %cr0
136
137         // Disable interrupts
138         cli
139         cld
140
141         // Check for restart indicator.
142         movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
143         outb %al, $PORT_CMOS_INDEX
144         inb $PORT_CMOS_DATA, %al
145         cmpb $0x0, %al
146         jnz 1f
147
148         // Normal entry point
149         ENTRY_INTO32 _code32__start
150
151         // Entry point when a post call looks like a resume.
152 1:
153         // Save old shutdown status.
154         movl %eax, %ebx
155
156         // Clear shutdown status register.
157         movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
158         outb %al, $PORT_CMOS_INDEX
159         xorl %eax, %eax
160         outb %al, $PORT_CMOS_DATA
161
162         // Use a stack in EBDA
163         movw $SEG_BDA, %ax
164         movw %ax, %ds
165         movw BDA_ebda_seg, %ax
166         // XXX - should verify ebda_seg looks sane.
167         movw %ax, %ds
168         movw %ax, %ss
169         movl $EBDA_OFFSET_TOP_STACK, %esp
170
171         // Call handler.
172         movl %ebx, %eax
173         jmp handle_resume
174
175
176 /****************************************************************
177  * Call trampolines
178  ****************************************************************/
179
180 // Place CPU into 32bit mode from 16bit mode.
181 // Clobbers: flags, segment registers, cr0, idt/gdt
182 // Require: interrupts must be disabled
183         DECLFUNC transition32
184 transition32:
185         pushl %eax
186
187         // enable a20
188         inb $PORT_A20, %al
189         orb $A20_ENABLE_BIT, %al
190         outb %al, $PORT_A20
191
192         // Set segment descriptors
193         lidtw %cs:pmode_IDT_info
194         lgdtw %cs:rombios32_gdt_48
195
196         // Disable nmi
197         movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
198         outb %al, $PORT_CMOS_INDEX
199         inb $PORT_CMOS_DATA, %al
200
201         // Enable protected mode
202         movl %cr0, %eax
203         orl $CR0_PE, %eax
204         movl %eax, %cr0
205
206         // start 32bit protected mode code
207         ljmpl $SEG32_MODE32_CS, $(BUILD_BIOS_ADDR + 1f)
208
209         .code32
210 1:
211         // init data segments
212         movl $SEG32_MODE32_DS, %eax
213         movw %ax, %ds
214         movw %ax, %es
215         movw %ax, %ss
216         movw %ax, %fs
217         movw %ax, %gs
218
219         popl %eax
220         retl
221
222 // Call a 16bit function from 32bit mode.
223 // %eax = address of struct bregs
224 // Clobbers: %e[bcd]x, %e[ds]i, flags, segment registers, idt/gdt
225         DECLFUNC __call16_from32
226         .global __call16big_from32
227 __call16_from32:
228         pushl %eax
229
230         // restore data segment limits to 0xffff
231         movl $SEG32_MODE16_DS, %eax
232         movw %ax, %ds
233         movw %ax, %es
234         movw %ax, %ss
235         movw %ax, %fs
236         movw %ax, %gs
237
238         // disable a20
239         inb $PORT_A20, %al
240         andb $~A20_ENABLE_BIT, %al
241         outb %al, $PORT_A20
242
243         // Jump to 16bit mode
244         ljmpw $SEG32_MODE16_CS, $1f
245
246 __call16big_from32:
247         pushl %eax
248
249         movl $SEG32_MODE16BIG_DS, %eax
250         movw %ax, %ds
251         movw %ax, %es
252         movw %ax, %ss
253         movw %ax, %fs
254         movw %ax, %gs
255
256         ljmpl $SEG32_MODE16BIG_CS, $(BUILD_BIOS_ADDR + 1f)
257
258         .code16gcc
259 1:
260         // Disable protected mode
261         movl %cr0, %eax
262         andl $~CR0_PE, %eax
263         movl %eax, %cr0
264
265         // far jump to flush CPU queue after transition to real mode
266         ljmpw $SEG_BIOS, $2f
267
268 2:
269         // restore IDT to normal real-mode defaults
270         lidtw %cs:rmode_IDT_info
271
272         // Clear segment registers
273         xorw %ax, %ax
274         movw %ax, %fs
275         movw %ax, %gs
276         movw %ax, %es
277         movw %ax, %ds
278         movw %ax, %ss  // Assume stack is in segment 0
279
280         popl %eax
281
282         // Make call.
283         calll __call16
284
285         // Return via transition32
286         jmp transition32
287
288
289 // Call a 16bit function from 16bit mode with a specified cpu register state
290 // %eax = address of struct bregs
291 // Clobbers: %e[bcd]x, %e[ds]i, flags
292         DECLFUNC __call16
293 __call16:
294         // Save %eax, %ebp
295         pushl %ebp
296         pushl %eax
297
298         // Setup for iretw call
299         pushw %cs
300         pushw $1f               // return point
301         pushw BREGS_flags(%eax) // flags
302         pushl BREGS_ip(%eax)    // CS:IP
303
304         // Load calling registers.
305         movl BREGS_edi(%eax), %edi
306         movl BREGS_esi(%eax), %esi
307         movl BREGS_ebx(%eax), %ebx
308         movl BREGS_edx(%eax), %edx
309         movl BREGS_ecx(%eax), %ecx
310         movw BREGS_es(%eax), %es
311         movw BREGS_ds(%eax), %ds
312         movl %ss:BREGS_eax(%eax), %eax
313
314         // Invoke call
315         iretw                   // XXX - just do a lcalll
316 1:
317         // Store flags, eax, ecx
318         pushfw
319         pushl %eax
320         movl 0x06(%esp), %eax
321         movl %ecx, %ss:BREGS_ecx(%eax)
322         movw %ds, %ss:BREGS_ds(%eax)
323         movw %ss, %cx
324         movw %cx, %ds           // Restore %ds == %ss
325         popl %ecx
326         movl %ecx, BREGS_eax(%eax)
327         popw %cx
328         movw %cx, BREGS_flags(%eax)
329
330         // Store remaining registers
331         movw %es, BREGS_es(%eax)
332         movl %edi, BREGS_edi(%eax)
333         movl %esi, BREGS_esi(%eax)
334         movl %ebx, BREGS_ebx(%eax)
335         movl %edx, BREGS_edx(%eax)
336
337         // Remove %eax, restore %ebp
338         popl %eax
339         popl %ebp
340
341         cli
342         cld
343
344         retl
345
346 // PnP trampolines
347         DECLFUNC entry_pnp_real
348         .global entry_pnp_prot
349 entry_pnp_prot:
350         pushl %esp
351         jmp 1f
352 entry_pnp_real:
353         pushl %esp              // Backup %esp, then clear high bits
354         movzwl %sp, %esp
355 1:
356         pushfl                  // Save registers clobbered by C code
357         pushl %eax
358         pushl %ecx
359         pushl %edx
360         pushw %es
361         pushw %ds
362         movw %ss, %cx           // Move %ss to %ds
363         movw %cx, %ds
364         lea 28(%esp), %eax      // %eax points to start of u16 args
365         calll handle_pnp
366         movw %ax, 12(%esp)      // Modify %eax to return %ax
367         popw %ds
368         popw %es
369         popl %edx
370         popl %ecx
371         popl %eax
372         popfl
373         popl %esp
374         lretw
375
376 // APM trampolines
377         DECLFUNC apm16protected_entry
378 apm16protected_entry:
379         pushfw          // save flags
380         pushl %eax      // dummy
381         ENTRY_ARG handle_1553
382         addw $4, %sp    // pop dummy
383         popfw           // restore flags
384         lretw
385
386         .code32
387         DECLFUNC apm32protected_entry
388 apm32protected_entry:
389         pushfw
390         pushw %cs       // Setup for long jump to 16bit mode
391         pushw $1f
392         addw $8, 2(%esp)
393         ljmpw *(%esp)
394         .code16gcc
395 1:
396         ENTRY_ARG_ESP handle_1553
397
398         movw $2f,(%esp) // Setup for long jump back to 32bit mode
399         subw $8, 2(%esp)
400         ljmpw *(%esp)
401         .code32
402 2:
403         addl $4, %esp   // pop call address
404         popfw
405         lretl
406
407 // 32bit elf entry point
408         DECLFUNC post32
409 post32:
410         cli
411         cld
412         lidtl (BUILD_BIOS_ADDR + pmode_IDT_info)
413         lgdtl (BUILD_BIOS_ADDR + rombios32_gdt_48)
414         movl $BUILD_STACK_ADDR, %esp
415         ljmpl $SEG32_MODE32_CS, $_code32__start
416
417         .code16gcc
418
419 // IRQ trampolines
420         .macro IRQ_TRAMPOLINE num
421         DECLFUNC irq_trampoline_0x\num
422         irq_trampoline_0x\num :
423         int $0x\num
424         lretw
425         .endm
426
427         IRQ_TRAMPOLINE 10
428         IRQ_TRAMPOLINE 13
429         IRQ_TRAMPOLINE 15
430         IRQ_TRAMPOLINE 16
431         IRQ_TRAMPOLINE 18
432         IRQ_TRAMPOLINE 19
433
434
435 /****************************************************************
436  * Interrupt entry points
437  ****************************************************************/
438
439         // Define an entry point for an interrupt (no args passed).
440         .macro IRQ_ENTRY num
441         .global entry_\num
442         entry_\num :
443         ENTRY handle_\num
444         iretw
445         .endm
446
447         // Define an entry point for an interrupt (can read/modify args).
448         .macro IRQ_ENTRY_ARG num
449         .global entry_\num
450         entry_\num :
451         ENTRY_ARG handle_\num
452         iretw
453         .endm
454
455         // Macros that put each handler into its own section
456         .macro DECL_IRQ_ENTRY num
457         .section .text.asm.entry_\num
458         IRQ_ENTRY \num
459         .endm
460         .macro DECL_IRQ_ENTRY_ARG num
461         .section .text.asm.entry_\num
462         IRQ_ENTRY_ARG \num
463         .endm
464
465         DECL_IRQ_ENTRY_ARG 13
466         DECL_IRQ_ENTRY_ARG 12
467         DECL_IRQ_ENTRY_ARG 11
468         DECL_IRQ_ENTRY 76
469         DECL_IRQ_ENTRY 70
470         DECL_IRQ_ENTRY 74
471         DECL_IRQ_ENTRY 75
472         DECL_IRQ_ENTRY hwpic1
473         DECL_IRQ_ENTRY hwpic2
474
475         // int 18/19 are special - they reset stack and call into 32bit mode.
476         DECLFUNC entry_19
477 entry_19:
478         cli
479         cld
480         ENTRY_INTO32 _code32_handle_19
481
482         DECLFUNC entry_18
483 entry_18:
484         cli
485         cld
486         ENTRY_INTO32 _code32_handle_18
487
488
489 /****************************************************************
490  * Fixed position entry points
491  ****************************************************************/
492
493         // Specify a location in the fixed part of bios area.
494         .macro ORG addr
495         .section .fixedaddr.\addr
496         .endm
497
498         ORG 0xe05b
499 entry_post_official:
500         jmp entry_post
501
502         ORG 0xe2c3
503         IRQ_ENTRY 02
504
505         ORG 0xe3fe
506         .global entry_13_official
507 entry_13_official:
508         jmp entry_13
509
510         // 0xe401 - OldFDPT in disk.c
511
512         ORG 0xe6f2
513         .global entry_19_official
514 entry_19_official:
515         jmp entry_19
516
517         // 0xe6f5 - BIOS_CONFIG_TABLE in misc.c
518
519         // 0xe729 - BaudTable in serial.c
520
521         ORG 0xe739
522         IRQ_ENTRY_ARG 14
523
524         ORG 0xe82e
525         IRQ_ENTRY_ARG 16
526
527         ORG 0xe987
528         IRQ_ENTRY 09
529
530         ORG 0xec59
531         IRQ_ENTRY_ARG 40
532
533         ORG 0xef57
534         IRQ_ENTRY 0e
535
536         // 0xefc7 - diskette_param_table in floppy.c
537
538         ORG 0xefd2
539         IRQ_ENTRY_ARG 17
540
541         ORG 0xf045
542 entry_10_0x0f:
543         // XXX - INT 10 Functions 0-Fh Entry Point
544         iretw
545
546         ORG 0xf065
547         IRQ_ENTRY_ARG 10
548
549         // 0xf0a4 - VideoParams in misc.c
550
551         ORG 0xf841
552         .global entry_12_official
553 entry_12_official:
554         jmp entry_12
555
556         ORG 0xf84d
557         .global entry_11_official
558 entry_11_official:
559         jmp entry_11
560
561         ORG 0xf859
562         IRQ_ENTRY_ARG 15
563
564         // 0xfa6e - vgafont8 in font.c
565
566         ORG 0xfe6e
567         IRQ_ENTRY_ARG 1a
568
569         ORG 0xfea5
570         IRQ_ENTRY 08
571
572         // 0xfef3 - InitVectors in misc.c
573
574         // 0xff00 - BiosCopyright in misc.c
575
576         ORG 0xff53
577         .global entry_iret_official
578 entry_iret_official:
579         iretw
580
581         ORG 0xff54
582         IRQ_ENTRY_ARG 05
583
584         ORG 0xfff0 // Power-up Entry Point
585         .global reset_vector
586 reset_vector:
587         ljmpw $SEG_BIOS, $entry_post_official
588
589         // 0xfff5 - BiosDate in misc.c
590
591         // 0xfffe - BiosModelId in misc.c
592
593         // 0xffff - BiosChecksum in misc.c
594
595         .end