Save/restore %ebp in __call16 instead of in caller (call16).
[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: flags, segment registers, cr0, idt/gdt
178         DECLFUNC transition32
179 transition32:
180         pushl %eax
181
182         // Disable irqs
183         cli
184
185         // enable a20
186         inb $PORT_A20, %al
187         orb $A20_ENABLE_BIT, %al
188         outb %al, $PORT_A20
189
190         // Set segment descriptors
191         lidtw %cs:pmode_IDT_info
192         lgdtw %cs:rombios32_gdt_48
193
194         // Enable protected mode
195         movl %cr0, %eax
196         orl $CR0_PE, %eax
197         movl %eax, %cr0
198
199         // start 32bit protected mode code
200         ljmpl $SEG32_MODE32_CS, $(BUILD_BIOS_ADDR + 1f)
201
202         .code32
203 1:
204         // init data segments
205         movl $SEG32_MODE32_DS, %eax
206         movw %ax, %ds
207         movw %ax, %es
208         movw %ax, %ss
209         movw %ax, %fs
210         movw %ax, %gs
211
212         popl %eax
213         retl
214
215 // Call a 16bit function from 32bit mode.
216 // %eax = address of struct bregs
217 // Clobbers: %e[bcd]x, %e[ds]i, flags, segment registers, idt/gdt
218         DECLFUNC __call16_from32
219         .global __call16big_from32
220 __call16_from32:
221         pushl %eax
222
223         // restore data segment limits to 0xffff
224         movl $SEG32_MODE16_DS, %eax
225         movw %ax, %ds
226         movw %ax, %es
227         movw %ax, %ss
228         movw %ax, %fs
229         movw %ax, %gs
230
231         // disable a20
232         inb $PORT_A20, %al
233         andb $~A20_ENABLE_BIT, %al
234         outb %al, $PORT_A20
235
236         // Jump to 16bit mode
237         ljmpw $SEG32_MODE16_CS, $1f
238
239 __call16big_from32:
240         pushl %eax
241
242         movl $SEG32_MODE16BIG_DS, %eax
243         movw %ax, %ds
244         movw %ax, %es
245         movw %ax, %ss
246         movw %ax, %fs
247         movw %ax, %gs
248
249         ljmpl $SEG32_MODE16BIG_CS, $(BUILD_BIOS_ADDR + 1f)
250
251         .code16gcc
252 1:
253         // Disable protected mode
254         movl %cr0, %eax
255         andl $~CR0_PE, %eax
256         movl %eax, %cr0
257
258         // far jump to flush CPU queue after transition to real mode
259         ljmpw $SEG_BIOS, $2f
260
261 2:
262         // restore IDT to normal real-mode defaults
263         lidtw %cs:rmode_IDT_info
264
265         // Clear segment registers
266         xorw %ax, %ax
267         movw %ax, %fs
268         movw %ax, %gs
269         movw %ax, %es
270         movw %ax, %ds
271         movw %ax, %ss  // Assume stack is in segment 0
272
273         popl %eax
274
275         // Make call.
276         calll __call16
277
278         // Return via transition32
279         jmp transition32
280
281
282 // Call a 16bit function from 16bit mode with a specified cpu register state
283 // %eax = address of struct bregs
284 // Clobbers: %e[bcd]x, %e[ds]i, flags
285         DECLFUNC __call16
286 __call16:
287         // Save %eax, %ebp
288         pushl %ebp
289         pushl %eax
290
291         // Setup for iretw call
292         pushw %cs
293         pushw $1f               // return point
294         pushw BREGS_flags(%eax) // flags
295         pushl BREGS_ip(%eax)    // CS:IP
296
297         // Load calling registers.
298         movl BREGS_edi(%eax), %edi
299         movl BREGS_esi(%eax), %esi
300         movl BREGS_ebx(%eax), %ebx
301         movl BREGS_edx(%eax), %edx
302         movl BREGS_ecx(%eax), %ecx
303         movw BREGS_es(%eax), %es
304         movw BREGS_ds(%eax), %ds
305         movl %ss:BREGS_eax(%eax), %eax
306
307         // Invoke call
308         iretw                   // XXX - just do a lcalll
309 1:
310         // Store flags, eax, ecx
311         pushfw
312         pushl %eax
313         movl 0x06(%esp), %eax
314         movl %ecx, %ss:BREGS_ecx(%eax)
315         movw %ds, %ss:BREGS_ds(%eax)
316         movw %ss, %cx
317         movw %cx, %ds           // Restore %ds == %ss
318         popl %ecx
319         movl %ecx, BREGS_eax(%eax)
320         popw %cx
321         movw %cx, BREGS_flags(%eax)
322
323         // Store remaining registers
324         movw %es, BREGS_es(%eax)
325         movl %edi, BREGS_edi(%eax)
326         movl %esi, BREGS_esi(%eax)
327         movl %ebx, BREGS_ebx(%eax)
328         movl %edx, BREGS_edx(%eax)
329
330         // Remove %eax, restore %ebp
331         popl %eax
332         popl %ebp
333
334         cld
335
336         retl
337
338 // PnP trampolines
339         DECLFUNC entry_pnp_real
340         .global entry_pnp_prot
341 entry_pnp_prot:
342         pushl %esp
343         jmp 1f
344 entry_pnp_real:
345         pushl %esp              // Backup %esp, then clear high bits
346         movzwl %sp, %esp
347 1:
348         pushfl                  // Save registers clobbered by C code
349         pushl %eax
350         pushl %ecx
351         pushl %edx
352         pushw %es
353         pushw %ds
354         movw %ss, %cx           // Move %ss to %ds
355         movw %cx, %ds
356         lea 28(%esp), %eax      // %eax points to start of u16 args
357         calll handle_pnp
358         movw %ax, 12(%esp)      // Modify %eax to return %ax
359         popw %ds
360         popw %es
361         popl %edx
362         popl %ecx
363         popl %eax
364         popfl
365         popl %esp
366         lretw
367
368 // APM trampolines
369         DECLFUNC apm16protected_entry
370 apm16protected_entry:
371         pushfw          // save flags
372         pushl %eax      // dummy
373         ENTRY_ARG handle_1553
374         addw $4, %sp    // pop dummy
375         popfw           // restore flags
376         lretw
377
378         .code32
379         DECLFUNC apm32protected_entry
380 apm32protected_entry:
381         pushfw
382         pushw %cs       // Setup for long jump to 16bit mode
383         pushw $1f
384         addw $8, 2(%esp)
385         ljmpw *(%esp)
386         .code16gcc
387 1:
388         ENTRY_ARG_ESP handle_1553
389
390         movw $2f,(%esp) // Setup for long jump back to 32bit mode
391         subw $8, 2(%esp)
392         ljmpw *(%esp)
393         .code32
394 2:
395         addl $4, %esp   // pop call address
396         popfw
397         lretl
398
399 // 32bit elf entry point
400         DECLFUNC post32
401 post32:
402         cli
403         cld
404         lidtl (BUILD_BIOS_ADDR + pmode_IDT_info)
405         lgdtl (BUILD_BIOS_ADDR + rombios32_gdt_48)
406         movl $BUILD_STACK_ADDR, %esp
407         ljmpl $SEG32_MODE32_CS, $_code32__start
408
409         .code16gcc
410
411 // IRQ trampolines
412         .macro IRQ_TRAMPOLINE num
413         DECLFUNC irq_trampoline_0x\num
414         irq_trampoline_0x\num :
415         int $0x\num
416         lretw
417         .endm
418
419         IRQ_TRAMPOLINE 10
420         IRQ_TRAMPOLINE 13
421         IRQ_TRAMPOLINE 15
422         IRQ_TRAMPOLINE 16
423         IRQ_TRAMPOLINE 18
424         IRQ_TRAMPOLINE 19
425
426
427 /****************************************************************
428  * Interrupt entry points
429  ****************************************************************/
430
431         // Define an entry point for an interrupt (no args passed).
432         .macro IRQ_ENTRY num
433         .global entry_\num
434         entry_\num :
435         cli         // In case something far-calls instead of using "int"
436         ENTRY handle_\num
437         iretw
438         .endm
439
440         // Define an entry point for an interrupt (can read/modify args).
441         .macro IRQ_ENTRY_ARG num
442         .global entry_\num
443         entry_\num :
444         cli         // In case something far-calls instead of using "int"
445         ENTRY_ARG handle_\num
446         iretw
447         .endm
448
449         // Macros that put each handler into its own section
450         .macro DECL_IRQ_ENTRY num
451         .section .text.asm.entry_\num
452         IRQ_ENTRY \num
453         .endm
454         .macro DECL_IRQ_ENTRY_ARG num
455         .section .text.asm.entry_\num
456         IRQ_ENTRY_ARG \num
457         .endm
458
459         DECL_IRQ_ENTRY_ARG 13
460         DECL_IRQ_ENTRY_ARG 12
461         DECL_IRQ_ENTRY_ARG 11
462         DECL_IRQ_ENTRY 76
463         DECL_IRQ_ENTRY 70
464         DECL_IRQ_ENTRY 74
465         DECL_IRQ_ENTRY 75
466         DECL_IRQ_ENTRY hwpic1
467         DECL_IRQ_ENTRY hwpic2
468
469         // int 18/19 are special - they reset the stack and do not return.
470         DECLFUNC entry_19
471 entry_19:
472         RESET_STACK
473         pushl $_code32_handle_19
474         jmp transition32
475
476         DECLFUNC entry_18
477 entry_18:
478         RESET_STACK
479         pushl $_code32_handle_18
480         jmp transition32
481
482
483 /****************************************************************
484  * Fixed position entry points
485  ****************************************************************/
486
487         // Specify a location in the fixed part of bios area.
488         .macro ORG addr
489         .section .fixedaddr.\addr
490         .endm
491
492         ORG 0xe05b
493 entry_post_official:
494         jmp entry_post
495
496         ORG 0xe2c3
497         IRQ_ENTRY nmi
498
499         ORG 0xe3fe
500         .global entry_13_official
501 entry_13_official:
502         jmp entry_13
503
504         // 0xe401 - OldFDPT in disk.c
505
506         ORG 0xe6f2
507         .global entry_19_official
508 entry_19_official:
509         jmp entry_19
510
511         // 0xe6f5 - BIOS_CONFIG_TABLE in misc.c
512
513         // 0xe729 - BaudTable in serial.c
514
515         ORG 0xe739
516         IRQ_ENTRY_ARG 14
517
518         ORG 0xe82e
519         IRQ_ENTRY_ARG 16
520
521         ORG 0xe987
522         IRQ_ENTRY 09
523
524         ORG 0xec59
525         IRQ_ENTRY_ARG 40
526
527         ORG 0xef57
528         IRQ_ENTRY 0e
529
530         // 0xefc7 - diskette_param_table in floppy.c
531
532         ORG 0xefd2
533         IRQ_ENTRY_ARG 17
534
535         ORG 0xf045
536 entry_10_0x0f:
537         // XXX - INT 10 Functions 0-Fh Entry Point
538         iretw
539
540         ORG 0xf065
541         IRQ_ENTRY_ARG 10
542
543         // 0xf0a4 - VideoParams in misc.c
544
545         ORG 0xf841
546         .global entry_12_official
547 entry_12_official:
548         jmp entry_12
549
550         ORG 0xf84d
551         .global entry_11_official
552 entry_11_official:
553         jmp entry_11
554
555         ORG 0xf859
556         IRQ_ENTRY_ARG 15
557
558         // 0xfa6e - vgafont8 in font.c
559
560         ORG 0xfe6e
561         IRQ_ENTRY_ARG 1a
562
563         ORG 0xfea5
564         IRQ_ENTRY 08
565
566         // 0xfef3 - InitVectors in misc.c
567
568         // 0xff00 - BiosCopyright in misc.c
569
570         ORG 0xff53
571         .global entry_iret_official
572 entry_iret_official:
573         iretw
574
575         ORG 0xff54
576         IRQ_ENTRY_ARG 05
577
578         ORG 0xfff0 // Power-up Entry Point
579         .global reset_vector
580 reset_vector:
581         ljmpw $SEG_BIOS, $entry_post_official
582
583         // 0xfff5 - BiosDate in misc.c
584
585         // 0xfffe - BiosModelId in misc.c
586
587         // 0xffff - BiosChecksum in misc.c
588
589         .end