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