|
|
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:
1.1.1.3 ! root 108: ljmpw $SEG32_MODE16BIG_CS, $1f
1.1 root 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
1.1.1.2 root 351: ENTRY_ARG handle_apm16
1.1 root 352: addw $4, %sp // pop dummy
353: popfw // restore flags
354: lretw
355:
356: .code32
357: DECLFUNC apm32protected_entry
358: apm32protected_entry:
1.1.1.2 root 359: pushfl
360: pushl %gs
361: pushl %cs // Move second descriptor after %cs to %gs
362: addl $16, (%esp)
363: popl %gs
364: ENTRY_ARG_ESP handle_apm32
365: popl %gs
366: popfl
367: lretl
1.1 root 368:
1.1.1.2 root 369: // PCI-BIOS 32bit entry point
370: DECLFUNC pcibios32_entry
371: pcibios32_entry:
372: pushfl
373: pushl %gs // Backup %gs and set %gs=%ds
374: pushl %ds
375: popl %gs
376: ENTRY_ARG_ESP handle_pcibios32
377: popl %gs
378: popfl
379: lretl
380:
381: // BIOS32 support
382: EXPORTFUNC bios32_entry
383: bios32_entry:
384: pushfl
385: #if CONFIG_PCIBIOS
386: // Check for PCI-BIOS request
387: cmpl $0x49435024, %eax // $PCI
388: jne 1f
389: movl $BUILD_BIOS_ADDR, %ebx
390: movl $BUILD_BIOS_SIZE, %ecx
391: movl $pcibios32_entry, %edx
392: xorb %al, %al
393: jmp 2f
394: #endif
395: // Unknown request
396: 1: movb $0x80, %al
397: // Return to caller
398: 2: popfl
1.1 root 399: lretl
400:
401: // 32bit elf entry point
402: EXPORTFUNC post32
403: post32:
404: cli
405: cld
406: lidtl (BUILD_BIOS_ADDR + pmode_IDT_info)
407: lgdtl (BUILD_BIOS_ADDR + rombios32_gdt_48)
408: movl $SEG32_MODE32_DS, %eax
409: movw %ax, %ds
410: movw %ax, %es
411: movw %ax, %fs
412: movw %ax, %gs
413: movw %ax, %ss
414: movl $BUILD_STACK_ADDR, %esp
415: ljmpl $SEG32_MODE32_CS, $_start
416:
417: .code16gcc
418:
419:
420: /****************************************************************
421: * Interrupt entry points
422: ****************************************************************/
423:
424: // Define an entry point for an interrupt (no args passed).
425: .macro IRQ_ENTRY num
426: .global entry_\num
427: entry_\num :
428: pushl $ handle_\num
429: jmp irqentry
430: .endm
431:
432: // Define an entry point for an interrupt (can read/modify args).
433: .macro IRQ_ENTRY_ARG num
434: .global entry_\num
435: entry_\num :
436: pushl $ handle_\num
437: jmp irqentryarg
438: .endm
439:
440: // Macros that put each handler into its own section
441: .macro DECL_IRQ_ENTRY num
442: DECLFUNC entry_\num
443: IRQ_ENTRY \num
444: .endm
445: .macro DECL_IRQ_ENTRY_ARG num
446: DECLFUNC entry_\num
447: IRQ_ENTRY_ARG \num
448: .endm
449:
450: // Main entry point for interrupts without args
451: DECLFUNC irqentry
452: irqentry:
453: ENTRY_ST
454: iretw
455:
456: // Main entry point for interrupts with args
457: DECLFUNC irqentryarg
458: irqentryarg:
459: ENTRY_ARG_ST
460: iretw
461:
462: DECL_IRQ_ENTRY_ARG 13
463: DECL_IRQ_ENTRY 76
464: DECL_IRQ_ENTRY 70
465: DECL_IRQ_ENTRY 74
466: DECL_IRQ_ENTRY 75
467: DECL_IRQ_ENTRY hwpic1
468: DECL_IRQ_ENTRY hwpic2
469:
470: // int 18/19 are special - they reset stack and call into 32bit mode.
471: DECLFUNC entry_19
472: entry_19:
473: ENTRY_INTO32 handle_19
474:
475: DECLFUNC entry_18
476: entry_18:
477: ENTRY_INTO32 handle_18
478:
479:
480: /****************************************************************
481: * Fixed position entry points
482: ****************************************************************/
483:
484: // Specify a location in the fixed part of bios area.
485: .macro ORG addr
486: .section .fixedaddr.\addr
487: .endm
488:
489: ORG 0xe05b
490: entry_post_official:
491: jmp entry_post
492:
493: ORG 0xe2c3
494: IRQ_ENTRY 02
495:
496: ORG 0xe3fe
497: .global entry_13_official
498: entry_13_official:
499: jmp entry_13
500:
501: // 0xe401 - OldFDPT in disk.c
502:
503: ORG 0xe6f2
504: .global entry_19_official
505: entry_19_official:
506: jmp entry_19
507:
508: // 0xe6f5 - BIOS_CONFIG_TABLE in misc.c
509:
510: // 0xe729 - BaudTable in serial.c
511:
512: ORG 0xe739
513: IRQ_ENTRY_ARG 14
514:
515: ORG 0xe82e
516: IRQ_ENTRY_ARG 16
517:
518: ORG 0xe987
519: IRQ_ENTRY 09
520:
521: ORG 0xec59
522: IRQ_ENTRY_ARG 40
523:
524: ORG 0xef57
525: IRQ_ENTRY 0e
526:
527: // 0xefc7 - diskette_param_table in floppy.c
528:
529: ORG 0xefd2
530: IRQ_ENTRY_ARG 17
531:
532: ORG 0xf045
533: entry_10_0x0f:
534: // XXX - INT 10 Functions 0-Fh Entry Point
535: iretw
536:
537: ORG 0xf065
538: IRQ_ENTRY_ARG 10
539:
540: // 0xf0a4 - VideoParams in misc.c
541:
542: ORG 0xf841
543: IRQ_ENTRY_ARG 12
544:
545: ORG 0xf84d
546: IRQ_ENTRY_ARG 11
547:
548: ORG 0xf859
549: IRQ_ENTRY_ARG 15
550:
551: // 0xfa6e - vgafont8 in font.c
552:
553: ORG 0xfe6e
554: IRQ_ENTRY_ARG 1a
555:
556: ORG 0xfea5
557: IRQ_ENTRY 08
558:
559: // 0xfef3 - InitVectors in misc.c
560:
561: // 0xff00 - BiosCopyright in misc.c
562:
563: ORG 0xff53
564: .global entry_iret_official
565: entry_iret_official:
566: iretw
567:
568: ORG 0xff54
569: IRQ_ENTRY_ARG 05
570:
571: ORG 0xfff0 // Power-up Entry Point
572: .global reset_vector
573: reset_vector:
574: ljmpw $SEG_BIOS, $entry_post_official
575:
576: // 0xfff5 - BiosDate in misc.c
577:
578: // 0xfffe - BiosModelId in misc.c
579:
580: // 0xffff - BiosChecksum in misc.c
581:
582: .end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.