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