Subversion Repositories SvarDOS

Rev

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

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