|
@@ -4,8 +4,8 @@
|
|
|
# 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
|
|
|
-#
|
|
|
+# This is the (nwpre-like) startup code for netware (clib)
|
|
|
+#
|
|
|
# See the file COPYING.FPC, included in this distribution,
|
|
|
# for details about the copyright.
|
|
|
#
|
|
@@ -14,6 +14,14 @@
|
|
|
# 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;
|
|
@@ -22,15 +30,10 @@ interface
|
|
|
|
|
|
implementation
|
|
|
|
|
|
-// .file "nwpre.as"
|
|
|
-// .text
|
|
|
-
|
|
|
|
|
|
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';
|
|
|
-//procedure _StartNLM; external name '_StartNLM';
|
|
|
-
|
|
|
function _StartNLM (NLMHandle : longint;
|
|
|
initErrorScreenID : longint;
|
|
|
cmdLineP : pchar;
|
|
@@ -44,13 +47,14 @@ function _StartNLM (NLMHandle : longint;
|
|
|
userStartFunc : pointer) : longint; cdecl; external '!clib' name '_StartNLM';
|
|
|
|
|
|
|
|
|
-procedure _TerminateNLM; cdecl; external '!clib' name '_TerminateNLM';
|
|
|
+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 _Stop; forward;
|
|
|
|
|
|
procedure _pasStart; assembler; export; [alias:'_pasStart_'];
|
|
|
asm
|
|
@@ -60,39 +64,67 @@ asm
|
|
|
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;
|
|
|
|
|
|
-//.data
|
|
|
-//# argc is defined in the novell nwpre, i assume it is not needed
|
|
|
-//#_argc:
|
|
|
-//# .long 0
|
|
|
|
|
|
// 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
|
|
|
+ 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;
|
|
|
-// .globl _kNLMInfo # will be used as data start
|
|
|
-var _kNLMInfo:kNLMInfoT = (Signature:'NLMI';Flavor:0;Version:1;LongDoubleSize:8;wChar_tSize:2);
|
|
|
-// .ascii "NLMI"
|
|
|
-// .long 0,1,8,2
|
|
|
-//
|
|
|
|
|
|
-//.data
|
|
|
-// __uninitializedDataSize: .long
|
|
|
-var __uninitializedDataSize:longint;
|
|
|
+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 netware is doing the work
|
|
|
-//
|
|
|
-// .globl _Prelude
|
|
|
+// _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
|
|
@@ -134,58 +166,27 @@ asm
|
|
|
popl %ebp
|
|
|
ret
|
|
|
end;
|
|
|
+*)
|
|
|
|
|
|
-//#
|
|
|
//# the global stop-function
|
|
|
-//#
|
|
|
-// .globl _Stop
|
|
|
-procedure _Stop; assembler; [alias:'_Stop'];
|
|
|
-asm
|
|
|
- pushl $0x5 // TERMINATE_BY_UNLOAD=0, TERMINATE_BY_EXTERNAL_THREAD=0
|
|
|
- pushl $0x0
|
|
|
- movl _kNLMInfo,%edx
|
|
|
- pushl %edx
|
|
|
- call _TerminateNLM
|
|
|
- addl $0x0c,%esp
|
|
|
- ret
|
|
|
-end;
|
|
|
-
|
|
|
-
|
|
|
-//.text
|
|
|
-procedure __getTextStart; assembler; export; [alias:'__getTextStart'];
|
|
|
-asm
|
|
|
-//__getTextStart:
|
|
|
-// movl $.text,%eax
|
|
|
- movl $_pasStart,%eax // should be the start in .text, dont know how to access .text in the internal assembler
|
|
|
- ret
|
|
|
-end;
|
|
|
-
|
|
|
-procedure _DataStart; external name '.data';
|
|
|
-
|
|
|
-procedure __getDataStart; assembler; export; [alias:'_getDataStart'];
|
|
|
-asm
|
|
|
-//__getDataStart:
|
|
|
-// movl $.data,%eax
|
|
|
- movl $_kNLMInfo, %eax
|
|
|
- ret
|
|
|
-end;
|
|
|
|
|
|
-
|
|
|
-procedure __getBssStart; assembler; export; [alias:'__getBssStart'];
|
|
|
-asm
|
|
|
-//__getBssStart:
|
|
|
-// movl $.bss,%eax
|
|
|
- movl $__uninitializedDataSize,%eax
|
|
|
- ret
|
|
|
+// fpc will generate an (unneeded) stack frame here, gcc does not
|
|
|
+(*
|
|
|
+procedure _Stop; cdecl; export; [alias:'_Stop'];
|
|
|
+begin
|
|
|
+ _TerminateNLM (@_kNLMInfo,0,5);
|
|
|
end;
|
|
|
+*)
|
|
|
|
|
|
-//.text
|
|
|
-procedure __getUninitializedDataSize; assembler; export; [alias:'__getUninitializedDataSize'];
|
|
|
+procedure _Stop; cdecl; assembler; [alias:'_Stop'];
|
|
|
asm
|
|
|
-//__getUninitializedDataSize:
|
|
|
- movl __uninitializedDataSize, %eax
|
|
|
- ret
|
|
|
+ pushl $0x5
|
|
|
+ pushl $0x0
|
|
|
+ movl _kNLMInfo,%edx
|
|
|
+ pushl %edx
|
|
|
+ call _TerminateNLM
|
|
|
+ addl $0x0c,%esp
|
|
|
+ ret
|
|
|
end;
|
|
|
|
|
|
-
|
|
|
end.
|