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
183
184
185
186
187
188
189
190
191
192
|
(*
# $Id: nwpre.as,v 1.3 2003/03/25 18:17:54 armin Exp $
# This file is part of the Free Pascal run time library.
# Copyright (c) 1999-2011 by the Free Pascal development team
# Copyright (c) 2002-2011 Armin Diehl
#
# This is the (nwpre-like) startup code for netware (clib)
#
# See the file COPYING.FPC, included in this distribution,
# for details about the copyright.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
#**********************************************************************
# This version initializes BSS
#
# Imported functions will not be known by the linker because only the
# generated object file will be included into the link process. The
# ppu will not be read. Therefore the file nwpre.imp containing the
# names of all imported functions needs to be created. This file
# will be used by the internal linker to import the needed functions.
#**********************************************************************
*)
unit nwpre;
interface
implementation
procedure _SetupArgV_411 (startProc:pointer); cdecl; external 'clib' name '_SetupArgV_411';
procedure _nlm_main; external name '_nlm_main';
procedure FPC_NW_CHECKFUNCTION; external name 'FPC_NW_CHECKFUNCTION';
function _StartNLM (NLMHandle : longint;
initErrorScreenID : longint;
cmdLineP : pchar;
loadDirectoryPath : pchar;
uninitializedDataLength : longint;
NLMFileHandle : longint;
readRoutineP : pointer;
customDataOffset : longint;
customDataSize : longint;
NLMInformation : pointer;
userStartFunc : pointer) : longint; cdecl; external '!clib' name '_StartNLM';
function _TerminateNLM (NLMInformation : pointer;
threadID, status : longint) : longint; cdecl; external '!clib' name '_TerminateNLM';
procedure _Stop; cdecl; forward;
// This is the main program (not loader) Entry-Point that will be called by netware
// it sets up the argc and argv and calls _nlm_main (in system.pp)
procedure _pasStart; assembler; export; [alias:'_pasStart_'];
asm
pushl $_nlm_main
call _SetupArgV_411
addl $4,%esp
ret
// this is a hack to avoid that FPC_NW_CHECKFUNCTION will be
// eleminated by the linker (with smartlinking)
// TODO: change the internal linker to allow check and stop
call FPC_NW_CHECKFUNCTION
call _Stop
end;
// structure needed by clib
type kNLMInfoT =
packed record
Signature : array [0..3] of char; // LONG 'NLMI'
Flavor : longint; // TRADINIONAL_FLAVOR = 0
Version : longint; // TRADINIONAL_VERSION = 0, LIBERTY_VERSION = 1
LongDoubleSize : longint; // gcc nwpre defines 12, watcom 8
wchar_tSize : longint;
end;
var
_kNLMInfo:kNLMInfoT = (Signature:'NLMI';Flavor:0;Version:1;LongDoubleSize:8;wChar_tSize:2);
// symbol is generated by the internal linker, when using ld in the future again,
// the link script for ld needs to be modified to include this symbol
bss : ptruint; external name '__bss_start__';
// fillchar
// netware kernel function
procedure CSetB(value:byte; var addr; count:longint); cdecl; external '!' name 'CSetB';
// this will be called by the loader, we pass the address of _pasStart_ and
// _kNLMInfo (needed by clib) and clib will call _pasStart within a newly
// created thread
function _Prelude (NLMHandle : longint;
initErrorScreenID : longint;
cmdLineP : pchar;
loadDirectoryPath : pchar;
uninitializedDataLength : longint;
NLMFileHandle : longint;
readRoutineP : pointer;
customDataOffset : longint;
customDataSize : longint) : longint; cdecl; export; [alias:'_Prelude'];
begin
// initialize BSS
CSetB(0,bss,uninitializedDataLength);
// let clib setup a thread and call pasStart in this new thread
_Prelude := _StartNLM (NLMHandle,
initErrorScreenID,
cmdLineP,
loadDirectoryPath,
uninitializedDataLength,
NLMFileHandle,
readRoutineP,
customDataOffset,
customDataSize,
@_kNLMInfo,
@_pasStart);
end;
(*
procedure _Prelude; assembler; export; [alias:'_Prelude'];
asm
pushl %ebp
movl %esp,%ebp
pushl %edi
pushl %esi
pushl %ebx
movl 0x14(%ebp),%edi
movl 0x18(%ebp),%esi
movl %esi, __uninitializedDataSize
movl 0x1c(%ebp),%ebx
movl 0x20(%ebp),%ecx
movl 0x28(%ebp),%eax
pushl $_pasStart
pushl $_kNLMInfo
pushl %eax
movl 0x24(%ebp),%edx // 1b7f6
pushl %edx
pushl %ecx
pushl %ebx
pushl %esi // uninitialized data size
pushl %edi
movl 0x10(%ebp),%edx
pushl %edx
movl 0xc(%ebp),%edx
pushl %edx
movl 0x8(%ebp),%edx
pushl %edx
call _StartNLM
test %eax,%eax
jne .Lx1
xorl %eax,%eax // dont know why this is needed ?
.Lx1:
lea 0xfffffff4(%ebp),%esp
popl %ebx
popl %esi
popl %edi
movl %ebp,%esp
popl %ebp
ret
end;
*)
//# the global stop-function
// fpc will generate an (unneeded) stack frame here, gcc does not
(*
procedure _Stop; cdecl; export; [alias:'_Stop'];
begin
_TerminateNLM (@_kNLMInfo,0,5);
end;
*)
procedure _Stop; cdecl; assembler; [alias:'_Stop'];
asm
pushl $0x5
pushl $0x0
movl _kNLMInfo,%edx
pushl %edx
call _TerminateNLM
addl $0x0c,%esp
ret
end;
end.
|