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