summaryrefslogtreecommitdiff
path: root/i386/dos/i16/i16_dos_mem.c
blob: e78398dbdfe0c37e3ec728c20f552d623cf9f905 (plain)
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/* 
 * Copyright (c) 1995-1994 The University of Utah and
 * the Computer Systems Laboratory at the University of Utah (CSL).
 * All rights reserved.
 *
 * Permission to use, copy, modify and distribute this software is hereby
 * granted provided that (1) source code retains these copyright, permission,
 * and disclaimer notices, and (2) redistributions including binaries
 * reproduce the notices in supporting documentation, and (3) all advertising
 * materials mentioning features or use of this software display the following
 * acknowledgement: ``This product includes software developed by the
 * Computer Systems Laboratory at the University of Utah.''
 *
 * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
 * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * CSL requests users of this software to return to csl-dist@cs.utah.edu any
 * improvements that they make and grant CSL redistribution rights.
 *
 *      Author: Bryan Ford, University of Utah CSL
 */

#include <mach/machine/code16.h>
#include <mach/machine/vm_types.h>

#include "i16_dos.h"
#include "config.h"



/* These aren't static because vcpi and dpmi code need to grab DOS memory
   before we've switched to protected mode and memory has been collected.  */
vm_offset_t dos_mem_phys_free_mem;
vm_size_t dos_mem_phys_free_size;


CODE32

void dos_mem_collect(void)
{
	if (dos_mem_phys_free_mem)
	{
		phys_mem_add(dos_mem_phys_free_mem, dos_mem_phys_free_size);
		dos_mem_phys_free_mem = 0;
	}
}

CODE16

void i16_dos_mem_check()
{
	unsigned short paras = 0xf000;
	int dos_mem_seg;

	/* Allocate as big a chunk of memory as we can find.  */
	do
	{
		if (paras == 0)
			return;
		dos_mem_seg = i16_dos_alloc(&paras);
	}
	while (dos_mem_seg < 0);

	dos_mem_phys_free_mem = dos_mem_seg << 4;
	dos_mem_phys_free_size = paras << 4;

#ifdef ENABLE_CODE_CHECK
	i16_code_copy();
#endif
}


#ifdef ENABLE_CODE_CHECK

/* Big humongo kludge to help in finding random code-trashing bugs.
   We copy the entire text segment upon initialization,
   and then check it later as necessary.  */

#include <mach/machine/proc_reg.h>
#include "vm_param.h"

extern char etext[], i16_entry_2[];

static int code_copy_seg;

static int i16_code_copy()
{
	int text_size = (int)etext & ~0xf;
	int i;

	if (dos_mem_phys_free_size < text_size)
		return;

	code_copy_seg = dos_mem_phys_free_mem >> 4;
	dos_mem_phys_free_mem += text_size;
	dos_mem_phys_free_size -= text_size;

	set_fs(code_copy_seg);
	for (i = 0; i < text_size; i += 4)
		asm volatile("
			movl (%%ebx),%%eax
			movl %%eax,%%fs:(%%ebx)
		" : : "b" (i) : "eax");
}

void i16_code_check(int dummy)
{
	int text_size = (int)etext & ~0xf;
	int i, old, new;
	int found = 0;

	if (!code_copy_seg)
		return;

	set_fs(code_copy_seg);
	for (i = (int)i16_entry_2; i < text_size; i += 4)
	{
		asm volatile("
			movl (%%ebx),%%eax
			movl %%fs:(%%ebx),%%ecx
		" : "=a" (new), "=c" (old) : "b" (i));
		if (old != new)
		{
			found = 1;
			i16_writehexw(i);
			i16_putchar(' ');
			i16_writehexl(old);
			i16_putchar(' ');
			i16_writehexl(new);
			i16_putchar('\r');
			i16_putchar('\n');
		}
	}
	if (found)
	{
		code_copy_seg = 0;
		i16_writehexl((&dummy)[-1]);
		i16_die(" DOS extender code trashed!");
	}
}

CODE32

void code_check(int dummy)
{
	int text_size = (int)etext & ~0xf;
	unsigned char *new = 0, *old = (void*)phystokv(code_copy_seg*16);
	int found = 0;
	int i;

	if (!code_copy_seg)
		return;

	for (i = (int)i16_entry_2; (i < text_size) && (found < 10); i++)
	{
		/* In several places we have to self-modify an int instruction,
		   or the segment value in an absolute long jmp instruction,
		   so ignore any changes preceded by those opcodes.  */
		if ((new[i] != old[i])
		    && (old[i-1] != 0xcd)
		    && (old[i-6] != 0xea))
		{
			if (!found)
			{
				found = 1;
				about_to_die(1);
			}
			printf("%08x addr %04x was %02x now %02x\n",
				(&dummy)[-1], i, old[i], new[i]);
		}
	}
	if (found)
	{
		code_copy_seg = 0;
		die("%08x DOS extender code trashed!", (&dummy)[-1]);
	}
}

CODE16

#endif ENABLE_CODE_CHECK