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