Annotation of qemu/roms/seabios/src/romlayout.S, revision 1.1.1.3

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.