Subversion Repositories SvarDOS

Rev

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

Rev 453 Rev 454
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 far pointer to rmod's settings block on success */
36
/* returns far pointer to rmod's settings block on success */
37
struct rmod_props far *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
  const unsigned short sizeof_rmodandprops_paras = rmod_len + sizeof(struct rmod_props) + 15 / 16;
41
  unsigned short rmodseg = 0xffff;
41
  unsigned short rmodseg = 0xffff;
42
  unsigned short envseg = 0, origenvseg = 0;
42
  unsigned short envseg, origenvseg;
43
  struct rmod_props far *res = NULL;
43
  struct rmod_props far *res = NULL;
44
 
44
 
45
  /* read my current env segment from PSP and save it */
45
  /* read my current env segment from PSP and save it */
46
  _asm {
-
 
47
    push ax
-
 
48
    push bx
-
 
49
    mov bx, 0x2c
46
  envseg = *((unsigned short *)0x2c);
50
    mov ax, [bx]
-
 
51
    mov envseg, ax
-
 
52
    mov origenvseg, ax
47
  origenvseg = envseg;
53
    pop bx
-
 
54
    pop ax
-
 
55
  }
-
 
56
 
48
 
57
  /* printf("original (PSP) env buffer at %04X\r\n", envseg); */
49
  /* printf("original (PSP) env buffer at %04X\r\n", envseg); */
58
 
50
 
59
  /* if envseg is zero, then enforce our own one (MSDOS 5 does not provide a default env) */
51
  /* if envseg is zero, then enforce our own one (MSDOS 5 does not provide a default env) */
60
  if ((envseg == 0) && (envsize == 0)) envsize = 256;
52
  if ((envseg == 0) && (envsize == 0)) envsize = 256;
61
 
53
 
62
  /* if custom envsize requested, convert it to number of paragraphs */
54
  /* if custom envsize requested, convert it to number of paragraphs */
63
  if (envsize != 0) {
55
  if (envsize != 0) {
64
    envsize += 15;
56
    envsize += 15;
65
    envsize /= 16;
57
    envsize /= 16;
66
  }
58
  }
67
 
59
 
68
 
-
 
69
  _asm {
60
  _asm {
70
    /* link in the UMB memory chain for enabling high-memory allocation (and save initial status on stack) */
61
    /* link in the UMB memory chain for enabling high-memory allocation (and save initial status on stack) */
71
    mov ax, 0x5802  /* GET UMB LINK STATE */
62
    mov ax, 0x5802  /* GET UMB LINK STATE */
72
    int 0x21
63
    int 0x21
73
    xor ah, ah
64
    xor ah, ah
74
    push ax         /* save link state on stack */
65
    push ax         /* save link state on stack */
75
    mov ax, 0x5803  /* SET UMB LINK STATE */
66
    mov ax, 0x5803  /* SET UMB LINK STATE */
76
    mov bx, 1
67
    mov bx, 1
77
    int 0x21
68
    int 0x21
78
    /* get current allocation strategy and save it in DX */
69
    /* get current allocation strategy and save it in DX */
79
    mov ax, 0x5800
70
    mov ax, 0x5800
80
    int 0x21
71
    int 0x21
81
    push ax
72
    push ax
82
    pop dx
73
    pop dx
83
    /* set strategy to 'last fit, try high then low memory' */
74
    /* set strategy to 'last fit, try high then low memory' */
84
    mov ax, 0x5801
75
    mov ax, 0x5801
85
    mov bx, 0x0082
76
    mov bx, 0x0082
86
    int 0x21
77
    int 0x21
87
    /* ask for a memory block and save the given segment to rmodseg */
78
    /* ask for a memory block and save the given segment to rmodseg */
88
    mov ah, 0x48
79
    mov ah, 0x48
89
    mov bx, sizeof_rmodandprops_paras
80
    mov bx, sizeof_rmodandprops_paras
90
    int 0x21
81
    int 0x21
91
    jc ALLOC_FAIL
82
    jc ALLOC_FAIL
92
    mov rmodseg, ax
83
    mov rmodseg, ax
93
    /* ask for a memory block for the environment and save it to envseg (only if custom size requested) */
84
    /* ask for a memory block for the environment and save it to envseg (only if custom size requested) */
94
    mov bx, envsize
85
    mov bx, envsize
95
    test bx, bx
86
    test bx, bx
96
    jz ALLOC_FAIL
87
    jz ALLOC_FAIL
97
    mov ah, 0x48
88
    mov ah, 0x48
98
    int 0x21
89
    int 0x21
99
    jc ALLOC_FAIL
90
    jc ALLOC_FAIL
100
    mov envseg, ax
91
    mov envseg, ax
101
 
92
 
102
    ALLOC_FAIL:
93
    ALLOC_FAIL:
103
    /* restore initial allocation strategy */
94
    /* restore initial allocation strategy */
104
    mov ax, 0x5801
95
    mov ax, 0x5801
105
    mov bx, dx
96
    mov bx, dx
106
    int 0x21
97
    int 0x21
107
    /* restore initial UMB memory link state */
98
    /* restore initial UMB memory link state */
108
    mov ax, 0x5803
99
    mov ax, 0x5803
109
    pop bx       /* pop initial UMB link state from stack */
100
    pop bx       /* pop initial UMB link state from stack */
110
    int 0x21
101
    int 0x21
111
  }
102
  }
