|
|
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: /****************************************************************
1.1.1.5 ! root 233: * Misc. entry points.
1.1 root 234: ****************************************************************/
235:
1.1.1.5 ! root 236: // Resume (and reboot) entry point - called from entry_post
! 237: DECLFUNC entry_resume
! 238: entry_resume:
1.1 root 239: // Disable interrupts
240: cli
241: cld
242: // Use a stack in EBDA
243: movw $SEG_BDA, %ax
244: movw %ax, %ds
245: movw BDA_ebda_seg, %ax
1.1.1.5 ! root 246: movw %ax, %ds
1.1 root 247: movw %ax, %ss
248: movl $EBDA_OFFSET_TOP_STACK, %esp
249: // Call handler.
250: jmp handle_resume
251:
252: // PMM entry point
253: DECLFUNC entry_pmm
254: entry_pmm:
255: pushl %esp // Backup %esp, then clear high bits
256: movzwl %sp, %esp
257: pushfl // Save registers clobbered by C code
258: cli
259: cld
260: pushl %eax
261: pushl %ecx
262: pushl %edx
263: pushw %es
264: pushw %ds
265: movw %ss, %cx // Move %ss to %ds
266: movw %cx, %ds
1.1.1.5 ! root 267: movl $_cfunc32flat_handle_pmm, %eax // Setup: call32(handle_pmm, args, -1)
! 268: leal 28(%esp), %edx // %edx points to start of args
! 269: movl $-1, %ecx
! 270: calll call32
1.1 root 271: movw %ax, 12(%esp) // Modify %ax:%dx to return %eax
272: shrl $16, %eax
273: movw %ax, 4(%esp)
274: popw %ds // Restore saved registers
275: popw %es
276: popl %edx
277: popl %ecx
278: popl %eax
279: popfl
280: popl %esp
281: lretw
282:
283: // PnP entry points
284: DECLFUNC entry_pnp_real
285: .global entry_pnp_prot
286: entry_pnp_prot:
287: pushl %esp
288: jmp 1f
289: entry_pnp_real:
290: pushl %esp // Backup %esp, then clear high bits
291: movzwl %sp, %esp
292: 1:
293: pushfl // Save registers clobbered by C code
294: cli
295: cld
296: pushl %eax
297: pushl %ecx
298: pushl %edx
299: pushw %es
300: pushw %ds
301: movw %ss, %cx // Move %ss to %ds
302: movw %cx, %ds
303: leal 28(%esp), %eax // %eax points to start of u16 args
304: calll handle_pnp
305: movw %ax, 12(%esp) // Modify %eax to return %ax
306: popw %ds
307: popw %es
308: popl %edx
309: popl %ecx
310: popl %eax
311: popfl
312: popl %esp
313: lretw
314:
315: // APM entry points
1.1.1.5 ! root 316: DECLFUNC entry_apm16
! 317: entry_apm16:
1.1 root 318: pushfw // save flags
319: pushl %eax // dummy
1.1.1.2 root 320: ENTRY_ARG handle_apm16
1.1 root 321: addw $4, %sp // pop dummy
322: popfw // restore flags
323: lretw
324:
325: .code32
1.1.1.5 ! root 326: DECLFUNC entry_apm32
! 327: entry_apm32:
1.1.1.2 root 328: pushfl
329: pushl %gs
330: pushl %cs // Move second descriptor after %cs to %gs
331: addl $16, (%esp)
332: popl %gs
1.1.1.4 root 333: ENTRY_ARG_ESP _cfunc32seg_handle_apm32
1.1.1.2 root 334: popl %gs
335: popfl
336: lretl
1.1 root 337:
1.1.1.2 root 338: // PCI-BIOS 32bit entry point
1.1.1.5 ! root 339: DECLFUNC entry_pcibios32
! 340: entry_pcibios32:
1.1.1.2 root 341: pushfl
342: pushl %gs // Backup %gs and set %gs=%ds
343: pushl %ds
344: popl %gs
1.1.1.4 root 345: ENTRY_ARG_ESP _cfunc32seg_handle_pcibios32
1.1.1.2 root 346: popl %gs
347: popfl
348: lretl
349:
350: // BIOS32 support
1.1.1.5 ! root 351: EXPORTFUNC entry_bios32
! 352: entry_bios32:
1.1.1.2 root 353: pushfl
354: #if CONFIG_PCIBIOS
355: // Check for PCI-BIOS request
356: cmpl $0x49435024, %eax // $PCI
357: jne 1f
358: movl $BUILD_BIOS_ADDR, %ebx
359: movl $BUILD_BIOS_SIZE, %ecx
1.1.1.5 ! root 360: movl $entry_pcibios32, %edx
1.1.1.2 root 361: xorb %al, %al
362: jmp 2f
363: #endif
364: // Unknown request
365: 1: movb $0x80, %al
366: // Return to caller
367: 2: popfl
1.1 root 368: lretl
369:
370: // 32bit elf entry point
1.1.1.5 ! root 371: EXPORTFUNC entry_elf
! 372: entry_elf:
1.1 root 373: cli
374: cld
375: lidtl (BUILD_BIOS_ADDR + pmode_IDT_info)
376: lgdtl (BUILD_BIOS_ADDR + rombios32_gdt_48)
377: movl $SEG32_MODE32_DS, %eax
378: movw %ax, %ds
379: movw %ax, %es
380: movw %ax, %fs
381: movw %ax, %gs
382: movw %ax, %ss
383: movl $BUILD_STACK_ADDR, %esp
1.1.1.5 ! root 384: ljmpl $SEG32_MODE32_CS, $_cfunc32flat_handle_post
1.1 root 385:
386: .code16gcc
387:
388:
389: /****************************************************************
390: * Interrupt entry points
391: ****************************************************************/
392:
1.1.1.4 root 393: // Main entry point for interrupts without args
394: DECLFUNC irqentry
395: irqentry:
396: ENTRY_ST
397: iretw
398:
399: // Main entry point for interrupts with args
400: DECLFUNC irqentryarg
401: irqentryarg:
402: ENTRY_ARG_ST
403: iretw
404:
1.1 root 405: // Define an entry point for an interrupt (no args passed).
406: .macro IRQ_ENTRY num
407: .global entry_\num
408: entry_\num :
409: pushl $ handle_\num
410: jmp irqentry
411: .endm
412:
1.1.1.4 root 413: .macro DECL_IRQ_ENTRY num
414: DECLFUNC entry_\num
415: IRQ_ENTRY \num
416: .endm
417:
1.1 root 418: // Define an entry point for an interrupt (can read/modify args).
419: .macro IRQ_ENTRY_ARG num
420: .global entry_\num
421: entry_\num :
422: pushl $ handle_\num
423: jmp irqentryarg
424: .endm
425:
426: .macro DECL_IRQ_ENTRY_ARG num
427: DECLFUNC entry_\num
428: IRQ_ENTRY_ARG \num
429: .endm
430:
1.1.1.4 root 431: // Various entry points (that don't require a fixed location).
1.1 root 432: DECL_IRQ_ENTRY_ARG 13
433: DECL_IRQ_ENTRY 76
434: DECL_IRQ_ENTRY 70
435: DECL_IRQ_ENTRY 74
436: DECL_IRQ_ENTRY 75
437: DECL_IRQ_ENTRY hwpic1
438: DECL_IRQ_ENTRY hwpic2
439:
440: // int 18/19 are special - they reset stack and call into 32bit mode.
441: DECLFUNC entry_19
442: entry_19:
1.1.1.4 root 443: ENTRY_INTO32 _cfunc32flat_handle_19
1.1 root 444:
445: DECLFUNC entry_18
446: entry_18:
1.1.1.4 root 447: ENTRY_INTO32 _cfunc32flat_handle_18
1.1 root 448:
449:
450: /****************************************************************
451: * Fixed position entry points
452: ****************************************************************/
453:
454: // Specify a location in the fixed part of bios area.
455: .macro ORG addr
456: .section .fixedaddr.\addr
457: .endm
458:
459: ORG 0xe05b
1.1.1.5 ! root 460: entry_post:
! 461: cmpl $0, %cs:HaveRunPost // Check for resume/reboot
! 462: jnz entry_resume
! 463: ENTRY_INTO32 _cfunc32flat_handle_post // Normal entry point
1.1 root 464:
465: ORG 0xe2c3
466: IRQ_ENTRY 02
467:
468: ORG 0xe3fe
469: .global entry_13_official
470: entry_13_official:
471: jmp entry_13
472:
473: // 0xe401 - OldFDPT in disk.c
474:
475: ORG 0xe6f2
476: .global entry_19_official
477: entry_19_official:
478: jmp entry_19
479:
480: // 0xe6f5 - BIOS_CONFIG_TABLE in misc.c
481:
482: // 0xe729 - BaudTable in serial.c
483:
484: ORG 0xe739
485: IRQ_ENTRY_ARG 14
486:
487: ORG 0xe82e
488: IRQ_ENTRY_ARG 16
489:
490: ORG 0xe987
491: IRQ_ENTRY 09
492:
493: ORG 0xec59
494: IRQ_ENTRY_ARG 40
495:
496: ORG 0xef57
497: IRQ_ENTRY 0e
498:
499: // 0xefc7 - diskette_param_table in floppy.c
500:
501: ORG 0xefd2
502: IRQ_ENTRY_ARG 17
503:
504: ORG 0xf045
505: entry_10_0x0f:
506: // XXX - INT 10 Functions 0-Fh Entry Point
507: iretw
508:
509: ORG 0xf065
510: IRQ_ENTRY_ARG 10
511:
512: // 0xf0a4 - VideoParams in misc.c
513:
514: ORG 0xf841
515: IRQ_ENTRY_ARG 12
516:
517: ORG 0xf84d
518: IRQ_ENTRY_ARG 11
519:
520: ORG 0xf859
521: IRQ_ENTRY_ARG 15
522:
523: // 0xfa6e - vgafont8 in font.c
524:
525: ORG 0xfe6e
526: IRQ_ENTRY_ARG 1a
527:
528: ORG 0xfea5
529: IRQ_ENTRY 08
530:
531: // 0xfef3 - InitVectors in misc.c
532:
533: // 0xff00 - BiosCopyright in misc.c
534:
535: ORG 0xff53
536: .global entry_iret_official
537: entry_iret_official:
538: iretw
539:
540: ORG 0xff54
541: IRQ_ENTRY_ARG 05
542:
543: ORG 0xfff0 // Power-up Entry Point
544: .global reset_vector
545: reset_vector:
1.1.1.5 ! root 546: ljmpw $SEG_BIOS, $entry_post
1.1 root 547:
548: // 0xfff5 - BiosDate in misc.c
549:
550: // 0xfffe - BiosModelId in misc.c
551:
552: // 0xffff - BiosChecksum in misc.c
553:
554: .end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.