Annotation of qemu/roms/SLOF/clients/net-snk/app/biosemu/biosemu.c, revision 1.1.1.1

1.1       root        1: /******************************************************************************
                      2:  * Copyright (c) 2004, 2008 IBM Corporation
                      3:  * All rights reserved.
                      4:  * This program and the accompanying materials
                      5:  * are made available under the terms of the BSD License
                      6:  * which accompanies this distribution, and is available at
                      7:  * http://www.opensource.org/licenses/bsd-license.php
                      8:  *
                      9:  * Contributors:
                     10:  *     IBM Corporation - initial implementation
                     11:  *****************************************************************************/
                     12: 
                     13: 
                     14: #include <stdio.h>
                     15: #include <stdlib.h>
                     16: #include <string.h>
                     17: 
                     18: #include <stdint.h>
                     19: #include <cpu.h>
                     20: 
                     21: #include "debug.h"
                     22: 
                     23: #include <x86emu/x86emu.h>
                     24: #include <x86emu/regs.h>
                     25: #include <x86emu/prim_ops.h>   // for push_word
                     26: 
                     27: #include "biosemu.h"
                     28: #include "io.h"
                     29: #include "mem.h"
                     30: #include "interrupt.h"
                     31: #include "device.h"
                     32: 
                     33: #include <rtas.h>
                     34: 
                     35: 
                     36: static X86EMU_memFuncs my_mem_funcs = {
                     37:        my_rdb, my_rdw, my_rdl,
                     38:        my_wrb, my_wrw, my_wrl
                     39: };
                     40: 
                     41: static X86EMU_pioFuncs my_pio_funcs = {
                     42:        my_inb, my_inw, my_inl,
                     43:        my_outb, my_outw, my_outl
                     44: };
                     45: 
                     46: void dump(uint8_t * addr, uint32_t len);
                     47: 
                     48: uint32_t
                     49: biosemu(char argc, char **argv)
                     50: {
                     51:        uint8_t *rom_image;
                     52:        int i = 0;
                     53:        uint8_t *biosmem;
                     54:        uint32_t biosmem_size;
                     55: #ifdef DEBUG
                     56:        //debug_flags = DEBUG_PRINT_INT10 | DEBUG_PNP;// | DEBUG_PMM;// | DEBUG_INTR | DEBUG_CHECK_VMEM_ACCESS | DEBUG_MEM | DEBUG_IO;// | DEBUG_TRACE_X86EMU | DEBUG_JMP;
                     57: #endif
                     58:        if (argc < 4) {
                     59:                printf("Usage %s <vmem_base> <vmem_size> <device_path> [<debug_flags>]\n", argv[0]);
                     60:                for (i = 0; i < argc; i++) {
                     61:                        printf("argv[%d]: %s\n", i, argv[i]);
                     62:                }
                     63:                return -1;
                     64:        }
                     65:        // argv[1] is address of virtual BIOS mem...
                     66:        // argv[2] is the size
                     67:        biosmem = (uint8_t *) strtoul(argv[1], 0, 16);
                     68:        biosmem_size = strtoul(argv[2], 0, 16);
                     69:        if (biosmem_size < MIN_REQUIRED_VMEM_SIZE) {
                     70:                printf("Error: Not enough virtual memory: %x, required: %x!\n",
                     71:                       biosmem_size, MIN_REQUIRED_VMEM_SIZE);
                     72:                return -1;
                     73:        }
                     74:        // argv[3] is the device to open and use...
                     75:        if (dev_init(argv[3]) != 0) {
                     76:                printf("Error initializing device!\n");
                     77:                return -1;
                     78:        }
                     79:        if (dev_check_exprom() != 0) {
                     80:                printf("Error: Device Expansion ROM invalid!\n");
                     81:                return -1;
                     82:        }
                     83:    // argv[4] if set, is additional debug_flags
                     84:    if (argc >= 5) {
                     85:       debug_flags |= strtoul(argv[4], 0, 16);
                     86:       printf("debug_flags: %x\n", debug_flags);
                     87:    }
                     88:        rom_image = (uint8_t *) bios_device.img_addr;
                     89:        DEBUG_PRINTF("executing rom_image from %p\n", rom_image);
                     90:        DEBUG_PRINTF("biosmem at %p\n", biosmem);
                     91: 
                     92:        DEBUG_PRINTF("Image Size: %d\n", bios_device.img_size);
                     93: 
                     94:        // in case we jump somewhere unexpected, or execution is finished,
                     95:        // fill the biosmem with hlt instructions (0xf4)
                     96:        memset(biosmem, 0xf4, biosmem_size);
                     97: 
                     98:        M.mem_base = (long) biosmem;
                     99:        M.mem_size = biosmem_size;
                    100:        DEBUG_PRINTF("membase set: %08x, size: %08x\n", (int) M.mem_base,
                    101:                     (int) M.mem_size);
                    102: 
                    103:        // copy expansion ROM image to segment OPTION_ROM_CODE_SEGMENT
                    104:        // NOTE: this sometimes fails, some bytes are 0x00... so we compare
                    105:        // after copying and do some retries...
                    106:        uint8_t *mem_img = biosmem + (OPTION_ROM_CODE_SEGMENT << 4);
                    107:        uint8_t copy_count = 0;
                    108:        uint8_t cmp_result = 0;
                    109:        do {
                    110: #if 0
                    111:                set_ci();
                    112:                memcpy(mem_img, rom_image, len);
                    113:                clr_ci();
                    114: #else
                    115:                // memcpy fails... try copy byte-by-byte with set/clr_ci
                    116:                uint8_t c;
                    117:                for (i = 0; i < bios_device.img_size; i++) {
                    118:                        set_ci();
                    119:                        c = *(rom_image + i);
                    120:                        if (c != *(rom_image + i)) {
                    121:                                clr_ci();
                    122:                                printf("Copy failed at: %x/%x\n", i,
                    123:                                       bios_device.img_size);
                    124:                                printf("rom_image(%x): %x, mem_img(%x): %x\n",
                    125:                                       i, *(rom_image + i), i, *(mem_img + i));
                    126:                                break;
                    127:                        }
                    128:                        clr_ci();
                    129:                        *(mem_img + i) = c;
                    130:                }
                    131: #endif
                    132:                copy_count++;
                    133:                set_ci();
                    134:                cmp_result = memcmp(mem_img, rom_image, bios_device.img_size);
                    135:                clr_ci();
                    136:        }
                    137:        while ((copy_count < 5) && (cmp_result != 0));
                    138:        if (cmp_result != 0) {
                    139:                printf
                    140:                    ("\nCopying Expansion ROM Image to Memory failed after %d retries! (%x)\n",
                    141:                     copy_count, cmp_result);
                    142:                dump(rom_image, 0x20);
                    143:                dump(mem_img, 0x20);
                    144:                return 0;
                    145:        }
                    146:        // setup default Interrupt Vectors
                    147:        // some expansion ROMs seem to check for these addresses..
                    148:        // each handler is only an IRET (0xCF) instruction
                    149:        // ROM BIOS Int 10 Handler F000:F065
                    150:        my_wrl(0x10 * 4, 0xf000f065);
                    151:        my_wrb(0x000ff065, 0xcf);
                    152:        // ROM BIOS Int 11 Handler F000:F84D
                    153:        my_wrl(0x11 * 4, 0xf000f84d);
                    154:        my_wrb(0x000ff84d, 0xcf);
                    155:        // ROM BIOS Int 12 Handler F000:F841
                    156:        my_wrl(0x12 * 4, 0xf000f841);
                    157:        my_wrb(0x000ff841, 0xcf);
                    158:        // ROM BIOS Int 13 Handler F000:EC59
                    159:        my_wrl(0x13 * 4, 0xf000ec59);
                    160:        my_wrb(0x000fec59, 0xcf);
                    161:        // ROM BIOS Int 14 Handler F000:E739
                    162:        my_wrl(0x14 * 4, 0xf000e739);
                    163:        my_wrb(0x000fe739, 0xcf);
                    164:        // ROM BIOS Int 15 Handler F000:F859
                    165:        my_wrl(0x15 * 4, 0xf000f859);
                    166:        my_wrb(0x000ff859, 0xcf);
                    167:        // ROM BIOS Int 16 Handler F000:E82E
                    168:        my_wrl(0x16 * 4, 0xf000e82e);
                    169:        my_wrb(0x000fe82e, 0xcf);
                    170:        // ROM BIOS Int 17 Handler F000:EFD2
                    171:        my_wrl(0x17 * 4, 0xf000efd2);
                    172:        my_wrb(0x000fefd2, 0xcf);
                    173:        // ROM BIOS Int 1A Handler F000:FE6E
                    174:        my_wrl(0x1a * 4, 0xf000fe6e);
                    175:        my_wrb(0x000ffe6e, 0xcf);
                    176: 
                    177:        // setup BIOS Data Area (0000:04xx, or 0040:00xx)
                    178:        // we currently 0 this area, meaning "we dont have
                    179:        // any hardware" :-) no serial/parallel ports, floppys, ...
                    180:        memset(biosmem + 0x400, 0x0, 0x100);
                    181: 
                    182:        // at offset 13h in BDA is the memory size in kbytes
                    183:        my_wrw(0x413, biosmem_size / 1024);
                    184:        // at offset 0eh in BDA is the segment of the Extended BIOS Data Area
                    185:        // see setup further down
                    186:        my_wrw(0x40e, INITIAL_EBDA_SEGMENT);
                    187:        // TODO: setup BDA Video Data ( offset 49h-66h)
                    188:        // e.g. to store video mode, cursor position, ...
                    189:        // in int10 (done) handler and VBE Functions
                    190: 
                    191:        // TODO: setup BDA Fixed Disk Data
                    192:        // 74h: Fixed Disk Last Operation Status
                    193:        // 75h: Fixed Disk Number of Disk Drives
                    194: 
                    195:        // TODO: check BDA for further needed data...
                    196: 
                    197:        //setup Extended BIOS Data Area
                    198:        //we currently 0 this area
                    199:        memset(biosmem + (INITIAL_EBDA_SEGMENT << 4), 0, INITIAL_EBDA_SIZE);
                    200:        // at offset 0h in EBDA is the size of the EBDA in KB
                    201:        my_wrw((INITIAL_EBDA_SEGMENT << 4) + 0x0, INITIAL_EBDA_SIZE / 1024);
                    202:        //TODO: check for further needed EBDA data...
                    203: 
                    204:        // setup  original ROM BIOS Area (F000:xxxx)
                    205:        char *date = "06/11/99";
                    206:        for (i = 0; date[i]; i++)
                    207:                my_wrb(0xffff5 + i, date[i]);
                    208:        // set up eisa ident string
                    209:        char *ident = "PCI_ISA";
                    210:        for (i = 0; ident[i]; i++)
                    211:                my_wrb(0xfffd9 + i, ident[i]);
                    212: 
                    213:        // write system model id for IBM-AT
                    214:        // according to "Ralf Browns Interrupt List" Int15 AH=C0 Table 515,
                    215:        // model FC is the original AT and also used in all DOSEMU Versions.
                    216:        my_wrb(0xFFFFE, 0xfc);
                    217: 
                    218:        //setup interrupt handler
                    219:        X86EMU_intrFuncs intrFuncs[256];
                    220:        for (i = 0; i < 256; i++)
                    221:                intrFuncs[i] = handleInterrupt;
                    222:        X86EMU_setupIntrFuncs(intrFuncs);
                    223:        X86EMU_setupPioFuncs(&my_pio_funcs);
                    224:        X86EMU_setupMemFuncs(&my_mem_funcs);
                    225: 
                    226:        // setup the CPU
                    227:        M.x86.R_AH = bios_device.bus;
                    228:        M.x86.R_AL = bios_device.devfn;
                    229:        M.x86.R_DX = 0x80;
                    230:        M.x86.R_EIP = 3;
                    231:        M.x86.R_CS = OPTION_ROM_CODE_SEGMENT;
                    232: 
                    233:        // Initialize stack and data segment
                    234:        M.x86.R_SS = STACK_SEGMENT;
                    235:        M.x86.R_SP = STACK_START_OFFSET;
                    236:        M.x86.R_DS = DATA_SEGMENT;
                    237: 
                    238:        // push a HLT instruction and a pointer to it onto the stack
                    239:        // any return will pop the pointer and jump to the HLT, thus
                    240:        // exiting (more or less) cleanly
                    241:        push_word(0xf4f4);      //F4=HLT
                    242:        push_word(M.x86.R_SS);
                    243:        push_word(M.x86.R_SP + 2);
                    244: 
                    245:        CHECK_DBG(DEBUG_TRACE_X86EMU) {
                    246:                X86EMU_trace_on();
                    247:        } else {
                    248: #ifdef DEBUG
                    249:                M.x86.debug |= DEBUG_SAVE_IP_CS_F;
                    250:                M.x86.debug |= DEBUG_DECODE_F;
                    251:                M.x86.debug |= DEBUG_DECODE_NOPRINT_F;
                    252: #endif
                    253:        }
                    254:        CHECK_DBG(DEBUG_JMP) {
                    255:                M.x86.debug |= DEBUG_TRACEJMP_F;
                    256:                M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
                    257:                M.x86.debug |= DEBUG_TRACECALL_F;
                    258:                M.x86.debug |= DEBUG_TRACECALL_REGS_F;
                    259:                }
                    260: 
                    261:        DEBUG_PRINTF("Executing Initialization Vector...\n");
                    262:        X86EMU_exec();
                    263:        DEBUG_PRINTF("done\n");
                    264: 
                    265:        // according to PNP BIOS Spec, Option ROMs should upon exit, return some boot device status in
                    266:        // AX (see PNP BIOS Spec Section 3.3
                    267:        DEBUG_PRINTF_CS_IP("Option ROM Exit Status: %04x\n", M.x86.R_AX);
                    268: #ifdef DEBUG
                    269:        DEBUG_PRINTF("Exit Status Decode:\n");
                    270:        if (M.x86.R_AX & 0x100) {       // bit 8
                    271:                DEBUG_PRINTF
                    272:                    ("  IPL Device supporting INT 13h Block Device Format:\n");
                    273:                switch (((M.x86.R_AX >> 4) & 0x3)) {    // bits 5:4
                    274:                case 0:
                    275:                        DEBUG_PRINTF("    No IPL Device attached\n");
                    276:                        break;
                    277:                case 1:
                    278:                        DEBUG_PRINTF("    IPL Device status unknown\n");
                    279:                        break;
                    280:                case 2:
                    281:                        DEBUG_PRINTF("    IPL Device attached\n");
                    282:                        break;
                    283:                case 3:
                    284:                        DEBUG_PRINTF("    IPL Device status RESERVED!!\n");
                    285:                        break;
                    286:                }
                    287:        }
                    288:        if (M.x86.R_AX & 0x80) {        // bit 7
                    289:                DEBUG_PRINTF
                    290:                    ("  Output Device supporting INT 10h Character Output:\n");
                    291:                switch (((M.x86.R_AX >> 4) & 0x3)) {    // bits 5:4
                    292:                case 0:
                    293:                        DEBUG_PRINTF("    No Display Device attached\n");
                    294:                        break;
                    295:                case 1:
                    296:                        DEBUG_PRINTF("    Display Device status unknown\n");
                    297:                        break;
                    298:                case 2:
                    299:                        DEBUG_PRINTF("    Display Device attached\n");
                    300:                        break;
                    301:                case 3:
                    302:                        DEBUG_PRINTF("    Display Device status RESERVED!!\n");
                    303:                        break;
                    304:                }
                    305:        }
                    306:        if (M.x86.R_AX & 0x40) {        // bit 6
                    307:                DEBUG_PRINTF
                    308:                    ("  Input Device supporting INT 9h Character Input:\n");
                    309:                switch (((M.x86.R_AX >> 4) & 0x3)) {    // bits 5:4
                    310:                case 0:
                    311:                        DEBUG_PRINTF("    No Input Device attached\n");
                    312:                        break;
                    313:                case 1:
                    314:                        DEBUG_PRINTF("    Input Device status unknown\n");
                    315:                        break;
                    316:                case 2:
                    317:                        DEBUG_PRINTF("    Input Device attached\n");
                    318:                        break;
                    319:                case 3:
                    320:                        DEBUG_PRINTF("    Input Device status RESERVED!!\n");
                    321:                        break;
                    322:                }
                    323:        }
                    324: #endif
                    325:        // check wether the stack is "clean" i.e. containing the HLT instruction
                    326:        // we pushed before executing, and pointing to the original stack address...
                    327:        // indicating that the initialization probably was successful
                    328:        if ((pop_word() == 0xf4f4) && (M.x86.R_SS == STACK_SEGMENT)
                    329:            && (M.x86.R_SP == STACK_START_OFFSET)) {
                    330:                DEBUG_PRINTF("Stack is clean, initialization successfull!\n");
                    331:        } else {
                    332:                DEBUG_PRINTF
                    333:                    ("Stack unclean, initialization probably NOT COMPLETE!!!\n");
                    334:                DEBUG_PRINTF("SS:SP = %04x:%04x, expected: %04x:%04x\n",
                    335:                             M.x86.R_SS, M.x86.R_SP, STACK_SEGMENT,
                    336:                             STACK_START_OFFSET);
                    337:        }
                    338: 
                    339: 
                    340:        // TODO: according to the BIOS Boot Spec initializations may be ended using INT18h and setting
                    341:        // the status.
                    342:        // We need to implement INT18 accordingly, pseudo code is in specsbbs101.pdf page 30
                    343:        // (also for Int19)
                    344:        return 0;
                    345: }

unix.superglobalmegacorp.com

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