52 |
|
|
53 |
#define DEBUG_LOGFILE "/tmp/vl.log" |
#define DEBUG_LOGFILE "/tmp/vl.log" |
54 |
#define DEFAULT_NETWORK_SCRIPT "/etc/vl-ifup" |
#define DEFAULT_NETWORK_SCRIPT "/etc/vl-ifup" |
55 |
|
#define BIOS_FILENAME "bios.bin" |
56 |
|
#define VGABIOS_FILENAME "vgabios.bin" |
57 |
|
|
58 |
//#define DEBUG_UNUSED_IOPORT |
//#define DEBUG_UNUSED_IOPORT |
59 |
|
|
60 |
//#define DEBUG_IRQ_LATENCY |
//#define DEBUG_IRQ_LATENCY |
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 |
|
|
77 |
#define PHYS_RAM_BASE 0xac000000 |
#define PHYS_RAM_BASE 0xac000000 |
78 |
#define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) |
#define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) |
79 |
|
|
203 |
|
|
204 |
#define MAX_IOPORTS 4096 |
#define MAX_IOPORTS 4096 |
205 |
|
|
206 |
|
static const char *interp_prefix = CONFIG_QEMU_PREFIX; |
207 |
char phys_ram_file[1024]; |
char phys_ram_file[1024]; |
208 |
CPUX86State *global_env; |
CPUX86State *global_env; |
209 |
CPUX86State *cpu_single_env; |
CPUX86State *cpu_single_env; |
235 |
uint32_t default_ioport_readw(CPUX86State *env, uint32_t address) |
uint32_t default_ioport_readw(CPUX86State *env, uint32_t address) |
236 |
{ |
{ |
237 |
uint32_t data; |
uint32_t data; |
238 |
data = ioport_read_table[0][address](env, address); |
data = ioport_read_table[0][address & (MAX_IOPORTS - 1)](env, address); |
239 |
data |= ioport_read_table[0][address + 1](env, address + 1) << 8; |
data |= ioport_read_table[0][(address + 1) & (MAX_IOPORTS - 1)](env, address + 1) << 8; |
240 |
return data; |
return data; |
241 |
} |
} |
242 |
|
|
243 |
void default_ioport_writew(CPUX86State *env, uint32_t address, uint32_t data) |
void default_ioport_writew(CPUX86State *env, uint32_t address, uint32_t data) |
244 |
{ |
{ |
245 |
ioport_write_table[0][address](env, address, data & 0xff); |
ioport_write_table[0][address & (MAX_IOPORTS - 1)](env, address, data & 0xff); |
246 |
ioport_write_table[0][address + 1](env, address + 1, (data >> 8) & 0xff); |
ioport_write_table[0][(address + 1) & (MAX_IOPORTS - 1)](env, address + 1, (data >> 8) & 0xff); |
247 |
} |
} |
248 |
|
|
249 |
uint32_t default_ioport_readl(CPUX86State *env, uint32_t address) |
uint32_t default_ioport_readl(CPUX86State *env, uint32_t address) |
535 |
{ |
{ |
536 |
struct tm *tm; |
struct tm *tm; |
537 |
time_t ti; |
time_t ti; |
538 |
|
int val; |
539 |
|
|
540 |
ti = time(NULL); |
ti = time(NULL); |
541 |
tm = gmtime(&ti); |
tm = gmtime(&ti); |
552 |
cmos_data[RTC_REG_C] = 0x00; |
cmos_data[RTC_REG_C] = 0x00; |
553 |
cmos_data[RTC_REG_D] = 0x80; |
cmos_data[RTC_REG_D] = 0x80; |
554 |
|
|
555 |
|
/* various important CMOS locations needed by PC/Bochs bios */ |
556 |
|
|
557 |
cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */ |
cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */ |
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 |
|
|
576 |
register_ioport_write(0x70, 2, cmos_ioport_write, 1); |
register_ioport_write(0x70, 2, cmos_ioport_write, 1); |
577 |
register_ioport_read(0x70, 2, cmos_ioport_read, 1); |
register_ioport_read(0x70, 2, cmos_ioport_read, 1); |
578 |
} |
} |
580 |
/***********************************************************/ |
/***********************************************************/ |
581 |
/* 8259 pic emulation */ |
/* 8259 pic emulation */ |
582 |
|
|
|
//#define DEBUG_PIC |
|
|
|
|
583 |
typedef struct PicState { |
typedef struct PicState { |
584 |
uint8_t last_irr; /* edge detection */ |
uint8_t last_irr; /* edge detection */ |
585 |
uint8_t irr; /* interrupt request register */ |
uint8_t irr; /* interrupt request register */ |
1397 |
/***********************************************************/ |
/***********************************************************/ |
1398 |
/* ne2000 emulation */ |
/* ne2000 emulation */ |
1399 |
|
|
|
//#define DEBUG_NE2000 |
|
|
|
|
1400 |
#define NE2000_IOPORT 0x300 |
#define NE2000_IOPORT 0x300 |
1401 |
#define NE2000_IRQ 9 |
#define NE2000_IRQ 9 |
1402 |
|
|
1862 |
/***********************************************************/ |
/***********************************************************/ |
1863 |
/* ide emulation */ |
/* ide emulation */ |
1864 |
|
|
|
//#define DEBUG_IDE |
|
|
|
|
1865 |
/* Bits of HD_STATUS */ |
/* Bits of HD_STATUS */ |
1866 |
#define ERR_STAT 0x01 |
#define ERR_STAT 0x01 |
1867 |
#define INDEX_STAT 0x02 |
#define INDEX_STAT 0x02 |
2385 |
int ret; |
int ret; |
2386 |
ret = s->status; |
ret = s->status; |
2387 |
#ifdef DEBUG_IDE |
#ifdef DEBUG_IDE |
2388 |
printf("ide: read addr=0x%x val=%02x\n", addr, ret); |
printf("ide: read status val=%02x\n", ret); |
2389 |
#endif |
#endif |
2390 |
return ret; |
return ret; |
2391 |
} |
} |
2392 |
|
|
2393 |
void ide_cmd_write(CPUX86State *env, uint32_t addr, uint32_t val) |
void ide_cmd_write(CPUX86State *env, uint32_t addr, uint32_t val) |
2394 |
{ |
{ |
2395 |
IDEState *s = &ide_state[0]; |
IDEState *s; |
2396 |
|
int i; |
2397 |
|
|
2398 |
|
#ifdef DEBUG_IDE |
2399 |
|
printf("ide: write control val=%02x\n", val); |
2400 |
|
#endif |
2401 |
/* common for both drives */ |
/* common for both drives */ |
2402 |
s->cmd = val; |
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; |
2432 |
} |
} |
2433 |
|
|
2434 |
void ide_data_writew(CPUX86State *env, uint32_t addr, uint32_t val) |
void ide_data_writew(CPUX86State *env, uint32_t addr, uint32_t val) |
2506 |
s->bs = bs_table[i]; |
s->bs = bs_table[i]; |
2507 |
if (s->bs) { |
if (s->bs) { |
2508 |
bdrv_get_geometry(s->bs, &nb_sectors); |
bdrv_get_geometry(s->bs, &nb_sectors); |
2509 |
cylinders = nb_sectors / (16 * 63); |
if (s->cylinders == 0) { |
2510 |
if (cylinders > 16383) |
/* if no geometry, use a LBA compatible one */ |
2511 |
cylinders = 16383; |
cylinders = nb_sectors / (16 * 63); |
2512 |
else if (cylinders < 2) |
if (cylinders > 16383) |
2513 |
cylinders = 2; |
cylinders = 16383; |
2514 |
s->cylinders = cylinders; |
else if (cylinders < 2) |
2515 |
s->heads = 16; |
cylinders = 2; |
2516 |
s->sectors = 63; |
s->cylinders = cylinders; |
2517 |
|
s->heads = 16; |
2518 |
|
s->sectors = 63; |
2519 |
|
} |
2520 |
s->nb_sectors = nb_sectors; |
s->nb_sectors = nb_sectors; |
2521 |
} |
} |
2522 |
s->irq = 14; |
s->irq = 14; |
2535 |
} |
} |
2536 |
|
|
2537 |
/***********************************************************/ |
/***********************************************************/ |
2538 |
/* simulate reset (stop qemu) */ |
/* 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 |
|
}; |
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; |
2630 |
int reset_requested; |
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 |
|
} |
2659 |
|
|
2660 |
uint32_t kbd_read_status(CPUX86State *env, uint32_t addr) |
uint32_t kbd_read_status(CPUX86State *env, uint32_t addr) |
2661 |
{ |
{ |
2662 |
return 0; |
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; |
2669 |
} |
} |
2670 |
|
|
2671 |
void kbd_write_command(CPUX86State *env, uint32_t addr, uint32_t val) |
void kbd_write_command(CPUX86State *env, uint32_t addr, uint32_t val) |
2672 |
{ |
{ |
2673 |
|
KBDState *s = &kbd_state; |
2674 |
|
|
2675 |
|
#ifdef DEBUG_KBD |
2676 |
|
printf("kbd: write cmd=0x%02x\n", val); |
2677 |
|
#endif |
2678 |
switch(val) { |
switch(val) { |
2679 |
case 0xfe: |
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: |
2730 |
reset_requested = 1; |
reset_requested = 1; |
2731 |
cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); |
cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); |
2732 |
break; |
break; |
2733 |
default: |
default: |
2734 |
|
fprintf(stderr, "vl: unsupported keyboard cmd=0x%02x\n", val); |
2735 |
break; |
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: |
2858 |
|
break; |
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 |
|
} |
2877 |
|
} |
2878 |
|
|
2879 |
void kbd_init(void) |
void kbd_init(void) |
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); |
2884 |
register_ioport_read(0x64, 1, kbd_read_status, 1); |
register_ioport_read(0x64, 1, kbd_read_status, 1); |
2885 |
register_ioport_write(0x64, 1, kbd_write_command, 1); |
register_ioport_write(0x64, 1, kbd_write_command, 1); |
2886 |
} |
} |
2887 |
|
|
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 |
|
/***********************************************************/ |
2934 |
/* cpu signal handler */ |
/* cpu signal handler */ |
2935 |
static void host_segv_handler(int host_signum, siginfo_t *info, |
static void host_segv_handler(int host_signum, siginfo_t *info, |
2936 |
void *puc) |
void *puc) |
3063 |
void help(void) |
void help(void) |
3064 |
{ |
{ |
3065 |
printf("Virtual Linux version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" |
printf("Virtual Linux version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" |
3066 |
"usage: vl [options] bzImage [kernel parameters...]\n" |
"usage: vl [options] [bzImage [kernel parameters...]]\n" |
3067 |
"\n" |
"\n" |
3068 |
"'bzImage' is a Linux kernel image (PAGE_OFFSET must be defined\n" |
"'bzImage' is a Linux kernel image (PAGE_OFFSET must be defined\n" |
3069 |
"to 0x90000000 in asm/page.h and arch/i386/vmlinux.lds)\n" |
"to 0x90000000 in asm/page.h and arch/i386/vmlinux.lds)\n" |
3076 |
"-m megs set virtual RAM size to megs MB\n" |
"-m megs set virtual RAM size to megs MB\n" |
3077 |
"-n script set network init script [default=%s]\n" |
"-n script set network init script [default=%s]\n" |
3078 |
"\n" |
"\n" |
3079 |
"Debug options:\n" |
"Debug/Expert options:\n" |
3080 |
"-s wait gdb connection to port %d\n" |
"-s wait gdb connection to port %d\n" |
3081 |
"-p port change gdb connection port\n" |
"-p port change gdb connection port\n" |
3082 |
"-d output log in /tmp/vl.log\n" |
"-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" |
3085 |
"\n" |
"\n" |
3086 |
"During emulation, use C-a h to get terminal commands:\n", |
"During emulation, use C-a h to get terminal commands:\n", |
3087 |
DEFAULT_NETWORK_SCRIPT, DEFAULT_GDBSTUB_PORT); |
DEFAULT_NETWORK_SCRIPT, DEFAULT_GDBSTUB_PORT); |
3094 |
{ "hda", 1, NULL, 0, }, |
{ "hda", 1, NULL, 0, }, |
3095 |
{ "hdb", 1, NULL, 0, }, |
{ "hdb", 1, NULL, 0, }, |
3096 |
{ "snapshot", 0, NULL, 0, }, |
{ "snapshot", 0, NULL, 0, }, |
3097 |
|
{ "hdachs", 1, NULL, 0, }, |
3098 |
{ NULL, 0, NULL, 0 }, |
{ NULL, 0, NULL, 0 }, |
3099 |
}; |
}; |
3100 |
|
|
3101 |
int main(int argc, char **argv) |
int main(int argc, char **argv) |
3102 |
{ |
{ |
3103 |
int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; |
int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; |
3104 |
int snapshot; |
int snapshot, linux_boot; |
3105 |
struct linux_params *params; |
struct linux_params *params; |
3106 |
struct sigaction act; |
struct sigaction act; |
3107 |
struct itimerval itv; |
struct itimerval itv; |
3119 |
use_gdbstub = 0; |
use_gdbstub = 0; |
3120 |
gdbstub_port = DEFAULT_GDBSTUB_PORT; |
gdbstub_port = DEFAULT_GDBSTUB_PORT; |
3121 |
snapshot = 0; |
snapshot = 0; |
3122 |
|
linux_boot = 0; |
3123 |
for(;;) { |
for(;;) { |
3124 |
c = getopt_long_only(argc, argv, "hm:dn:sp:", long_options, &long_index); |
c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index); |
3125 |
if (c == -1) |
if (c == -1) |
3126 |
break; |
break; |
3127 |
switch(c) { |
switch(c) { |
3139 |
case 3: |
case 3: |
3140 |
snapshot = 1; |
snapshot = 1; |
3141 |
break; |
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; |
3164 |
} |
} |
3165 |
break; |
break; |
3166 |
case 'h': |
case 'h': |
3188 |
case 'p': |
case 'p': |
3189 |
gdbstub_port = atoi(optarg); |
gdbstub_port = atoi(optarg); |
3190 |
break; |
break; |
3191 |
|
case 'L': |
3192 |
|
interp_prefix = optarg; |
3193 |
|
break; |
3194 |
} |
} |
3195 |
} |
} |
3196 |
if (optind >= argc) |
|
3197 |
|
linux_boot = (optind < argc); |
3198 |
|
|
3199 |
|
if (!linux_boot && hd_filename[0] == '\0') |
3200 |
help(); |
help(); |
3201 |
|
|
3202 |
/* init debug */ |
/* init debug */ |
3251 |
} |
} |
3252 |
} |
} |
3253 |
|
|
3254 |
/* now we can load the kernel */ |
/* init CPU state */ |
3255 |
ret = load_kernel(argv[optind], phys_ram_base + KERNEL_LOAD_ADDR); |
env = cpu_init(); |
3256 |
if (ret < 0) { |
global_env = env; |
3257 |
fprintf(stderr, "vl: could not load kernel '%s'\n", argv[optind]); |
cpu_single_env = env; |
3258 |
exit(1); |
|
3259 |
} |
init_ioports(); |
3260 |
|
|
3261 |
/* load initrd */ |
if (linux_boot) { |
3262 |
initrd_size = 0; |
/* now we can load the kernel */ |
3263 |
if (initrd_filename) { |
ret = load_kernel(argv[optind], phys_ram_base + KERNEL_LOAD_ADDR); |
3264 |
initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR); |
if (ret < 0) { |
3265 |
if (initrd_size < 0) { |
fprintf(stderr, "vl: could not load kernel '%s'\n", argv[optind]); |
|
fprintf(stderr, "vl: could not load initial ram disk '%s'\n", |
|
|
initrd_filename); |
|
3266 |
exit(1); |
exit(1); |
3267 |
} |
} |
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; |
3324 |
|
|
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 |
/* init kernel params */ |
env->eflags = 0x2; |
3362 |
params = (void *)(phys_ram_base + KERNEL_PARAMS_ADDR); |
|
3363 |
memset(params, 0, sizeof(struct linux_params)); |
bochs_bios_init(); |
|
params->mount_root_rdonly = 0; |
|
|
params->cl_magic = 0xA33F; |
|
|
params->cl_offset = params->commandline - (uint8_t *)params; |
|
|
params->alt_mem_k = (phys_ram_size / 1024) - 1024; |
|
|
for(i = optind + 1; i < argc; i++) { |
|
|
if (i != optind + 1) |
|
|
pstrcat(params->commandline, sizeof(params->commandline), " "); |
|
|
pstrcat(params->commandline, sizeof(params->commandline), argv[i]); |
|
|
} |
|
|
params->loader_type = 0x01; |
|
|
if (initrd_size > 0) { |
|
|
params->initrd_start = INITRD_LOAD_ADDR; |
|
|
params->initrd_size = initrd_size; |
|
3364 |
} |
} |
|
params->orig_video_lines = 25; |
|
|
params->orig_video_cols = 80; |
|
3365 |
|
|
3366 |
/* init basic PC hardware */ |
/* init basic PC hardware */ |
|
init_ioports(); |
|
3367 |
register_ioport_write(0x80, 1, ioport80_write, 1); |
register_ioport_write(0x80, 1, ioport80_write, 1); |
3368 |
|
|
3369 |
register_ioport_write(0x3d4, 2, vga_ioport_write, 1); |
register_ioport_write(0x3d4, 2, vga_ioport_write, 1); |
3386 |
act.sa_sigaction = host_alarm_handler; |
act.sa_sigaction = host_alarm_handler; |
3387 |
sigaction(SIGALRM, &act, NULL); |
sigaction(SIGALRM, &act, NULL); |
3388 |
|
|
|
/* init CPU state */ |
|
|
env = cpu_init(); |
|
|
global_env = env; |
|
|
cpu_single_env = env; |
|
|
|
|
|
/* setup basic memory access */ |
|
|
env->cr[0] = 0x00000033; |
|
|
cpu_x86_init_mmu(env); |
|
|
|
|
|
memset(params->idt_table, 0, sizeof(params->idt_table)); |
|
|
|
|
|
params->gdt_table[2] = 0x00cf9a000000ffffLL; /* KERNEL_CS */ |
|
|
params->gdt_table[3] = 0x00cf92000000ffffLL; /* KERNEL_DS */ |
|
|
|
|
|
env->idt.base = (void *)params->idt_table; |
|
|
env->idt.limit = sizeof(params->idt_table) - 1; |
|
|
env->gdt.base = (void *)params->gdt_table; |
|
|
env->gdt.limit = sizeof(params->gdt_table) - 1; |
|
|
|
|
|
cpu_x86_load_seg(env, R_CS, KERNEL_CS); |
|
|
cpu_x86_load_seg(env, R_DS, KERNEL_DS); |
|
|
cpu_x86_load_seg(env, R_ES, KERNEL_DS); |
|
|
cpu_x86_load_seg(env, R_SS, KERNEL_DS); |
|
|
cpu_x86_load_seg(env, R_FS, KERNEL_DS); |
|
|
cpu_x86_load_seg(env, R_GS, KERNEL_DS); |
|
|
|
|
|
env->eip = KERNEL_LOAD_ADDR; |
|
|
env->regs[R_ESI] = KERNEL_PARAMS_ADDR; |
|
|
env->eflags = 0x2; |
|
|
|
|
3389 |
itv.it_interval.tv_sec = 0; |
itv.it_interval.tv_sec = 0; |
3390 |
itv.it_interval.tv_usec = 1000; |
itv.it_interval.tv_usec = 1000; |
3391 |
itv.it_value.tv_sec = 0; |
itv.it_value.tv_sec = 0; |