coreboot/util/vgabios/testbios.c
<<
>>
Prefs
   1#include <stdio.h>
   2#include <stdlib.h>
   3#include <unistd.h>
   4#include <sys/io.h>
   5#include <sys/mman.h>
   6#include <fcntl.h>
   7#include <getopt.h>
   8#include <string.h>
   9
  10#define die(x) { perror(x); exit(1); }
  11#define warn(x) { perror(x);  }
  12
  13#include <x86emu/x86emu.h>
  14#include "helper_exec.h"
  15#include "test.h"
  16#include "pci-userspace.h"
  17
  18void x86emu_dump_xregs(void);
  19int int15_handler(void);
  20int int16_handler(void);
  21int int1A_handler(void);
  22#ifndef _PC
  23int int42_handler(void);
  24#endif
  25int intE6_handler(void);
  26
  27void pushw(u16 val);
  28
  29unsigned short get_device(char *arg_val);
  30
  31extern int teststart, testend;
  32
  33_ptr p;
  34ptr current = 0;
  35unsigned char biosmem[1024 * 1024];
  36
  37int verbose = 0;
  38
  39
  40/* Interrupt multiplexer */
  41
  42void do_int(int num)
  43{
  44        int ret = 0;
  45
  46        printf("int%x vector at %x\n", num, getIntVect(num));
  47
  48        /* This is a pInt leftover */
  49        current->num = num;
  50
  51        switch (num) {
  52#ifndef _PC
  53        case 0x10:
  54        case 0x42:
  55        case 0x6D:
  56
  57                if (getIntVect(num) == 0xFF065) {
  58                        ret = int42_handler();
  59                }
  60                break;
  61#endif
  62        case 0x15:
  63                ret = int15_handler();
  64                break;
  65        case 0x16:
  66                ret = int16_handler();
  67                break;
  68        case 0x1A:
  69                ret = int1A_handler();
  70                break;
  71        case 0xe6:
  72                ret = intE6_handler();
  73                break;
  74        default:
  75                break;
  76        }
  77
  78        if (!ret)
  79                ret = run_bios_int(num);
  80
  81        if (!ret) {
  82                printf("\nint%x: not implemented\n", num);
  83                //x86emu_dump_xregs();
  84        }
  85}
  86
  87unsigned char *mapitin(char *file, off_t where, size_t size)
  88{
  89        void *z;
  90
  91        int fd = open(file, O_RDWR, 0);
  92
  93        if (fd < 0)
  94                die(file);
  95        z = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, where);
  96        if (z == (void *) -1)
  97                die("mmap");
  98        close(fd);
  99
 100        return z;
 101
 102}
 103
 104u8 x_inb(u16 port);
 105u16 x_inw(u16 port);
 106void x_outb(u16 port, u8 val);
 107void x_outw(u16 port, u16 val);
 108u32 x_inl(u16 port);
 109void x_outl(u16 port, u32 val);
 110
 111
 112X86EMU_pioFuncs myfuncs = {
 113        x_inb, x_inw, x_inl,
 114        x_outb, x_outw, x_outl
 115};
 116
 117
 118void usage(char *name)
 119{
 120        printf
 121            ("Usage: %s [-c codesegment] [-s size] [-b base] [-i ip] [-t] <filename> ... \n",
 122             name);
 123}
 124
 125int main(int argc, char **argv)
 126{
 127        char *absegname = 0;
 128        void *abseg = 0;
 129        int i, c, trace = 0;
 130        unsigned char *cp;
 131        char *filename;
 132        size_t size = 0;
 133        int base = 0;
 134        int have_size = 0, have_base = 0, have_ip = 0, have_cs = 0;
 135        int have_devfn = 0;
 136        int parse_rom = 0;
 137        char *fsegname = 0;
 138        unsigned char *fsegptr;
 139        unsigned short initialip = 0, initialcs = 0, devfn = 0;
 140        X86EMU_intrFuncs intFuncs[256];
 141        void X86EMU_setMemBase(void *base, size_t size);
 142        void x86emu_dump_xregs(void);
 143        int X86EMU_set_debug(int debug);
 144        int debugflag = 0;
 145
 146        const char *optstring = "vh?b:i:c:s:tpd:";
 147        while (1) {
 148                int option_index = 0;
 149                static struct option long_options[] = {
 150                        {"verbose", 0, 0, 'v'},
 151                        {"help", 0, 0, 'h'},
 152                        {"trace", 0, 0, 't'},
 153                        {"base", 1, 0, 'b'},
 154                        {"fseg", 1, 0, 'f'},
 155                        {"instructionpointer", 1, 0, 'i'},
 156                        {"codesegment", 1, 0, 'c'},
 157                        {"absegment", 1, 0, 'a'},
 158                        {"size", 1, 0, 's'},
 159                        {"parserom", 0, 0, 'p'},
 160                        {"device", 1, 0, 'd'},
 161                        {"debug", 1, 0, 'D'},
 162                        {0, 0, 0, 0}
 163                };
 164                c = getopt_long(argc, argv, optstring, long_options, &option_index);
 165                if (c == -1)
 166                        break;
 167                switch (c) {
 168                case 'v':
 169                        verbose = 1;
 170                        break;
 171                case 'h':
 172                case '?':
 173                        usage(argv[0]);
 174                        return 0;
 175                case 't':
 176                        trace = 1;
 177                        break;
 178                case 'b':
 179                        base = strtol(optarg, 0, 0);
 180                        have_base = 1;
 181                        break;
 182                case 'i':
 183                        initialip = strtol(optarg, 0, 0);
 184                        have_ip = 1;
 185                        break;
 186                case 'c':
 187                        initialcs = strtol(optarg, 0, 0);
 188                        have_cs = 1;
 189                        break;
 190                case 's':
 191                        size = strtol(optarg, 0, 0);
 192                        have_size = 1;
 193                        break;
 194                case 'p':
 195                        printf("Parsing rom images not implemented.\n");
 196                        parse_rom = 1;
 197                        break;
 198                case 'f':
 199                        fsegname = optarg;
 200                        break;
 201                case 'a':
 202                        absegname = optarg;
 203                        break;
 204                case 'd':
 205                        devfn = get_device(optarg);
 206                        have_devfn = 1;
 207                        break;
 208                case 'D':
 209                        debugflag = strtol(optarg, 0, 0);
 210                        break;
 211                default:
 212                        printf("Unknown option \n");
 213                        usage(argv[0]);
 214                        return 1;
 215                }
 216        }
 217
 218        if (optind >= argc) {
 219                printf("Filename missing.\n");
 220                usage(argv[0]);
 221                return 1;
 222        }
 223
 224        while (optind < argc) {
 225                printf("running file %s\n", argv[optind]);
 226                filename = argv[optind];
 227                optind++;
 228                /* normally we would do continue, but for
 229                 * now only one filename is supported.
 230                 */
 231                /* continue; */
 232                break;
 233        }
 234
 235        if (!have_size) {
 236                printf("No size specified. defaulting to 32k\n");
 237                size = 32 * 1024;
 238        }
 239        if (!have_base) {
 240                printf("No base specified. defaulting to 0xc0000\n");
 241                base = 0xc0000;
 242        }
 243        if (!have_cs) {
 244                printf("No initial code segment specified. defaulting to 0xc000\n");
 245                initialcs = 0xc000;
 246        }
 247        if (!have_ip) {
 248                printf
 249                    ("No initial instruction pointer specified. defaulting to 0x0003\n");
 250                initialip = 0x0003;
 251        }
 252
 253        //printf("Point 1 int%x vector at %x\n", 0x42, getIntVect(0x42));
 254
 255        if (initialip == 0x0003) {
 256                if ((devfn == 0) || (have_devfn == 0)) {
 257                        printf("WARNING! It appears you are trying to run an option ROM.\n");
 258                        printf("  (initial ip = 0x0003)\n");
 259                        if (have_devfn) {
 260                                printf("  However, the device you have specified is 0x00\n");
 261                                printf("  It is very unlikely that your device is at this address\n");
 262                                printf("  Please check your -d option\n");
 263                        }
 264                        else {
 265                                printf("  Please specify a device with -d\n");
 266                                printf("  The default is not likely to work\n");
 267                        }
 268                }
 269        }
 270
 271        if (absegname) {
 272                abseg = mapitin(absegname, (off_t) 0xa0000, 0x20000);
 273                if (!abseg)
 274                        die(absegname);
 275        }
 276
 277        current = &p;
 278        X86EMU_setMemBase(biosmem, sizeof(biosmem));
 279        M.abseg = (unsigned long)abseg;
 280        X86EMU_setupPioFuncs(&myfuncs);
 281        ioperm(0, 0x400, 1);
 282
 283        if (iopl(3) < 0) {
 284                warn("iopl failed, continuing anyway");
 285        }
 286
 287        /* Emergency sync ;-) */
 288        sync();
 289        sync();
 290
 291        /* Setting up interrupt environment.
 292         * basically this means initializing PCI and
 293         * intXX handlers.
 294         */
 295        pciInit();
 296
 297        for (i = 0; i < 256; i++)
 298                intFuncs[i] = do_int;
 299        X86EMU_setupIntrFuncs(intFuncs);
 300        cp = mapitin(filename, (off_t) 0, size);
 301
 302        if (devfn) {
 303                printf("Loading ax with BusDevFn = %x\n",devfn);
 304        }
 305
 306        current->ax = devfn   ? devfn : 0xff;
 307        current->dx = 0x80;
 308        //      current->ip = 0;
 309        for (i = 0; i < size; i++)
 310                wrb(base + i, cp[i]);
 311
 312        if (fsegname) {
 313                fsegptr = mapitin(fsegname, (off_t) 0, 0x10000);
 314                for (i = 0; i < 0x10000; i++)
 315                        wrb(0xf0000 + i, fsegptr[i]);
 316        } else {
 317                char *date = "01/01/99";
 318                for (i = i; date[i]; i++)
 319                        wrb(0xffff5 + i, date[i]);
 320                wrb(0xffff7, '/');
 321                wrb(0xffffa, '/');
 322        }
 323        /* cpu setup */
 324        X86_AX = devfn ? devfn : 0xff;
 325        X86_DX = 0x80;
 326        X86_EIP = initialip;
 327        X86_CS = initialcs;
 328
 329        /* Initialize stack and data segment */
 330        X86_SS = 0x0030;
 331        X86_DS = 0x0040;
 332        X86_SP = 0xfffe;
 333        /* We need a sane way to return from bios
 334         * execution. A hlt instruction and a pointer
 335         * to it, both kept on the stack, will do.
 336         */
 337        pushw(0xf4f4);          /* hlt; hlt */
 338        pushw(X86_SS);
 339        pushw(X86_SP + 2);
 340
 341        X86_ES = 0x0000;
 342
 343        if (trace) {
 344                printf("Switching to single step mode.\n");
 345                //X86EMU_trace_on();
 346        }
 347        if (debugflag) {
 348                //X86EMU_set_debug(debugflag);
 349        }
 350        X86EMU_exec();
 351        /* Cleaning up */
 352        pciExit();
 353
 354        return 0;
 355}
 356
 357unsigned short get_device(char *arg_val)
 358{
 359        unsigned short devfn=0;
 360        long bus=0,dev=0,fn=0,need_pack=0;
 361        char *tok;
 362
 363        tok = strsep(&arg_val,":");
 364        if (arg_val != NULL) {
 365                bus = strtol(tok,0,16);
 366                need_pack = 1;
 367        }
 368        else {
 369                arg_val = tok;
 370        }
 371
 372        tok = strsep(&arg_val,".");
 373        if (arg_val != NULL) {
 374                dev = strtol(tok,0,16);
 375                fn  = strtol(arg_val,0,16);
 376                need_pack = 1;
 377        }
 378        else {
 379                if (need_pack ==1 && (strlen(tok))) {
 380                        dev = strtol(tok,0,16);
 381                }
 382        }
 383
 384        if ( need_pack == 1) {
 385                devfn = bus<<8 | (dev<<3) | fn;
 386        }
 387        else {
 388                devfn = strtol(tok, 0, 0);
 389        }
 390
 391
 392        return devfn;
 393}
 394
 395
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.