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