summaryrefslogtreecommitdiffstats
path: root/private/mvdm/v86/scaffold/i386/fakeinit.c
blob: ae5d586dea5712c55ad55e4dc490f1f91f03a359 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//
// Fake Bios support initialization.
//
// This file provides interrim support for rom bios services initialization.
// It is only intended for use until Insignia produces proper rom support
// for NTVDM
//

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include "softpc.h"
#include "bop.h"
#include "xguest.h"
#include "xbios.h"
#include "xbiosdsk.h"
#include "fun.h"

#define SERVICE_LENGTH 4
static BYTE ServiceRoutine[] = { 0xC4 , 0xC4, BOP_UNIMPINT, 0xCF };

#define RESET_LENGTH 16
static BYTE ResetRoutine[] = { 0xEA, 0x00, 0x00, 0x00, 0xE0, // jmpf E000:0
                               BIOSDATE_MINE,
                               0, 0xFE, 0 };

static BYTE WarmBoot[] = {
    OPX_MOVAX,      BYTESOFFSET(0x30),
    OPX_MOV2SEG,    MODREGRM(MOD_REGISTER,REG_SS,REG_AX),
    OPX_MOVSP,      BYTESOFFSET(0x100),
    OPX_MOVAX,      0x00, 0x00,
    OPX_MOV2SEG,    MODREGRM(MOD_REGISTER,REG_DS,REG_AX),
    OPX_MOV2SEG,    MODREGRM(MOD_REGISTER,REG_ES,REG_AX),
    OPX_MOVDX,      DRIVE_FD0, 0x00,    // WARNING: sync with BIOSBOOT_DRIVE
    OPX_MOVCX,      0x01, 0x00,
    OPX_MOVBX,      BYTESOFFSET(BIOSDATA_BOOT),
    OPX_MOVAX,      0x01, DSKFUNC_READSECTORS,
    OPX_INT,        BIOSINT_DSK,
    OPX_JB,         -7,
    OPX_JMPF,       BYTESCOMPOSITE(0, BIOSDATA_BOOT)
};
#define WARMBOOT_LENGTH sizeof(WarmBoot)

static BYTE EquipmentRoutine[] = {   // INT 11h code
    OPX_PUSHDS,
    OPX_MOVAX,      0x00, 0x00,
    OPX_MOV2SEG,    MODREGRM(MOD_REGISTER,REG_DS,REG_AX),
    OPX_MOVAXOFF,   BYTESOFFSET(BIOSDATA_EQUIP_FLAG),
    OPX_POPDS,
    OPX_IRET
};
#define EQUIPMENT_LENGTH sizeof(EquipmentRoutine)

static BYTE MemoryRoutine[] = {      // INT 12h code
    OPX_PUSHDS,
    OPX_MOVAX,      0x00, 0x00,
    OPX_MOV2SEG,    MODREGRM(MOD_REGISTER,REG_DS,REG_AX),
    OPX_MOVAXOFF,   BYTESOFFSET(BIOSDATA_MEMORY_SIZE),
    OPX_POPDS,
    OPX_IRET
};
#define MEMORY_LENGTH sizeof(MemoryRoutine)


VOID BiosInit(int argc, char *argv[]) {

    PVOID Address, RomAddress;

    // set up IVT with unimplemented interrupt handler

    for (Address = NULL; Address < (PVOID)(0x1D * 4); (PCHAR)Address += 4) {
        *(PWORD)Address = 0x100;
        *(((PWORD)Address) + 1) = 0xF000;
    }

    RomAddress = (PVOID)(0xE000 << 4);

    // set up warm boot handler
    memcpy(RomAddress, WarmBoot, WARMBOOT_LENGTH);
    Address = RMSEGOFFTOLIN(0, BIOSINT_WBOOT * 4);
    *((PWORD)Address) = 0;
    *((PWORD)Address + 1) = 0xE000;
    (PCHAR)RomAddress += WARMBOOT_LENGTH;

    // set up equipment interrupt handler
    memcpy(RomAddress, EquipmentRoutine, EQUIPMENT_LENGTH);
    Address = RMSEGOFFTOLIN(0, BIOSINT_EQUIP * 4);
    *((PWORD)Address) = RMOFF(RomAddress);
    *((PWORD)Address + 1) = RMSEG(RomAddress);
    (PCHAR)RomAddress += EQUIPMENT_LENGTH;

    // set up memory size interrupt handler
    memcpy(RomAddress, MemoryRoutine, MEMORY_LENGTH);
    Address = RMSEGOFFTOLIN(0, BIOSINT_MEMORY * 4);
    *((PWORD)Address) = RMOFF(RomAddress);
    *((PWORD)Address + 1) = RMSEG(RomAddress);
 
    RomAddress = (PVOID)((0xF000 << 4) + 0x100);

    Address = (PBYTE)RomAddress + 0xFE53;
    *(PCHAR)Address = 0xCF;         // IRET at f000:ff53

    // set up unimplemented interrupt handler

    memcpy(RomAddress, ServiceRoutine, SERVICE_LENGTH);
    (PCHAR)RomAddress += SERVICE_LENGTH;

    // set up reset code
    memcpy(RMSEGOFFTOLIN(BIOSROM_SEG, BIOSROM_RESET), ResetRoutine, RESET_LENGTH);

    // set up equipment byte and memory size

    *(PWORD)RMSEGOFFTOLIN(BIOSDATA_SEG, BIOSDATA_EQUIP_FLAG) = 
        BIOSEQUIP_32KPLANAR;
    *(PWORD)RMSEGOFFTOLIN(BIOSDATA_SEG, BIOSDATA_MEMORY_SIZE) = 
        640;
    
    // Initialize individual rom modules

    BiosKbdInit(argc, argv, &RomAddress);
    BiosVidInit(argc, argv, &RomAddress);
}