|
|
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.