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