112
 
103
 
113
  if (rmodseg == 0xffff) {
104
  if (rmodseg == 0xffff) {
114
    outputnl("malloc error");
105
    outputnl("malloc error");
115
    return(NULL);
106
    return(NULL);
116
  }
107
  }
117
 
108
 
118
  /* copy rmod to its destination */
109
  /* copy rmod to its destination */
119
  myptr = MK_FP(rmodseg, 0);
110
  myptr = MK_FP(rmodseg, 0);
120
  _fmemcpy(myptr, rmod, rmod_len);
111
  _fmemcpy(myptr, rmod, rmod_len);
121
 
112
 
122
  /* mark rmod memory as "self owned" */
113
  /* mark rmod memory as "self owned" */
123
  mcb = MK_FP(rmodseg - 1, 0);
114
  mcb = MK_FP(rmodseg - 1, 0);
124
  owner = (void far *)(mcb + 1);
115
  owner = (void far *)(mcb + 1);
125
  *owner = rmodseg;
116
  *owner = rmodseg;
126
  _fmemcpy(mcb + 8, "SVARCOM", 8);
117
  _fmemcpy(mcb + 8, "SVARCOM", 8);
127
 
118
 
128
  /* mark env memory as "owned by rmod" */
119
  /* mark env memory as "owned by rmod" */
129
  mcb = MK_FP(envseg - 1, 0);
120
  mcb = MK_FP(envseg - 1, 0);
130
  owner = (void far *)(mcb + 1);
121
  owner = (void far *)(mcb + 1);
131
  *owner = rmodseg;
122
  *owner = rmodseg;
132
  _fmemcpy(mcb + 8, "SVARENV", 8);
123
  _fmemcpy(mcb + 8, "SVARENV", 8);
133
 
124
 
134
  /* if env block is newly allocated, fill it with a few NULLs */
125
  /* if env block is newly allocated, fill it with a few NULLs */
135
  if (envsize != 0) {
126
  if (envsize != 0) {
136
    owner = MK_FP(envseg, 0);
127
    owner = MK_FP(envseg, 0);
137
    owner[0] = 0;
128
    owner[0] = 0;
138
    owner[1] = 0;
129
    owner[1] = 0;
139
  }
130
  }
140
 
131
 
141
  /* prepare result (rmod props) */
132
  /* prepare result (rmod props) */
142
  res = MK_FP(rmodseg, rmod_len);
133
  res = MK_FP(rmodseg, rmod_len);
143
  _fmemset(res, 0, sizeof(*res));  /* zero out */
134
  _fmemset(res, 0, sizeof(*res));  /* zero out */
144
  res->rmodseg = rmodseg;          /* rmod segment */
135
  res->rmodseg = rmodseg;          /* rmod segment */
145
  res->inputbuf[0] = 128;          /* input buffer for INT 0x21, AH=0Ah*/
136
  res->inputbuf[0] = 128;          /* input buffer for INT 0x21, AH=0Ah*/
146
  res->echoflag = 1;               /* ECHO ON */
137
  res->echoflag = 1;               /* ECHO ON */
147
  res->origenvseg = origenvseg;    /* original environment segment */
138
  res->origenvseg = origenvseg;    /* original environment segment */
148
 
139
 
149
  /* write env segment to rmod buffer */
140
  /* write env segment to rmod buffer */
150
  owner = MK_FP(rmodseg, RMOD_OFFSET_ENVSEG);
141
  owner = MK_FP(rmodseg, RMOD_OFFSET_ENVSEG);
151
  *owner = envseg;
142
  *owner = envseg;
152
 
143
 
153
  /* write boot drive to rmod bootdrive field */
144
  /* write boot drive to rmod bootdrive field */
154
  _asm {
145
  _asm {
155
    push ax
146
    push ax
156
    push bx
147
    push bx
157
    push dx
148
    push dx
158
    push ds
149
    push ds
159
    mov ax, 0x3305 /* DOS 4.0+ - GET BOOT DRIVE */
150
    mov ax, 0x3305 /* DOS 4.0+ - GET BOOT DRIVE */
160
    int 0x21 /* boot drive is in DL now (1=A:, 2=B:, etc) */
151
    int 0x21 /* boot drive is in DL now (1=A:, 2=B:, etc) */
161
    add dl, 'A'-1 /* convert to a proper ASCII letter */
152
    add dl, 'A'-1 /* convert to a proper ASCII letter */
162
    /* set DS to rmodseg */
153
    /* set DS to rmodseg */
163
    mov ax, rmodseg
154
    mov ax, rmodseg
164
    mov ds, ax
155
    mov ds, ax
165
    /* write boot drive to rmod bootdrive field */
156
    /* write boot drive to rmod bootdrive field */
166
    mov bx, RMOD_OFFSET_BOOTDRIVE
157
    mov bx, RMOD_OFFSET_BOOTDRIVE
167
    mov [bx], dl
158
    mov [bx], dl
168
    pop ds
159
    pop ds
169
    pop dx
160
    pop dx
170
    pop bx
161
    pop bx
171
    pop ax
162
    pop ax
172
  }
163
  }
