Subversion Repositories SvarDOS

Rev

Rev 448 | Rev 450 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 448 Rev 449
1
/* This file is part of the SvarCOM project and is published under the terms
1
/* This file is part of the SvarCOM project and is published under the terms
2
 * of the MIT license.
2
 * of the MIT license.
3
 *
3
 *
4
 * Copyright (C) 2021 Mateusz Viste
4
 * Copyright (C) 2021 Mateusz Viste
5
 *
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
12
 *
13
 * The above copyright notice and this permission notice shall be included in
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
14
 * all copies or substantial portions of the Software.
15
 *
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
22
 * DEALINGS IN THE SOFTWARE.
23
 */
23
 */
24
 
24
 
25
#include <i86.h>
25
#include <i86.h>
26
#include <string.h>
26
#include <string.h>
27
 
27
 
28
#include "env.h"
28
#include "env.h"
29
#include "helpers.h"
29
#include "helpers.h"
30
 
30
 
31
#include "rmod.h"
31
#include "rmod.h"
32
 
32
 
33
#include "rmodinit.h"
33
#include "rmodinit.h"
34
 
34
 
35
 
35
 
36
/* returns segment where rmod is installed */
36
/* returns far pointer to rmod's settings block on success */
37
unsigned short rmod_install(unsigned short envsize) {
37
struct rmod_props far *rmod_install(unsigned short envsize) {
38
  char far *myptr, far *mcb;
38
  char far *myptr, far *mcb;
39
  unsigned short far *owner;
39
  unsigned short far *owner;
-
 
40
  const unsigned short sizeof_rmodandprops_paras = rmod_len + sizeof(struct rmod_props) + 15 / 16;
40
  unsigned int rmodseg = 0xffff;
41
  unsigned int rmodseg = 0xffff;
41
  unsigned int envseg = 0;
42
  unsigned int envseg = 0;
-
 
43
  struct rmod_props far *res = NULL;
42
 
44
 
43
  /* read my current env segment from PSP */
45
  /* read my current env segment from PSP */
44
  _asm {
46
  _asm {
45
    push ax
47
    push ax
46
    push bx
48
    push bx
47
    mov bx, 0x2c
49
    mov bx, 0x2c
48
    mov ax, [bx]
50
    mov ax, [bx]
49
    mov envseg, ax
51
    mov envseg, ax
50
    pop bx
52
    pop bx
51
    pop ax
53
    pop ax
52
  }
54
  }
53
 
55
 
54
  /* printf("original (PSP) env buffer at %04X\r\n", envseg); */
56
  /* printf("original (PSP) env buffer at %04X\r\n", envseg); */
-
 
57
 
-
 
58
  /* if envseg is zero, then enforce our own one (MSDOS 5 does not provide a default env) */
-
 
59
  if ((envseg == 0) && (envsize == 0)) envsize = 256;
-
 
60
 
55
  /* if custom envsize requested, convert it to number of paragraphs */
61
  /* if custom envsize requested, convert it to number of paragraphs */
56
  if (envsize != 0) {
62
  if (envsize != 0) {
57
    envsize += 15;
63
    envsize += 15;
58
    envsize /= 16;
64
    envsize /= 16;
59
  }
65
  }
60
 
66
 
61
 
67
 
62
  _asm {
68
  _asm {
63
    /* link in the UMB memory chain for enabling high-memory allocation (and save initial status on stack) */
69
    /* link in the UMB memory chain for enabling high-memory allocation (and save initial status on stack) */
64
    mov ax, 0x5802  /* GET UMB LINK STATE */
70
    mov ax, 0x5802  /* GET UMB LINK STATE */
65
    int 0x21
71
    int 0x21
66
    xor ah, ah
72
    xor ah, ah
67
    push ax         /* save link state on stack */
73
    push ax         /* save link state on stack */
68
    mov ax, 0x5803  /* SET UMB LINK STATE */
74
    mov ax, 0x5803  /* SET UMB LINK STATE */
69
    mov bx, 1
75
    mov bx, 1
70
    int 0x21
76
    int 0x21
71
    /* get current allocation strategy and save it in DX */
77
    /* get current allocation strategy and save it in DX */
72
    mov ax, 0x5800
78
    mov ax, 0x5800
73
    int 0x21
79
    int 0x21
74
    push ax
80
    push ax
75
    pop dx
81
    pop dx
76
    /* set strategy to 'last fit, try high then low memory' */
82
    /* set strategy to 'last fit, try high then low memory' */
77
    mov ax, 0x5801
83
    mov ax, 0x5801
78
    mov bx, 0x0082
84
    mov bx, 0x0082
79
    int 0x21
85
    int 0x21
80
    /* ask for a memory block and save the given segment to rmodseg */
86
    /* ask for a memory block and save the given segment to rmodseg */
81
    mov ah, 0x48
87
    mov ah, 0x48
82
    mov bx, (rmod_len + 15) / 16
88
    mov bx, sizeof_rmodandprops_paras
83
    int 0x21
89
    int 0x21
84
    jc ALLOC_FAIL
90
    jc ALLOC_FAIL
85
    mov rmodseg, ax
91
    mov rmodseg, ax
86
    /* ask for a memory block for the environment and save it to envseg (only if custom size requested) */
92
    /* ask for a memory block for the environment and save it to envseg (only if custom size requested) */
87
    mov bx, envsize
93
    mov bx, envsize
88
    test bx, bx
94
    test bx, bx
89
    jz ALLOC_FAIL
95
    jz ALLOC_FAIL
90
    mov ah, 0x48
96
    mov ah, 0x48
91
    int 0x21
97
    int 0x21
92
    jc ALLOC_FAIL
98
    jc ALLOC_FAIL
93
    mov envseg, ax
99
    mov envseg, ax
94
 
100
 
95
    ALLOC_FAIL:
101
    ALLOC_FAIL:
96
    /* restore initial allocation strategy */
102
    /* restore initial allocation strategy */
97
    mov ax, 0x5801
103
    mov ax, 0x5801
98
    mov bx, dx
104
    mov bx, dx
99
    int 0x21
105
    int 0x21
100
    /* restore initial UMB memory link state */
106
    /* restore initial UMB memory link state */
101
    mov ax, 0x5803
107
    mov ax, 0x5803
102
    pop bx       /* pop initial UMB link state from stack */
108
    pop bx       /* pop initial UMB link state from stack */
103
    int 0x21
109
    int 0x21
104
  }
110
  }
105
 
111
 
106
  if (rmodseg == 0xffff) {
112
  if (rmodseg == 0xffff) {
107
    outputnl("malloc error");
113
    outputnl("malloc error");
108
    return(0xffff);
114
    return(NULL);
109
  }
115
  }
110
 
116
 
111
  /* copy rmod to its destination */
117
  /* copy rmod to its destination */
112
  myptr = MK_FP(rmodseg, 0);
118
  myptr = MK_FP(rmodseg, 0);
113
  _fmemcpy(myptr, rmod, rmod_len);
119
  _fmemcpy(myptr, rmod, rmod_len);
114
 
120
 
115
  /* mark rmod memory as "self owned" */
121
  /* mark rmod memory as "self owned" */
116
  mcb = MK_FP(rmodseg - 1, 0);
122
  mcb = MK_FP(rmodseg - 1, 0);
117
  owner = (void far *)(mcb + 1);
123
  owner = (void far *)(mcb + 1);
118
  *owner = rmodseg;
124
  *owner = rmodseg;
119
  _fmemcpy(mcb + 8, "SVARCOM", 8);
125
  _fmemcpy(mcb + 8, "SVARCOM", 8);
120
 
126
 
121
  /* mark env memory as "owned by rmod" */
127
  /* mark env memory as "owned by rmod" */
122
  mcb = MK_FP(envseg - 1, 0);
128
  mcb = MK_FP(envseg - 1, 0);
123
  owner = (void far *)(mcb + 1);
129
  owner = (void far *)(mcb + 1);
124
  *owner = rmodseg;
130
  *owner = rmodseg;
125
  _fmemcpy(mcb + 8, "SVARENV", 8);
131
  _fmemcpy(mcb + 8, "SVARENV", 8);
126
 
132
 
-
 
133
  /* if env block is newly allocated, fill it with a few NULLs */
-
 
134
  if (envsize != 0) {
-
 
135
    owner = MK_FP(envseg, 0);
-
 
136
    owner[0] = 0;
-
 
137
    owner[1] = 0;
-
 
138
  }
-
 
139
 
-
 
140
  /* prepare result (rmod props) */
-
 
141
  res = MK_FP(rmodseg, rmod_len);
-
 
142
  _fmemset(res, 0, sizeof(*res));
-
 
143
  res->rmodseg = rmodseg;
-
 
144
 
127
  /* write env segment to rmod buffer */
145
  /* write env segment to rmod buffer */
128
  owner = MK_FP(rmodseg, RMOD_OFFSET_ENVSEG);
146
  owner = MK_FP(rmodseg, RMOD_OFFSET_ENVSEG);
129
  *owner = envseg;
147
  *owner = envseg;
130
 
148
 
131
  /* write boot drive to rmod bootdrive field */
149
  /* write boot drive to rmod bootdrive field */
132
  _asm {
150
  _asm {
133
    push ax
151
    push ax
134
    push bx
152
    push bx
135
    push dx
153
    push dx
136
    push ds
154
    push ds
137
    mov ax, 0x3305 /* DOS 4.0+ - GET BOOT DRIVE */
155
    mov ax, 0x3305 /* DOS 4.0+ - GET BOOT DRIVE */
138
    int 0x21 /* boot drive is in DL now (1=A:, 2=B:, etc) */
156
    int 0x21 /* boot drive is in DL now (1=A:, 2=B:, etc) */
139
    add dl, 'A'-1 /* convert to a proper ASCII letter */
157
    add dl, 'A'-1 /* convert to a proper ASCII letter */
140
    /* set DS to rmodseg */
158
    /* set DS to rmodseg */
141
    mov ax, rmodseg
159
    mov ax, rmodseg
142
    mov ds, ax
160
    mov ds, ax
143
    /* write boot drive to rmod bootdrive field */
161
    /* write boot drive to rmod bootdrive field */
144
    mov bx, RMOD_OFFSET_BOOTDRIVE
162
    mov bx, RMOD_OFFSET_BOOTDRIVE
145
    mov [bx], dl
163
    mov [bx], dl
146
    pop ds
164
    pop ds
147
    pop dx
165
    pop dx
148
    pop bx
166
    pop bx
149
    pop ax
167
    pop ax
150
  }
168
  }
151
 
169
 
152
  /* set the int22 handler in my PSP to rmod so DOS jumps to rmod after I
170
  /* set the int22 handler in my PSP to rmod so DOS jumps to rmod after I
153
   * terminate and save the original handler in rmod's memory */
171
   * terminate and save the original handler in rmod's memory */
154
  _asm {
172
  _asm {
155
    push ax
173
    push ax
156
    push bx
174
    push bx
157
    push si
175
    push si
158
    push di
176
    push di
159
    push es
177
    push es
160
 
178
 
161
    /* save my original parent in rmod's memory */
179
    /* save my original parent in rmod's memory */
162
    mov es, [rmodseg]
180
    mov es, [rmodseg]
163
    mov si, 0x0a
181
    mov si, 0x0a
164
    mov di, RMOD_OFFSET_ORIGPARENT
182
    mov di, RMOD_OFFSET_ORIGPARENT
165
    cld
183
    cld
166
    movsw  /* mov ES:[DI], DS:[SI] and SI += 2 and DI += 2 */
184
    movsw  /* mov ES:[DI], DS:[SI] and SI += 2 and DI += 2 */
167
    movsw
185
    movsw
168
 
186
 
169
    mov bx, 0x0a                   /* int22 handler is at 0x0A of the PSP */
187
    mov bx, 0x0a                   /* int22 handler is at 0x0A of the PSP */
170
    mov ax, RMOD_OFFSET_ROUTINE
188
    mov ax, RMOD_OFFSET_ROUTINE
171
    mov [bx], ax                   /* int handler offset */
189
    mov [bx], ax                   /* int handler offset */
172
    mov ax, rmodseg
190
    mov ax, rmodseg
173
    mov [bx+2], ax                 /* int handler segment */
191
    mov [bx+2], ax                 /* int handler segment */
174
 
192
 
175
    pop es
193
    pop es
176
    pop di
194
    pop di
177
    pop si
195
    pop si
178
    pop bx
196
    pop bx
179
    pop ax
197
    pop ax
180
  }
198
  }
181
 
199
 
182
  return(rmodseg);
200
  return(res);
183
}
201
}
184
 
