|
|
1.1 root 1: // Rom layout and bios assembler to C interface.
2: //
3: // Copyright (C) 2008,2009 Kevin O'Connor <[email protected]>
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
1.1.1.4 ! root 14: #include "ccode.16.s"
1.1 root 15:
16: #include "config.h" // CONFIG_*
17: #include "ioport.h" // PORT_A20
18: #include "bregs.h" // CR0_*
19: #include "cmos.h" // CMOS_RESET_CODE
1.1.1.4 ! root 20: #include "asm-offsets.h" // BREGS_*
1.1 root 21: #include "entryfuncs.S" // ENTRY_*
22:
23:
24: /****************************************************************
25: * Call trampolines
26: ****************************************************************/
27:
28: // Place CPU into 32bit mode from 16bit mode.
1.1.1.4 ! root 29: // %edx = return location (in 32bit mode)
1.1 root 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
1.1.1.4 ! root 72: jmpl *%edx
1.1 root 73:
74: // Place CPU into 16bit mode from 32bit mode.
1.1.1.4 ! root 75: // %edx = return location (in 16bit mode)
1.1 root 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:
1.1.1.3 root 110: ljmpw $SEG32_MODE16BIG_CS, $1f
1.1 root 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
1.1.1.4 ! root 135: jmpl *%edx
1.1 root 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:
1.1.1.4 ! root 200: movl $1f, %edx
1.1 root 201: jmp transition16
202: __call16big_from32:
1.1.1.4 ! root 203: movl $1f, %edx
1.1 root 204: jmp transition16big
205:
206: // Make call.
207: .code16gcc
208: 1: calll __call16
209: // Return via transition32
1.1.1.4 ! root 210: movl $(2f + BUILD_BIOS_ADDR), %edx
1.1 root 211: jmp transition32
1.1.1.4 ! root 212: .code32
! 213: 2: retl
1.1 root 214:
1.1.1.4 ! root 215: .code16gcc
1.1 root 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
1.1.1.4 ! root 255: ENTRY_INTO32 _cfunc32flat__start
1.1 root 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
1.1.1.2 root 357: ENTRY_ARG handle_apm16
1.1 root 358: addw $4, %sp // pop dummy
359: popfw // restore flags
360: lretw
361:
362: .code32
363: DECLFUNC apm32protected_entry
364: apm32protected_entry:
1.1.1.2 root 365: pushfl
366: pushl %gs
367: pushl %cs // Move second descriptor after %cs to %gs
368: addl $16, (%esp)
369: popl %gs
1.1.1.4 ! root 370: ENTRY_ARG_ESP _cfunc32seg_handle_apm32
1.1.1.2 root 371: popl %gs
372: popfl
373: lretl
1.1 root 374:
1.1.1.2 root 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
1.1.1.4 ! root 382: ENTRY_ARG_ESP _cfunc32seg_handle_pcibios32
1.1.1.2 root 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
1.1 root 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
1.1.1.4 ! root 421: ljmpl $SEG32_MODE32_CS, $_cfunc32flat__start
1.1 root 422:
423: .code16gcc
424:
425:
426: /****************************************************************
427: * Interrupt entry points
428: ****************************************************************/
429:
1.1.1.4 ! root 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:
1.1 root 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:
1.1.1.4 ! root 450: .macro DECL_IRQ_ENTRY num
! 451: DECLFUNC entry_\num
! 452: IRQ_ENTRY \num
! 453: .endm
! 454:
1.1 root 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:
1.1.1.4 ! root 468: // Various entry points (that don't require a fixed location).
1.1 root 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:
1.1.1.4 ! root 480: ENTRY_INTO32 _cfunc32flat_handle_19
1.1 root 481:
482: DECLFUNC entry_18
483: entry_18:
1.1.1.4 ! root 484: ENTRY_INTO32 _cfunc32flat_handle_18
1.1 root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.