173
 
164
 
174
  /* save my original parent in rmod's memory */
165
  /* save my original parent in rmod's memory */
175
  res->origparent = *((unsigned long *)0x0a); /* original parent seg:off is at 0x0a of my PSP */
166
  res->origparent = *((unsigned long *)0x0a); /* original parent seg:off is at 0x0a of my PSP */
176
 
167
 
177
  /* set the int22 handler in my PSP to rmod so DOS jumps to rmod after I
168
  /* set the int22 handler in my PSP to rmod so DOS jumps to rmod after I
178
   * terminate and save the original handler in rmod's memory */
169
   * terminate and save the original handler in rmod's memory */
179
  _asm {
170
  {
180
    push ax
-
 
181
    push bx
-
 
182
    push si
-
 
183
    push di
-
 
184
    push es
-
 
185
 
-
 
186
    mov bx, 0x0a                   /* int22 handler is at 0x0A of the PSP */
171
    unsigned short *ptr = (void *)0x0a; /* int22 handler is at 0x0A of the PSP */
187
    mov ax, RMOD_OFFSET_ROUTINE
172
    ptr[0] = RMOD_OFFSET_ROUTINE;
188
    mov [bx], ax                   /* int handler offset */
-
 
189
    mov ax, rmodseg
173
    ptr[1] = rmodseg;
190
    mov [bx+2], ax                 /* int handler segment */
-
 
191
 
-
 
192
    pop es
-
 
193
    pop di
-
 
194
    pop si
-
 
195
    pop bx
-
 
196
    pop ax
-
 
197
  }
174
  }
198
 
175
 
199
  return(res);
176
  return(res);
200
}
177
}
201
 
178
 
202
 
179
 
203
/* look up my parent: if it's rmod then return a ptr to its props struct,
180
/* look up my parent: if it's rmod then return a ptr to its props struct,
204
 * otherwise return NULL */
181
 * otherwise return NULL */
205
struct rmod_props far *rmod_find(void) {
182
struct rmod_props far *rmod_find(void) {
206
  unsigned short *parent = (void *)0x0C; /* parent's seg in PSP[Ch] ("prev. int22 handler") */
183
  unsigned short *parent = (void *)0x0C; /* parent's seg in PSP[Ch] ("prev. int22 handler") */
207
  unsigned short far *ptr;
184
  unsigned short far *ptr;
208
  const unsigned short sig[] = {0x1983, 0x1985, 0x2017, 0x2019};
185
  const unsigned short sig[] = {0x1983, 0x1985, 0x2017, 0x2019};
209
  unsigned char i;
186
  unsigned char i;
210
  /* is it rmod? */
187
  /* is it rmod? */
211
  ptr = MK_FP(*parent, 0);
188
  ptr = MK_FP(*parent, 0);
212
  for (i = 0; i < 4; i++) if (ptr[i] != sig[i]) return(NULL);
189
  for (i = 0; i < 4; i++) if (ptr[i] != sig[i]) return(NULL);
213
  /* match successfull (rmod is my parent) */
190
  /* match successfull (rmod is my parent) */
214
  return(MK_FP(*parent, rmod_len));
191
  return(MK_FP(*parent, rmod_len));
215
}
192
}
216
 
193
 
217
 
194
 
218
/* update rmod's pointer to comspec */
195
/* update rmod's pointer to comspec */
219
void rmod_updatecomspecptr(unsigned short rmod_seg, unsigned short env_seg) {
196
void rmod_updatecomspecptr(unsigned short rmod_seg, unsigned short env_seg) {
220
  unsigned short far *comspecptr = MK_FP(rmod_seg, RMOD_OFFSET_COMSPECPTR);
197
  unsigned short far *comspecptr = MK_FP(rmod_seg, RMOD_OFFSET_COMSPECPTR);
221
  char far *comspecfp = env_lookup_val(env_seg, "COMSPEC");
198
  char far *comspecfp = env_lookup_val(env_seg, "COMSPEC");
222
  if (comspecfp != NULL) {
199
  if (comspecfp != NULL) {
223
    *comspecptr = FP_OFF(comspecfp);
200
    *comspecptr = FP_OFF(comspecfp);
224
  } else {
201
  } else {
225
    *comspecptr = 0;
202
    *comspecptr = 0;
226
  }
203
  }
227
}
204
}
228
 
205