202
 
185
 
203
 
186
/* look up my parent: if it's rmod then return its segment,
204
/* look up my parent: if it's rmod then return a ptr to its props struct,
187
 * otherwise return 0xffff */
205
 * otherwise return NULL */
188
unsigned short rmod_find(void) {
206
struct rmod_props far *rmod_find(void) {
189
  unsigned short *parent = (void *)0x0C; /* parent's seg in PSP[Ch] ("prev. int22 handler") */
207
  unsigned short *parent = (void *)0x0C; /* parent's seg in PSP[Ch] ("prev. int22 handler") */
190
  unsigned short far *ptr;
208
  unsigned short far *ptr;
191
  const unsigned short sig[] = {0x1983, 0x1985, 0x2017, 0x2019};
209
  const unsigned short sig[] = {0x1983, 0x1985, 0x2017, 0x2019};
192
  unsigned char i;
210
  unsigned char i;
193
  /* is it rmod? */
211
  /* is it rmod? */
194
  ptr = MK_FP(*parent, 0);
212
  ptr = MK_FP(*parent, 0);
195
  for (i = 0; i < 4; i++) if (ptr[i] != sig[i]) return(0xffff);
213
  for (i = 0; i < 4; i++) if (ptr[i] != sig[i]) return(NULL);
196
  /* match successfull (rmod is my parent) */
214
  /* match successfull (rmod is my parent) */
197
  return(*parent);
215
  return(MK_FP(*parent, rmod_len));
198
}
216
}
199
 
217
 
200
 
218
 
201
/* update rmod's pointer to comspec */
219
/* update rmod's pointer to comspec */
202
void rmod_updatecomspecptr(unsigned short rmod_seg, unsigned short env_seg) {
220
void rmod_updatecomspecptr(unsigned short rmod_seg, unsigned short env_seg) {
203
  unsigned short far *comspecptr = MK_FP(rmod_seg, RMOD_OFFSET_COMSPECPTR);
221
  unsigned short far *comspecptr = MK_FP(rmod_seg, RMOD_OFFSET_COMSPECPTR);
204
  char far *comspecfp = env_lookup_val(env_seg, "COMSPEC");
222
  char far *comspecfp = env_lookup_val(env_seg, "COMSPEC");
205
  if (comspecfp != NULL) {
223
  if (comspecfp != NULL) {
206
    *comspecptr = FP_OFF(comspecfp);
224
    *comspecptr = FP_OFF(comspecfp);
207
  } else {
225
  } else {
208
    *comspecptr = 0;
226
    *comspecptr = 0;
209
  }
227
  }
210
}
228
}
211
 
229