Commit 330d0414a5968d36edb635c63a729ffa55520e76
1 parent
3802ce26
keyboard emulation - accepts to boot with Bochs BIOS and LGPL'ed VGA BIOS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@338 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
605 additions
and
92 deletions
vl.c
@@ -52,10 +52,28 @@ | @@ -52,10 +52,28 @@ | ||
52 | 52 | ||
53 | #define DEBUG_LOGFILE "/tmp/vl.log" | 53 | #define DEBUG_LOGFILE "/tmp/vl.log" |
54 | #define DEFAULT_NETWORK_SCRIPT "/etc/vl-ifup" | 54 | #define DEFAULT_NETWORK_SCRIPT "/etc/vl-ifup" |
55 | +#define BIOS_FILENAME "bios.bin" | ||
56 | +#define VGABIOS_FILENAME "vgabios.bin" | ||
55 | 57 | ||
56 | //#define DEBUG_UNUSED_IOPORT | 58 | //#define DEBUG_UNUSED_IOPORT |
59 | + | ||
57 | //#define DEBUG_IRQ_LATENCY | 60 | //#define DEBUG_IRQ_LATENCY |
58 | 61 | ||
62 | +/* output Bochs bios info messages */ | ||
63 | +//#define DEBUG_BIOS | ||
64 | + | ||
65 | +/* debug IDE devices */ | ||
66 | +//#define DEBUG_IDE | ||
67 | + | ||
68 | +/* debug PIC */ | ||
69 | +//#define DEBUG_PIC | ||
70 | + | ||
71 | +/* debug NE2000 card */ | ||
72 | +//#define DEBUG_NE2000 | ||
73 | + | ||
74 | +/* debug PC keyboard */ | ||
75 | +//#define DEBUG_KBD | ||
76 | + | ||
59 | #define PHYS_RAM_BASE 0xac000000 | 77 | #define PHYS_RAM_BASE 0xac000000 |
60 | #define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) | 78 | #define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) |
61 | 79 | ||
@@ -185,6 +203,7 @@ typedef uint32_t (IOPortReadFunc)(CPUX86State *env, uint32_t address); | @@ -185,6 +203,7 @@ typedef uint32_t (IOPortReadFunc)(CPUX86State *env, uint32_t address); | ||
185 | 203 | ||
186 | #define MAX_IOPORTS 4096 | 204 | #define MAX_IOPORTS 4096 |
187 | 205 | ||
206 | +static const char *interp_prefix = CONFIG_QEMU_PREFIX; | ||
188 | char phys_ram_file[1024]; | 207 | char phys_ram_file[1024]; |
189 | CPUX86State *global_env; | 208 | CPUX86State *global_env; |
190 | CPUX86State *cpu_single_env; | 209 | CPUX86State *cpu_single_env; |
@@ -216,15 +235,15 @@ void default_ioport_writeb(CPUX86State *env, uint32_t address, uint32_t data) | @@ -216,15 +235,15 @@ void default_ioport_writeb(CPUX86State *env, uint32_t address, uint32_t data) | ||
216 | uint32_t default_ioport_readw(CPUX86State *env, uint32_t address) | 235 | uint32_t default_ioport_readw(CPUX86State *env, uint32_t address) |
217 | { | 236 | { |
218 | uint32_t data; | 237 | uint32_t data; |
219 | - data = ioport_read_table[0][address](env, address); | ||
220 | - data |= ioport_read_table[0][address + 1](env, address + 1) << 8; | 238 | + data = ioport_read_table[0][address & (MAX_IOPORTS - 1)](env, address); |
239 | + data |= ioport_read_table[0][(address + 1) & (MAX_IOPORTS - 1)](env, address + 1) << 8; | ||
221 | return data; | 240 | return data; |
222 | } | 241 | } |
223 | 242 | ||
224 | void default_ioport_writew(CPUX86State *env, uint32_t address, uint32_t data) | 243 | void default_ioport_writew(CPUX86State *env, uint32_t address, uint32_t data) |
225 | { | 244 | { |
226 | - ioport_write_table[0][address](env, address, data & 0xff); | ||
227 | - ioport_write_table[0][address + 1](env, address + 1, (data >> 8) & 0xff); | 245 | + ioport_write_table[0][address & (MAX_IOPORTS - 1)](env, address, data & 0xff); |
246 | + ioport_write_table[0][(address + 1) & (MAX_IOPORTS - 1)](env, address + 1, (data >> 8) & 0xff); | ||
228 | } | 247 | } |
229 | 248 | ||
230 | uint32_t default_ioport_readl(CPUX86State *env, uint32_t address) | 249 | uint32_t default_ioport_readl(CPUX86State *env, uint32_t address) |
@@ -516,6 +535,7 @@ void cmos_init(void) | @@ -516,6 +535,7 @@ void cmos_init(void) | ||
516 | { | 535 | { |
517 | struct tm *tm; | 536 | struct tm *tm; |
518 | time_t ti; | 537 | time_t ti; |
538 | + int val; | ||
519 | 539 | ||
520 | ti = time(NULL); | 540 | ti = time(NULL); |
521 | tm = gmtime(&ti); | 541 | tm = gmtime(&ti); |
@@ -532,8 +552,27 @@ void cmos_init(void) | @@ -532,8 +552,27 @@ void cmos_init(void) | ||
532 | cmos_data[RTC_REG_C] = 0x00; | 552 | cmos_data[RTC_REG_C] = 0x00; |
533 | cmos_data[RTC_REG_D] = 0x80; | 553 | cmos_data[RTC_REG_D] = 0x80; |
534 | 554 | ||
555 | + /* various important CMOS locations needed by PC/Bochs bios */ | ||
556 | + | ||
535 | cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */ | 557 | cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */ |
536 | 558 | ||
559 | + /* memory size */ | ||
560 | + val = (phys_ram_size / 1024) - 1024; | ||
561 | + if (val > 65535) | ||
562 | + val = 65535; | ||
563 | + cmos_data[0x17] = val; | ||
564 | + cmos_data[0x18] = val >> 8; | ||
565 | + cmos_data[0x30] = val; | ||
566 | + cmos_data[0x31] = val >> 8; | ||
567 | + | ||
568 | + val = (phys_ram_size / 65536) - ((16 * 1024 * 1024) / 65536); | ||
569 | + if (val > 65535) | ||
570 | + val = 65535; | ||
571 | + cmos_data[0x34] = val; | ||
572 | + cmos_data[0x35] = val >> 8; | ||
573 | + | ||
574 | + cmos_data[0x3d] = 0x02; /* hard drive boot */ | ||
575 | + | ||
537 | register_ioport_write(0x70, 2, cmos_ioport_write, 1); | 576 | register_ioport_write(0x70, 2, cmos_ioport_write, 1); |
538 | register_ioport_read(0x70, 2, cmos_ioport_read, 1); | 577 | register_ioport_read(0x70, 2, cmos_ioport_read, 1); |
539 | } | 578 | } |
@@ -541,8 +580,6 @@ void cmos_init(void) | @@ -541,8 +580,6 @@ void cmos_init(void) | ||
541 | /***********************************************************/ | 580 | /***********************************************************/ |
542 | /* 8259 pic emulation */ | 581 | /* 8259 pic emulation */ |
543 | 582 | ||
544 | -//#define DEBUG_PIC | ||
545 | - | ||
546 | typedef struct PicState { | 583 | typedef struct PicState { |
547 | uint8_t last_irr; /* edge detection */ | 584 | uint8_t last_irr; /* edge detection */ |
548 | uint8_t irr; /* interrupt request register */ | 585 | uint8_t irr; /* interrupt request register */ |
@@ -1360,8 +1397,6 @@ void serial_init(void) | @@ -1360,8 +1397,6 @@ void serial_init(void) | ||
1360 | /***********************************************************/ | 1397 | /***********************************************************/ |
1361 | /* ne2000 emulation */ | 1398 | /* ne2000 emulation */ |
1362 | 1399 | ||
1363 | -//#define DEBUG_NE2000 | ||
1364 | - | ||
1365 | #define NE2000_IOPORT 0x300 | 1400 | #define NE2000_IOPORT 0x300 |
1366 | #define NE2000_IRQ 9 | 1401 | #define NE2000_IRQ 9 |
1367 | 1402 | ||
@@ -1827,8 +1862,6 @@ void ne2000_init(void) | @@ -1827,8 +1862,6 @@ void ne2000_init(void) | ||
1827 | /***********************************************************/ | 1862 | /***********************************************************/ |
1828 | /* ide emulation */ | 1863 | /* ide emulation */ |
1829 | 1864 | ||
1830 | -//#define DEBUG_IDE | ||
1831 | - | ||
1832 | /* Bits of HD_STATUS */ | 1865 | /* Bits of HD_STATUS */ |
1833 | #define ERR_STAT 0x01 | 1866 | #define ERR_STAT 0x01 |
1834 | #define INDEX_STAT 0x02 | 1867 | #define INDEX_STAT 0x02 |
@@ -2352,16 +2385,50 @@ uint32_t ide_status_read(CPUX86State *env, uint32_t addr) | @@ -2352,16 +2385,50 @@ uint32_t ide_status_read(CPUX86State *env, uint32_t addr) | ||
2352 | int ret; | 2385 | int ret; |
2353 | ret = s->status; | 2386 | ret = s->status; |
2354 | #ifdef DEBUG_IDE | 2387 | #ifdef DEBUG_IDE |
2355 | - printf("ide: read addr=0x%x val=%02x\n", addr, ret); | 2388 | + printf("ide: read status val=%02x\n", ret); |
2356 | #endif | 2389 | #endif |
2357 | return ret; | 2390 | return ret; |
2358 | } | 2391 | } |
2359 | 2392 | ||
2360 | void ide_cmd_write(CPUX86State *env, uint32_t addr, uint32_t val) | 2393 | void ide_cmd_write(CPUX86State *env, uint32_t addr, uint32_t val) |
2361 | { | 2394 | { |
2362 | - IDEState *s = &ide_state[0]; | 2395 | + IDEState *s; |
2396 | + int i; | ||
2397 | + | ||
2398 | +#ifdef DEBUG_IDE | ||
2399 | + printf("ide: write control val=%02x\n", val); | ||
2400 | +#endif | ||
2363 | /* common for both drives */ | 2401 | /* common for both drives */ |
2364 | - s->cmd = val; | 2402 | + if (!(ide_state[0].cmd & IDE_CMD_RESET) && |
2403 | + (val & IDE_CMD_RESET)) { | ||
2404 | + /* reset low to high */ | ||
2405 | + for(i = 0;i < 2; i++) { | ||
2406 | + s = &ide_state[i]; | ||
2407 | + s->status = BUSY_STAT | SEEK_STAT; | ||
2408 | + s->error = 0x01; | ||
2409 | + } | ||
2410 | + } else if ((ide_state[0].cmd & IDE_CMD_RESET) && | ||
2411 | + !(val & IDE_CMD_RESET)) { | ||
2412 | + /* high to low */ | ||
2413 | + for(i = 0;i < 2; i++) { | ||
2414 | + s = &ide_state[i]; | ||
2415 | + s->status = READY_STAT; | ||
2416 | + /* set hard disk drive ID */ | ||
2417 | + s->select &= 0xf0; /* clear head */ | ||
2418 | + s->nsector = 1; | ||
2419 | + s->sector = 1; | ||
2420 | + if (s->nb_sectors == 0) { | ||
2421 | + /* no disk present */ | ||
2422 | + s->lcyl = 0x12; | ||
2423 | + s->hcyl = 0x34; | ||
2424 | + } else { | ||
2425 | + s->lcyl = 0; | ||
2426 | + s->hcyl = 0; | ||
2427 | + } | ||
2428 | + } | ||
2429 | + } | ||
2430 | + | ||
2431 | + ide_state[0].cmd = val; | ||
2365 | } | 2432 | } |
2366 | 2433 | ||
2367 | void ide_data_writew(CPUX86State *env, uint32_t addr, uint32_t val) | 2434 | void ide_data_writew(CPUX86State *env, uint32_t addr, uint32_t val) |
@@ -2439,14 +2506,17 @@ void ide_init(void) | @@ -2439,14 +2506,17 @@ void ide_init(void) | ||
2439 | s->bs = bs_table[i]; | 2506 | s->bs = bs_table[i]; |
2440 | if (s->bs) { | 2507 | if (s->bs) { |
2441 | bdrv_get_geometry(s->bs, &nb_sectors); | 2508 | bdrv_get_geometry(s->bs, &nb_sectors); |
2442 | - cylinders = nb_sectors / (16 * 63); | ||
2443 | - if (cylinders > 16383) | ||
2444 | - cylinders = 16383; | ||
2445 | - else if (cylinders < 2) | ||
2446 | - cylinders = 2; | ||
2447 | - s->cylinders = cylinders; | ||
2448 | - s->heads = 16; | ||
2449 | - s->sectors = 63; | 2509 | + if (s->cylinders == 0) { |
2510 | + /* if no geometry, use a LBA compatible one */ | ||
2511 | + cylinders = nb_sectors / (16 * 63); | ||
2512 | + if (cylinders > 16383) | ||
2513 | + cylinders = 16383; | ||
2514 | + else if (cylinders < 2) | ||
2515 | + cylinders = 2; | ||
2516 | + s->cylinders = cylinders; | ||
2517 | + s->heads = 16; | ||
2518 | + s->sectors = 63; | ||
2519 | + } | ||
2450 | s->nb_sectors = nb_sectors; | 2520 | s->nb_sectors = nb_sectors; |
2451 | } | 2521 | } |
2452 | s->irq = 14; | 2522 | s->irq = 14; |
@@ -2465,34 +2535,402 @@ void ide_init(void) | @@ -2465,34 +2535,402 @@ void ide_init(void) | ||
2465 | } | 2535 | } |
2466 | 2536 | ||
2467 | /***********************************************************/ | 2537 | /***********************************************************/ |
2468 | -/* simulate reset (stop qemu) */ | 2538 | +/* keyboard emulation */ |
2539 | + | ||
2540 | +/* Keyboard Controller Commands */ | ||
2541 | +#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */ | ||
2542 | +#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */ | ||
2543 | +#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */ | ||
2544 | +#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */ | ||
2545 | +#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */ | ||
2546 | +#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */ | ||
2547 | +#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */ | ||
2548 | +#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */ | ||
2549 | +#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */ | ||
2550 | +#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */ | ||
2551 | +#define KBD_CCMD_READ_INPORT 0xC0 /* read input port */ | ||
2552 | +#define KBD_CCMD_READ_OUTPORT 0xD0 /* read output port */ | ||
2553 | +#define KBD_CCMD_WRITE_OUTPORT 0xD1 /* write output port */ | ||
2554 | +#define KBD_CCMD_WRITE_OBUF 0xD2 | ||
2555 | +#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if | ||
2556 | + initiated by the auxiliary device */ | ||
2557 | +#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */ | ||
2558 | +#define KBD_CCMD_ENABLE_A20 0xDD | ||
2559 | +#define KBD_CCMD_DISABLE_A20 0xDF | ||
2560 | +#define KBD_CCMD_RESET 0xFE | ||
2561 | + | ||
2562 | +/* Keyboard Commands */ | ||
2563 | +#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ | ||
2564 | +#define KBD_CMD_ECHO 0xEE | ||
2565 | +#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ | ||
2566 | +#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ | ||
2567 | +#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */ | ||
2568 | +#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */ | ||
2569 | +#define KBD_CMD_RESET 0xFF /* Reset */ | ||
2570 | + | ||
2571 | +/* Keyboard Replies */ | ||
2572 | +#define KBD_REPLY_POR 0xAA /* Power on reset */ | ||
2573 | +#define KBD_REPLY_ACK 0xFA /* Command ACK */ | ||
2574 | +#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ | ||
2575 | + | ||
2576 | +/* Status Register Bits */ | ||
2577 | +#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */ | ||
2578 | +#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ | ||
2579 | +#define KBD_STAT_SELFTEST 0x04 /* Self test successful */ | ||
2580 | +#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */ | ||
2581 | +#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */ | ||
2582 | +#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ | ||
2583 | +#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */ | ||
2584 | +#define KBD_STAT_PERR 0x80 /* Parity error */ | ||
2585 | + | ||
2586 | +/* Controller Mode Register Bits */ | ||
2587 | +#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */ | ||
2588 | +#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */ | ||
2589 | +#define KBD_MODE_SYS 0x04 /* The system flag (?) */ | ||
2590 | +#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */ | ||
2591 | +#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */ | ||
2592 | +#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */ | ||
2593 | +#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */ | ||
2594 | +#define KBD_MODE_RFU 0x80 | ||
2595 | + | ||
2596 | +/* Mouse Commands */ | ||
2597 | +#define AUX_SET_RES 0xE8 /* Set resolution */ | ||
2598 | +#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ | ||
2599 | +#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ | ||
2600 | +#define AUX_GET_SCALE 0xE9 /* Get scaling factor */ | ||
2601 | +#define AUX_SET_STREAM 0xEA /* Set stream mode */ | ||
2602 | +#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ | ||
2603 | +#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ | ||
2604 | +#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ | ||
2605 | +#define AUX_RESET 0xFF /* Reset aux device */ | ||
2606 | +#define AUX_ACK 0xFA /* Command byte ACK. */ | ||
2607 | + | ||
2608 | +#define KBD_QUEUE_SIZE 64 | ||
2609 | + | ||
2610 | +typedef struct { | ||
2611 | + uint8_t data[KBD_QUEUE_SIZE]; | ||
2612 | + int rptr, wptr, count; | ||
2613 | +} KBDQueue; | ||
2614 | + | ||
2615 | +enum KBDWriteState { | ||
2616 | + KBD_STATE_CMD = 0, | ||
2617 | + KBD_STATE_LED, | ||
2618 | +}; | ||
2469 | 2619 | ||
2620 | +typedef struct KBDState { | ||
2621 | + KBDQueue queues[2]; | ||
2622 | + uint8_t write_cmd; /* if non zero, write data to port 60 is expected */ | ||
2623 | + uint8_t status; | ||
2624 | + uint8_t mode; | ||
2625 | + int kbd_write_cmd; | ||
2626 | + int scan_enabled; | ||
2627 | +} KBDState; | ||
2628 | + | ||
2629 | +KBDState kbd_state; | ||
2470 | int reset_requested; | 2630 | int reset_requested; |
2631 | +int a20_enabled; | ||
2632 | + | ||
2633 | +static void kbd_update_irq(KBDState *s) | ||
2634 | +{ | ||
2635 | + int level; | ||
2636 | + | ||
2637 | + level = ((s->status & KBD_STAT_OBF) && (s->mode & KBD_MODE_KBD_INT)); | ||
2638 | + pic_set_irq(1, level); | ||
2639 | + | ||
2640 | + level = ((s->status & KBD_STAT_MOUSE_OBF) && (s->mode & KBD_MODE_MOUSE_INT)); | ||
2641 | + pic_set_irq(12, level); | ||
2642 | +} | ||
2643 | + | ||
2644 | +static void kbd_queue(KBDState *s, int b, int aux) | ||
2645 | +{ | ||
2646 | + KBDQueue *q = &kbd_state.queues[aux]; | ||
2647 | + | ||
2648 | + if (q->count >= KBD_QUEUE_SIZE) | ||
2649 | + return; | ||
2650 | + q->data[q->wptr] = b; | ||
2651 | + if (++q->wptr == KBD_QUEUE_SIZE) | ||
2652 | + q->wptr = 0; | ||
2653 | + q->count++; | ||
2654 | + s->status |= KBD_STAT_OBF; | ||
2655 | + if (aux) | ||
2656 | + s->status |= KBD_STAT_MOUSE_OBF; | ||
2657 | + kbd_update_irq(s); | ||
2658 | +} | ||
2471 | 2659 | ||
2472 | uint32_t kbd_read_status(CPUX86State *env, uint32_t addr) | 2660 | uint32_t kbd_read_status(CPUX86State *env, uint32_t addr) |
2473 | { | 2661 | { |
2474 | - return 0; | 2662 | + KBDState *s = &kbd_state; |
2663 | + int val; | ||
2664 | + val = s->status; | ||
2665 | +#if defined(DEBUG_KBD) && 0 | ||
2666 | + printf("kbd: read status=0x%02x\n", val); | ||
2667 | +#endif | ||
2668 | + return val; | ||
2475 | } | 2669 | } |
2476 | 2670 | ||
2477 | void kbd_write_command(CPUX86State *env, uint32_t addr, uint32_t val) | 2671 | void kbd_write_command(CPUX86State *env, uint32_t addr, uint32_t val) |
2478 | { | 2672 | { |
2673 | + KBDState *s = &kbd_state; | ||
2674 | + | ||
2675 | +#ifdef DEBUG_KBD | ||
2676 | + printf("kbd: write cmd=0x%02x\n", val); | ||
2677 | +#endif | ||
2479 | switch(val) { | 2678 | switch(val) { |
2480 | - case 0xfe: | 2679 | + case KBD_CCMD_READ_MODE: |
2680 | + kbd_queue(s, s->mode, 0); | ||
2681 | + break; | ||
2682 | + case KBD_CCMD_WRITE_MODE: | ||
2683 | + case KBD_CCMD_WRITE_OBUF: | ||
2684 | + case KBD_CCMD_WRITE_AUX_OBUF: | ||
2685 | + case KBD_CCMD_WRITE_MOUSE: | ||
2686 | + case KBD_CCMD_WRITE_OUTPORT: | ||
2687 | + s->write_cmd = val; | ||
2688 | + break; | ||
2689 | + case KBD_CCMD_MOUSE_DISABLE: | ||
2690 | + s->mode |= KBD_MODE_DISABLE_MOUSE; | ||
2691 | + break; | ||
2692 | + case KBD_CCMD_MOUSE_ENABLE: | ||
2693 | + s->mode &= ~KBD_MODE_DISABLE_MOUSE; | ||
2694 | + break; | ||
2695 | + case KBD_CCMD_TEST_MOUSE: | ||
2696 | + kbd_queue(s, 0x00, 0); | ||
2697 | + break; | ||
2698 | + case KBD_CCMD_SELF_TEST: | ||
2699 | + s->status |= KBD_STAT_SELFTEST; | ||
2700 | + kbd_queue(s, 0x55, 0); | ||
2701 | + break; | ||
2702 | + case KBD_CCMD_KBD_TEST: | ||
2703 | + kbd_queue(s, 0x00, 0); | ||
2704 | + break; | ||
2705 | + case KBD_CCMD_KBD_DISABLE: | ||
2706 | + s->mode |= KBD_MODE_DISABLE_KBD; | ||
2707 | + break; | ||
2708 | + case KBD_CCMD_KBD_ENABLE: | ||
2709 | + s->mode &= ~KBD_MODE_DISABLE_KBD; | ||
2710 | + break; | ||
2711 | + case KBD_CCMD_READ_INPORT: | ||
2712 | + kbd_queue(s, 0x00, 0); | ||
2713 | + break; | ||
2714 | + case KBD_CCMD_READ_OUTPORT: | ||
2715 | + /* XXX: check that */ | ||
2716 | + val = 0x01 | (a20_enabled << 1); | ||
2717 | + if (s->status & KBD_STAT_OBF) | ||
2718 | + val |= 0x10; | ||
2719 | + if (s->status & KBD_STAT_MOUSE_OBF) | ||
2720 | + val |= 0x20; | ||
2721 | + kbd_queue(s, val, 0); | ||
2722 | + break; | ||
2723 | + case KBD_CCMD_ENABLE_A20: | ||
2724 | + a20_enabled = 1; | ||
2725 | + break; | ||
2726 | + case KBD_CCMD_DISABLE_A20: | ||
2727 | + a20_enabled = 0; | ||
2728 | + break; | ||
2729 | + case KBD_CCMD_RESET: | ||
2481 | reset_requested = 1; | 2730 | reset_requested = 1; |
2482 | cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); | 2731 | cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); |
2483 | break; | 2732 | break; |
2484 | default: | 2733 | default: |
2734 | + fprintf(stderr, "vl: unsupported keyboard cmd=0x%02x\n", val); | ||
2735 | + break; | ||
2736 | + } | ||
2737 | +} | ||
2738 | + | ||
2739 | +uint32_t kbd_read_data(CPUX86State *env, uint32_t addr) | ||
2740 | +{ | ||
2741 | + KBDState *s = &kbd_state; | ||
2742 | + KBDQueue *q; | ||
2743 | + int val; | ||
2744 | + | ||
2745 | + q = &s->queues[1]; /* first check AUX data */ | ||
2746 | + if (q->count == 0) | ||
2747 | + q = &s->queues[0]; /* then check KBD data */ | ||
2748 | + if (q->count == 0) { | ||
2749 | + /* XXX: return something else ? */ | ||
2750 | + val = 0; | ||
2751 | + } else { | ||
2752 | + val = q->data[q->rptr]; | ||
2753 | + if (++q->rptr == KBD_QUEUE_SIZE) | ||
2754 | + q->rptr = 0; | ||
2755 | + q->count--; | ||
2756 | + } | ||
2757 | + if (s->queues[1].count == 0) { | ||
2758 | + s->status &= ~KBD_STAT_MOUSE_OBF; | ||
2759 | + if (s->queues[0].count == 0) | ||
2760 | + s->status &= ~KBD_STAT_OBF; | ||
2761 | + kbd_update_irq(s); | ||
2762 | + } | ||
2763 | + | ||
2764 | +#ifdef DEBUG_KBD | ||
2765 | + printf("kbd: read data=0x%02x\n", val); | ||
2766 | +#endif | ||
2767 | + return val; | ||
2768 | +} | ||
2769 | + | ||
2770 | +static void kbd_reset_keyboard(KBDState *s) | ||
2771 | +{ | ||
2772 | + s->scan_enabled = 1; | ||
2773 | +} | ||
2774 | + | ||
2775 | +static void kbd_write_keyboard(KBDState *s, int val) | ||
2776 | +{ | ||
2777 | + switch(s->kbd_write_cmd) { | ||
2778 | + default: | ||
2779 | + case -1: | ||
2780 | + switch(val) { | ||
2781 | + case 0x00: | ||
2782 | + kbd_queue(s, KBD_REPLY_ACK, 0); | ||
2783 | + break; | ||
2784 | + case 0x05: | ||
2785 | + kbd_queue(s, KBD_REPLY_RESEND, 0); | ||
2786 | + break; | ||
2787 | + case KBD_CMD_ECHO: | ||
2788 | + kbd_queue(s, KBD_CMD_ECHO, 0); | ||
2789 | + break; | ||
2790 | + case KBD_CMD_ENABLE: | ||
2791 | + s->scan_enabled = 1; | ||
2792 | + kbd_queue(s, KBD_REPLY_ACK, 0); | ||
2793 | + break; | ||
2794 | + case KBD_CMD_SET_LEDS: | ||
2795 | + case KBD_CMD_SET_RATE: | ||
2796 | + s->kbd_write_cmd = val; | ||
2797 | + break; | ||
2798 | + case KBD_CMD_RESET_DISABLE: | ||
2799 | + kbd_reset_keyboard(s); | ||
2800 | + s->scan_enabled = 0; | ||
2801 | + kbd_queue(s, KBD_REPLY_ACK, 0); | ||
2802 | + break; | ||
2803 | + case KBD_CMD_RESET_ENABLE: | ||
2804 | + kbd_reset_keyboard(s); | ||
2805 | + s->scan_enabled = 1; | ||
2806 | + kbd_queue(s, KBD_REPLY_ACK, 0); | ||
2807 | + break; | ||
2808 | + case KBD_CMD_RESET: | ||
2809 | + kbd_reset_keyboard(s); | ||
2810 | + kbd_queue(s, KBD_REPLY_ACK, 0); | ||
2811 | + kbd_queue(s, KBD_REPLY_POR, 0); | ||
2812 | + break; | ||
2813 | + default: | ||
2814 | + kbd_queue(s, KBD_REPLY_ACK, 0); | ||
2815 | + break; | ||
2816 | + } | ||
2817 | + break; | ||
2818 | + case KBD_CMD_SET_LEDS: | ||
2819 | + kbd_queue(s, KBD_REPLY_ACK, 0); | ||
2820 | + break; | ||
2821 | + case KBD_CMD_SET_RATE: | ||
2822 | + kbd_queue(s, KBD_REPLY_ACK, 0); | ||
2823 | + break; | ||
2824 | + } | ||
2825 | + s->kbd_write_cmd = -1; | ||
2826 | +} | ||
2827 | + | ||
2828 | +void kbd_write_data(CPUX86State *env, uint32_t addr, uint32_t val) | ||
2829 | +{ | ||
2830 | + KBDState *s = &kbd_state; | ||
2831 | + | ||
2832 | +#ifdef DEBUG_KBD | ||
2833 | + printf("kbd: write data=0x%02x\n", val); | ||
2834 | +#endif | ||
2835 | + | ||
2836 | + switch(s->write_cmd) { | ||
2837 | + case 0: | ||
2838 | + kbd_write_keyboard(s, val); | ||
2839 | + break; | ||
2840 | + case KBD_CCMD_WRITE_MODE: | ||
2841 | + s->mode = val; | ||
2842 | + kbd_update_irq(s); | ||
2843 | + break; | ||
2844 | + case KBD_CCMD_WRITE_OBUF: | ||
2845 | + kbd_queue(s, val, 0); | ||
2846 | + break; | ||
2847 | + case KBD_CCMD_WRITE_AUX_OBUF: | ||
2848 | + kbd_queue(s, val, 1); | ||
2849 | + break; | ||
2850 | + case KBD_CCMD_WRITE_OUTPORT: | ||
2851 | + a20_enabled = (val >> 1) & 1; | ||
2852 | + if (!(val & 1)) { | ||
2853 | + reset_requested = 1; | ||
2854 | + cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); | ||
2855 | + } | ||
2856 | + break; | ||
2857 | + default: | ||
2485 | break; | 2858 | break; |
2486 | } | 2859 | } |
2860 | + s->write_cmd = 0; | ||
2861 | +} | ||
2862 | + | ||
2863 | +void kbd_reset(KBDState *s) | ||
2864 | +{ | ||
2865 | + KBDQueue *q; | ||
2866 | + int i; | ||
2867 | + | ||
2868 | + s->kbd_write_cmd = -1; | ||
2869 | + s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT; | ||
2870 | + s->status = KBD_MODE_SYS | KBD_MODE_NO_KEYLOCK; | ||
2871 | + for(i = 0; i < 2; i++) { | ||
2872 | + q = &s->queues[i]; | ||
2873 | + q->rptr = 0; | ||
2874 | + q->wptr = 0; | ||
2875 | + q->count = 0; | ||
2876 | + } | ||
2487 | } | 2877 | } |
2488 | 2878 | ||
2489 | void kbd_init(void) | 2879 | void kbd_init(void) |
2490 | { | 2880 | { |
2881 | + kbd_reset(&kbd_state); | ||
2882 | + register_ioport_read(0x60, 1, kbd_read_data, 1); | ||
2883 | + register_ioport_write(0x60, 1, kbd_write_data, 1); | ||
2491 | register_ioport_read(0x64, 1, kbd_read_status, 1); | 2884 | register_ioport_read(0x64, 1, kbd_read_status, 1); |
2492 | register_ioport_write(0x64, 1, kbd_write_command, 1); | 2885 | register_ioport_write(0x64, 1, kbd_write_command, 1); |
2493 | } | 2886 | } |
2494 | 2887 | ||
2495 | /***********************************************************/ | 2888 | /***********************************************************/ |
2889 | +/* Bochs BIOS debug ports */ | ||
2890 | + | ||
2891 | +void bochs_bios_write(CPUX86State *env, uint32_t addr, uint32_t val) | ||
2892 | +{ | ||
2893 | + switch(addr) { | ||
2894 | + /* Bochs BIOS messages */ | ||
2895 | + case 0x400: | ||
2896 | + case 0x401: | ||
2897 | + fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val); | ||
2898 | + exit(1); | ||
2899 | + case 0x402: | ||
2900 | + case 0x403: | ||
2901 | +#ifdef DEBUG_BIOS | ||
2902 | + fprintf(stderr, "%c", val); | ||
2903 | +#endif | ||
2904 | + break; | ||
2905 | + | ||
2906 | + /* LGPL'ed VGA BIOS messages */ | ||
2907 | + case 0x501: | ||
2908 | + case 0x502: | ||
2909 | + fprintf(stderr, "VGA BIOS panic, line %d\n", val); | ||
2910 | + exit(1); | ||
2911 | + case 0x500: | ||
2912 | + case 0x503: | ||
2913 | +#ifdef DEBUG_BIOS | ||
2914 | + fprintf(stderr, "%c", val); | ||
2915 | +#endif | ||
2916 | + break; | ||
2917 | + } | ||
2918 | +} | ||
2919 | + | ||
2920 | +void bochs_bios_init(void) | ||
2921 | +{ | ||
2922 | + register_ioport_write(0x400, 1, bochs_bios_write, 2); | ||
2923 | + register_ioport_write(0x401, 1, bochs_bios_write, 2); | ||
2924 | + register_ioport_write(0x402, 1, bochs_bios_write, 1); | ||
2925 | + register_ioport_write(0x403, 1, bochs_bios_write, 1); | ||
2926 | + | ||
2927 | + register_ioport_write(0x501, 1, bochs_bios_write, 2); | ||
2928 | + register_ioport_write(0x502, 1, bochs_bios_write, 2); | ||
2929 | + register_ioport_write(0x500, 1, bochs_bios_write, 1); | ||
2930 | + register_ioport_write(0x503, 1, bochs_bios_write, 1); | ||
2931 | +} | ||
2932 | + | ||
2933 | +/***********************************************************/ | ||
2496 | /* cpu signal handler */ | 2934 | /* cpu signal handler */ |
2497 | static void host_segv_handler(int host_signum, siginfo_t *info, | 2935 | static void host_segv_handler(int host_signum, siginfo_t *info, |
2498 | void *puc) | 2936 | void *puc) |
@@ -2625,7 +3063,7 @@ int main_loop(void *opaque) | @@ -2625,7 +3063,7 @@ int main_loop(void *opaque) | ||
2625 | void help(void) | 3063 | void help(void) |
2626 | { | 3064 | { |
2627 | printf("Virtual Linux version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" | 3065 | printf("Virtual Linux version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" |
2628 | - "usage: vl [options] bzImage [kernel parameters...]\n" | 3066 | + "usage: vl [options] [bzImage [kernel parameters...]]\n" |
2629 | "\n" | 3067 | "\n" |
2630 | "'bzImage' is a Linux kernel image (PAGE_OFFSET must be defined\n" | 3068 | "'bzImage' is a Linux kernel image (PAGE_OFFSET must be defined\n" |
2631 | "to 0x90000000 in asm/page.h and arch/i386/vmlinux.lds)\n" | 3069 | "to 0x90000000 in asm/page.h and arch/i386/vmlinux.lds)\n" |
@@ -2638,10 +3076,12 @@ void help(void) | @@ -2638,10 +3076,12 @@ void help(void) | ||
2638 | "-m megs set virtual RAM size to megs MB\n" | 3076 | "-m megs set virtual RAM size to megs MB\n" |
2639 | "-n script set network init script [default=%s]\n" | 3077 | "-n script set network init script [default=%s]\n" |
2640 | "\n" | 3078 | "\n" |
2641 | - "Debug options:\n" | 3079 | + "Debug/Expert options:\n" |
2642 | "-s wait gdb connection to port %d\n" | 3080 | "-s wait gdb connection to port %d\n" |
2643 | "-p port change gdb connection port\n" | 3081 | "-p port change gdb connection port\n" |
2644 | "-d output log in /tmp/vl.log\n" | 3082 | "-d output log in /tmp/vl.log\n" |
3083 | + "-hdachs c,h,s force hard disk 0 geometry for non LBA disk images\n" | ||
3084 | + "-L path set the directory for the BIOS and VGA BIOS\n" | ||
2645 | "\n" | 3085 | "\n" |
2646 | "During emulation, use C-a h to get terminal commands:\n", | 3086 | "During emulation, use C-a h to get terminal commands:\n", |
2647 | DEFAULT_NETWORK_SCRIPT, DEFAULT_GDBSTUB_PORT); | 3087 | DEFAULT_NETWORK_SCRIPT, DEFAULT_GDBSTUB_PORT); |
@@ -2654,13 +3094,14 @@ struct option long_options[] = { | @@ -2654,13 +3094,14 @@ struct option long_options[] = { | ||
2654 | { "hda", 1, NULL, 0, }, | 3094 | { "hda", 1, NULL, 0, }, |
2655 | { "hdb", 1, NULL, 0, }, | 3095 | { "hdb", 1, NULL, 0, }, |
2656 | { "snapshot", 0, NULL, 0, }, | 3096 | { "snapshot", 0, NULL, 0, }, |
3097 | + { "hdachs", 1, NULL, 0, }, | ||
2657 | { NULL, 0, NULL, 0 }, | 3098 | { NULL, 0, NULL, 0 }, |
2658 | }; | 3099 | }; |
2659 | 3100 | ||
2660 | int main(int argc, char **argv) | 3101 | int main(int argc, char **argv) |
2661 | { | 3102 | { |
2662 | int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; | 3103 | int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; |
2663 | - int snapshot; | 3104 | + int snapshot, linux_boot; |
2664 | struct linux_params *params; | 3105 | struct linux_params *params; |
2665 | struct sigaction act; | 3106 | struct sigaction act; |
2666 | struct itimerval itv; | 3107 | struct itimerval itv; |
@@ -2678,8 +3119,9 @@ int main(int argc, char **argv) | @@ -2678,8 +3119,9 @@ int main(int argc, char **argv) | ||
2678 | use_gdbstub = 0; | 3119 | use_gdbstub = 0; |
2679 | gdbstub_port = DEFAULT_GDBSTUB_PORT; | 3120 | gdbstub_port = DEFAULT_GDBSTUB_PORT; |
2680 | snapshot = 0; | 3121 | snapshot = 0; |
3122 | + linux_boot = 0; | ||
2681 | for(;;) { | 3123 | for(;;) { |
2682 | - c = getopt_long_only(argc, argv, "hm:dn:sp:", long_options, &long_index); | 3124 | + c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index); |
2683 | if (c == -1) | 3125 | if (c == -1) |
2684 | break; | 3126 | break; |
2685 | switch(c) { | 3127 | switch(c) { |
@@ -2697,6 +3139,28 @@ int main(int argc, char **argv) | @@ -2697,6 +3139,28 @@ int main(int argc, char **argv) | ||
2697 | case 3: | 3139 | case 3: |
2698 | snapshot = 1; | 3140 | snapshot = 1; |
2699 | break; | 3141 | break; |
3142 | + case 4: | ||
3143 | + { | ||
3144 | + int cyls, heads, secs; | ||
3145 | + const char *p; | ||
3146 | + p = optarg; | ||
3147 | + cyls = strtol(p, (char **)&p, 0); | ||
3148 | + if (*p != ',') | ||
3149 | + goto chs_fail; | ||
3150 | + p++; | ||
3151 | + heads = strtol(p, (char **)&p, 0); | ||
3152 | + if (*p != ',') | ||
3153 | + goto chs_fail; | ||
3154 | + p++; | ||
3155 | + secs = strtol(p, (char **)&p, 0); | ||
3156 | + if (*p != '\0') | ||
3157 | + goto chs_fail; | ||
3158 | + ide_state[0].cylinders = cyls; | ||
3159 | + ide_state[0].heads = heads; | ||
3160 | + ide_state[0].sectors = secs; | ||
3161 | + chs_fail: ; | ||
3162 | + } | ||
3163 | + break; | ||
2700 | } | 3164 | } |
2701 | break; | 3165 | break; |
2702 | case 'h': | 3166 | case 'h': |
@@ -2724,9 +3188,15 @@ int main(int argc, char **argv) | @@ -2724,9 +3188,15 @@ int main(int argc, char **argv) | ||
2724 | case 'p': | 3188 | case 'p': |
2725 | gdbstub_port = atoi(optarg); | 3189 | gdbstub_port = atoi(optarg); |
2726 | break; | 3190 | break; |
3191 | + case 'L': | ||
3192 | + interp_prefix = optarg; | ||
3193 | + break; | ||
2727 | } | 3194 | } |
2728 | } | 3195 | } |
2729 | - if (optind >= argc) | 3196 | + |
3197 | + linux_boot = (optind < argc); | ||
3198 | + | ||
3199 | + if (!linux_boot && hd_filename[0] == '\0') | ||
2730 | help(); | 3200 | help(); |
2731 | 3201 | ||
2732 | /* init debug */ | 3202 | /* init debug */ |
@@ -2781,46 +3251,119 @@ int main(int argc, char **argv) | @@ -2781,46 +3251,119 @@ int main(int argc, char **argv) | ||
2781 | } | 3251 | } |
2782 | } | 3252 | } |
2783 | 3253 | ||
2784 | - /* now we can load the kernel */ | ||
2785 | - ret = load_kernel(argv[optind], phys_ram_base + KERNEL_LOAD_ADDR); | ||
2786 | - if (ret < 0) { | ||
2787 | - fprintf(stderr, "vl: could not load kernel '%s'\n", argv[optind]); | ||
2788 | - exit(1); | ||
2789 | - } | 3254 | + /* init CPU state */ |
3255 | + env = cpu_init(); | ||
3256 | + global_env = env; | ||
3257 | + cpu_single_env = env; | ||
3258 | + | ||
3259 | + init_ioports(); | ||
2790 | 3260 | ||
2791 | - /* load initrd */ | ||
2792 | - initrd_size = 0; | ||
2793 | - if (initrd_filename) { | ||
2794 | - initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR); | ||
2795 | - if (initrd_size < 0) { | ||
2796 | - fprintf(stderr, "vl: could not load initial ram disk '%s'\n", | ||
2797 | - initrd_filename); | 3261 | + if (linux_boot) { |
3262 | + /* now we can load the kernel */ | ||
3263 | + ret = load_kernel(argv[optind], phys_ram_base + KERNEL_LOAD_ADDR); | ||
3264 | + if (ret < 0) { | ||
3265 | + fprintf(stderr, "vl: could not load kernel '%s'\n", argv[optind]); | ||
2798 | exit(1); | 3266 | exit(1); |
2799 | } | 3267 | } |
2800 | - } | 3268 | + |
3269 | + /* load initrd */ | ||
3270 | + initrd_size = 0; | ||
3271 | + if (initrd_filename) { | ||
3272 | + initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR); | ||
3273 | + if (initrd_size < 0) { | ||
3274 | + fprintf(stderr, "vl: could not load initial ram disk '%s'\n", | ||
3275 | + initrd_filename); | ||
3276 | + exit(1); | ||
3277 | + } | ||
3278 | + } | ||
3279 | + | ||
3280 | + /* init kernel params */ | ||
3281 | + params = (void *)(phys_ram_base + KERNEL_PARAMS_ADDR); | ||
3282 | + memset(params, 0, sizeof(struct linux_params)); | ||
3283 | + params->mount_root_rdonly = 0; | ||
3284 | + params->cl_magic = 0xA33F; | ||
3285 | + params->cl_offset = params->commandline - (uint8_t *)params; | ||
3286 | + params->alt_mem_k = (phys_ram_size / 1024) - 1024; | ||
3287 | + for(i = optind + 1; i < argc; i++) { | ||
3288 | + if (i != optind + 1) | ||
3289 | + pstrcat(params->commandline, sizeof(params->commandline), " "); | ||
3290 | + pstrcat(params->commandline, sizeof(params->commandline), argv[i]); | ||
3291 | + } | ||
3292 | + params->loader_type = 0x01; | ||
3293 | + if (initrd_size > 0) { | ||
3294 | + params->initrd_start = INITRD_LOAD_ADDR; | ||
3295 | + params->initrd_size = initrd_size; | ||
3296 | + } | ||
3297 | + params->orig_video_lines = 25; | ||
3298 | + params->orig_video_cols = 80; | ||
3299 | + | ||
3300 | + /* setup basic memory access */ | ||
3301 | + env->cr[0] = 0x00000033; | ||
3302 | + cpu_x86_init_mmu(env); | ||
3303 | + | ||
3304 | + memset(params->idt_table, 0, sizeof(params->idt_table)); | ||
3305 | + | ||
3306 | + params->gdt_table[2] = 0x00cf9a000000ffffLL; /* KERNEL_CS */ | ||
3307 | + params->gdt_table[3] = 0x00cf92000000ffffLL; /* KERNEL_DS */ | ||
3308 | + | ||
3309 | + env->idt.base = (void *)params->idt_table; | ||
3310 | + env->idt.limit = sizeof(params->idt_table) - 1; | ||
3311 | + env->gdt.base = (void *)params->gdt_table; | ||
3312 | + env->gdt.limit = sizeof(params->gdt_table) - 1; | ||
3313 | + | ||
3314 | + cpu_x86_load_seg(env, R_CS, KERNEL_CS); | ||
3315 | + cpu_x86_load_seg(env, R_DS, KERNEL_DS); | ||
3316 | + cpu_x86_load_seg(env, R_ES, KERNEL_DS); | ||
3317 | + cpu_x86_load_seg(env, R_SS, KERNEL_DS); | ||
3318 | + cpu_x86_load_seg(env, R_FS, KERNEL_DS); | ||
3319 | + cpu_x86_load_seg(env, R_GS, KERNEL_DS); | ||
3320 | + | ||
3321 | + env->eip = KERNEL_LOAD_ADDR; | ||
3322 | + env->regs[R_ESI] = KERNEL_PARAMS_ADDR; | ||
3323 | + env->eflags = 0x2; | ||
2801 | 3324 | ||
2802 | - /* init kernel params */ | ||
2803 | - params = (void *)(phys_ram_base + KERNEL_PARAMS_ADDR); | ||
2804 | - memset(params, 0, sizeof(struct linux_params)); | ||
2805 | - params->mount_root_rdonly = 0; | ||
2806 | - params->cl_magic = 0xA33F; | ||
2807 | - params->cl_offset = params->commandline - (uint8_t *)params; | ||
2808 | - params->alt_mem_k = (phys_ram_size / 1024) - 1024; | ||
2809 | - for(i = optind + 1; i < argc; i++) { | ||
2810 | - if (i != optind + 1) | ||
2811 | - pstrcat(params->commandline, sizeof(params->commandline), " "); | ||
2812 | - pstrcat(params->commandline, sizeof(params->commandline), argv[i]); | ||
2813 | - } | ||
2814 | - params->loader_type = 0x01; | ||
2815 | - if (initrd_size > 0) { | ||
2816 | - params->initrd_start = INITRD_LOAD_ADDR; | ||
2817 | - params->initrd_size = initrd_size; | 3325 | + } else { |
3326 | + char buf[1024]; | ||
3327 | + | ||
3328 | + /* RAW PC boot */ | ||
3329 | + | ||
3330 | + /* BIOS load */ | ||
3331 | + snprintf(buf, sizeof(buf), "%s/%s", interp_prefix, BIOS_FILENAME); | ||
3332 | + ret = load_image(buf, phys_ram_base + 0x000f0000); | ||
3333 | + if (ret != 0x10000) { | ||
3334 | + fprintf(stderr, "vl: could not load PC bios '%s'\n", BIOS_FILENAME); | ||
3335 | + exit(1); | ||
3336 | + } | ||
3337 | + | ||
3338 | + /* VGA BIOS load */ | ||
3339 | + snprintf(buf, sizeof(buf), "%s/%s", interp_prefix, VGABIOS_FILENAME); | ||
3340 | + ret = load_image(buf, phys_ram_base + 0x000c0000); | ||
3341 | + | ||
3342 | + /* setup basic memory access */ | ||
3343 | + env->cr[0] = 0x60000010; | ||
3344 | + cpu_x86_init_mmu(env); | ||
3345 | + | ||
3346 | + env->idt.limit = 0xffff; | ||
3347 | + env->gdt.limit = 0xffff; | ||
3348 | + env->ldt.limit = 0xffff; | ||
3349 | + | ||
3350 | + /* not correct (CS base=0xffff0000) */ | ||
3351 | + cpu_x86_load_seg(env, R_CS, 0xf000); | ||
3352 | + cpu_x86_load_seg(env, R_DS, 0); | ||
3353 | + cpu_x86_load_seg(env, R_ES, 0); | ||
3354 | + cpu_x86_load_seg(env, R_SS, 0); | ||
3355 | + cpu_x86_load_seg(env, R_FS, 0); | ||
3356 | + cpu_x86_load_seg(env, R_GS, 0); | ||
3357 | + | ||
3358 | + env->eip = 0xfff0; | ||
3359 | + env->regs[R_EDX] = 0x600; /* indicate P6 processor */ | ||
3360 | + | ||
3361 | + env->eflags = 0x2; | ||
3362 | + | ||
3363 | + bochs_bios_init(); | ||
2818 | } | 3364 | } |
2819 | - params->orig_video_lines = 25; | ||
2820 | - params->orig_video_cols = 80; | ||
2821 | 3365 | ||
2822 | /* init basic PC hardware */ | 3366 | /* init basic PC hardware */ |
2823 | - init_ioports(); | ||
2824 | register_ioport_write(0x80, 1, ioport80_write, 1); | 3367 | register_ioport_write(0x80, 1, ioport80_write, 1); |
2825 | 3368 | ||
2826 | register_ioport_write(0x3d4, 2, vga_ioport_write, 1); | 3369 | register_ioport_write(0x3d4, 2, vga_ioport_write, 1); |
@@ -2843,36 +3386,6 @@ int main(int argc, char **argv) | @@ -2843,36 +3386,6 @@ int main(int argc, char **argv) | ||
2843 | act.sa_sigaction = host_alarm_handler; | 3386 | act.sa_sigaction = host_alarm_handler; |
2844 | sigaction(SIGALRM, &act, NULL); | 3387 | sigaction(SIGALRM, &act, NULL); |
2845 | 3388 | ||
2846 | - /* init CPU state */ | ||
2847 | - env = cpu_init(); | ||
2848 | - global_env = env; | ||
2849 | - cpu_single_env = env; | ||
2850 | - | ||
2851 | - /* setup basic memory access */ | ||
2852 | - env->cr[0] = 0x00000033; | ||
2853 | - cpu_x86_init_mmu(env); | ||
2854 | - | ||
2855 | - memset(params->idt_table, 0, sizeof(params->idt_table)); | ||
2856 | - | ||
2857 | - params->gdt_table[2] = 0x00cf9a000000ffffLL; /* KERNEL_CS */ | ||
2858 | - params->gdt_table[3] = 0x00cf92000000ffffLL; /* KERNEL_DS */ | ||
2859 | - | ||
2860 | - env->idt.base = (void *)params->idt_table; | ||
2861 | - env->idt.limit = sizeof(params->idt_table) - 1; | ||
2862 | - env->gdt.base = (void *)params->gdt_table; | ||
2863 | - env->gdt.limit = sizeof(params->gdt_table) - 1; | ||
2864 | - | ||
2865 | - cpu_x86_load_seg(env, R_CS, KERNEL_CS); | ||
2866 | - cpu_x86_load_seg(env, R_DS, KERNEL_DS); | ||
2867 | - cpu_x86_load_seg(env, R_ES, KERNEL_DS); | ||
2868 | - cpu_x86_load_seg(env, R_SS, KERNEL_DS); | ||
2869 | - cpu_x86_load_seg(env, R_FS, KERNEL_DS); | ||
2870 | - cpu_x86_load_seg(env, R_GS, KERNEL_DS); | ||
2871 | - | ||
2872 | - env->eip = KERNEL_LOAD_ADDR; | ||
2873 | - env->regs[R_ESI] = KERNEL_PARAMS_ADDR; | ||
2874 | - env->eflags = 0x2; | ||
2875 | - | ||
2876 | itv.it_interval.tv_sec = 0; | 3389 | itv.it_interval.tv_sec = 0; |
2877 | itv.it_interval.tv_usec = 1000; | 3390 | itv.it_interval.tv_usec = 1000; |
2878 | itv.it_value.tv_sec = 0; | 3391 | itv.it_value.tv_sec = 0; |