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