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
|
#include "monitor.h"
static unsigned memseg = 0, memlen = 0;
char buf[1];
/* If newseg == 0x0000 => Lowest address CS=$50
* If newseg == 0x0001 => DS to 64k position
* If newseg == 0x0002 => DS to 128k position
* ...
* If newseg == 0x0009 => DS to 576k position
* If newseg == 0xFFFF => Highest address leaving Linux-i386 clear.
*
* All others are literal, will fail if would overlap with something important.
*/
void
relocator(newseg)
unsigned newseg;
{
#ifdef __STANDALONE__
unsigned moved, codelen;
unsigned es = __get_es();
/* If running under DOS don't relocate */
if (__argr.x.cflag) return;
/* Where do we start */
if(memseg == 0)
{
extern int _heap_top;
memseg = __get_cs();
codelen = __get_ds()-memseg;
__set_es(memseg-2);
memlen = (((int)&_heap_top) >> 4);
/*
if (__deek_es(0) == 0x0301 ) memlen = (__deek_es(24) >> 4);
*/
if( memlen == 0 ) memlen = 0x1000;
memlen += codelen;
__set_es(es);
}
if( newseg == 0 ) newseg = 0x50;
if( newseg > 0 && newseg < 10 )
{
newseg = (newseg<<12) - (__get_ds() - __get_cs());
}
if( newseg < 0x50 ) return;
if( newseg == 0xFFFF )
{
newseg = boot_mem_top;
if( newseg > 0x9000 ) newseg = 0x9000;
newseg -= memlen;
}
/* If the old area overlaps the new then fail */
if( newseg >= memseg && newseg < memseg+memlen ) return;
if( memseg >= newseg && memseg < newseg+memlen ) return;
/* Copy segments, done in 32k chunks */
for(moved=0; moved < memlen; )
{
unsigned int lump;
if( memlen-moved <= 0x800 ) lump = memlen-moved; else lump = 0x800;
__movedata(memseg+moved, 0, newseg+moved, 0, (lump<<4));
moved += lump;
}
/* re-link int 0x80, this one is only an example (used by 'standalone.c') */
/* __set_es(0); __doke_es(0x80*4+2, newseg); __set_es(es); */
/* The actual jump ... */
memseg = newseg;
#asm
mov ax,ds
mov bx,cs
sub ax,bx
mov bx,[_memseg]
add ax,bx
push bx
call L_x
mov ds,ax
mov ss,ax
mov [_memseg],bx
#endasm
}
#asm
L_x:
retf
#endasm
#else
}
#endif
|