Subversion Repositories SvarDOS

Rev

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

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