567 lines
11 KiB
NASM
567 lines
11 KiB
NASM
|
|
||
|
TITLE LDSELF - BootStrap procedure for KERNEL.EXE
|
||
|
|
||
|
.xlist
|
||
|
?NODATA=1
|
||
|
?TF=1
|
||
|
include kernel.inc
|
||
|
include newexe.inc
|
||
|
include tdb.inc
|
||
|
.list
|
||
|
|
||
|
externFP IGlobalAlloc
|
||
|
externFP IGlobalLock
|
||
|
externFP IGlobalUnlock
|
||
|
|
||
|
DataBegin
|
||
|
|
||
|
externW winVer
|
||
|
;externW pGlobalHeap
|
||
|
|
||
|
DataEnd
|
||
|
|
||
|
sBegin CODE
|
||
|
assumes CS,CODE
|
||
|
assumes DS,NOTHING
|
||
|
assumes ES,NOTHING
|
||
|
|
||
|
;externW MyCSDS
|
||
|
|
||
|
externNP SetOwner
|
||
|
|
||
|
externFP set_discarded_sel_owner
|
||
|
|
||
|
; extra debugging parameter for EntProcAddress to avoid RIPing if all
|
||
|
; we are doing is a GetProcAddress to something that isn't there.
|
||
|
externNP EntProcAddress
|
||
|
cProc FarEntProcAddress,<PUBLIC,FAR,NODATA>
|
||
|
parmW hExe
|
||
|
parmW entno
|
||
|
cBegin
|
||
|
if KDEBUG
|
||
|
mov cx,1
|
||
|
cCall EntProcAddress,<hExe,entno,cx>
|
||
|
else
|
||
|
cCall EntProcAddress,<hExe,entno>
|
||
|
endif
|
||
|
cEnd
|
||
|
|
||
|
if KDEBUG
|
||
|
|
||
|
; AppLoaderEntProcAddress
|
||
|
; This call added for the app loader. The above call (FarEntProcAddress)
|
||
|
; forces no RIPs. When we're using the app loader, we really want
|
||
|
; RIPs, so in debug we add this entry point.
|
||
|
; This call ONLY exists in debug.
|
||
|
|
||
|
cProc AppLoaderEntProcAddress,<PUBLIC,FAR,NODATA>
|
||
|
parmW hExe
|
||
|
parmW entno
|
||
|
cBegin
|
||
|
xor cx,cx ;Force RIPs on this one
|
||
|
cCall EntProcAddress,<hExe,entno,cx>
|
||
|
cEnd
|
||
|
|
||
|
endif ; KDEBUG
|
||
|
|
||
|
|
||
|
externNP FindOrdinal
|
||
|
cProc FarFindOrdinal,<PUBLIC,FAR,NODATA>
|
||
|
parmW hExe
|
||
|
parmD lpname
|
||
|
parmW fh
|
||
|
cBegin
|
||
|
cCall FindOrdinal,<hExe,lpName,fh>
|
||
|
cEnd
|
||
|
|
||
|
|
||
|
externNP LoadSegment
|
||
|
cProc FarLoadSegment,<PUBLIC,FAR,NODATA>
|
||
|
parmW hExe
|
||
|
parmW segno
|
||
|
parmW fh
|
||
|
parmW isfh
|
||
|
cBegin
|
||
|
cCall LoadSegment,<hExe,segno,fh,isfh>
|
||
|
cEnd
|
||
|
|
||
|
|
||
|
externNP AllocSeg
|
||
|
cProc FarAllocSeg,<PUBLIC,FAR,NODATA>
|
||
|
parmD pSegInfo
|
||
|
cBegin
|
||
|
cCall AllocSeg,<pSegInfo>
|
||
|
cEnd
|
||
|
|
||
|
|
||
|
externNP DeleteTask
|
||
|
cProc FarDeleteTask,<PUBLIC,FAR,NODATA,ATOMIC>
|
||
|
parmW taskID
|
||
|
cBegin
|
||
|
cCall DeleteTask,<taskID>
|
||
|
cEnd
|
||
|
|
||
|
|
||
|
externNP UnlinkObject
|
||
|
cProc FarUnlinkObject,<PUBLIC,FAR,NODATA,ATOMIC>
|
||
|
cBegin
|
||
|
cCall UnlinkObject
|
||
|
cEnd
|
||
|
|
||
|
|
||
|
externNP MyLower
|
||
|
cProc FarMyLower,<PUBLIC,FAR,NODATA,ATOMIC>
|
||
|
cBegin
|
||
|
cCall MyLower
|
||
|
cEnd
|
||
|
|
||
|
|
||
|
externNP MyUpper
|
||
|
cProc FarMyUpper,<PUBLIC,FAR,NODATA,ATOMIC>
|
||
|
cBegin
|
||
|
cCall MyUpper
|
||
|
cEnd
|
||
|
|
||
|
|
||
|
externNP MyAlloc
|
||
|
cProc FarMyAlloc,<PUBLIC,FAR,NODATA>
|
||
|
parmW aflags
|
||
|
parmW nsize
|
||
|
parmW nelem
|
||
|
cBegin
|
||
|
cCall MyAlloc,<aflags,nsize,nelem>
|
||
|
cEnd
|
||
|
|
||
|
|
||
|
externNP MyAllocLinear
|
||
|
cProc FarMyAllocLinear,<PUBLIC,FAR,NODATA>
|
||
|
parmW aflags
|
||
|
parmD dwBytes
|
||
|
cBegin
|
||
|
cCall MyAllocLinear,<aflags,dwBytes>
|
||
|
cEnd
|
||
|
|
||
|
|
||
|
externNP MyLock
|
||
|
cProc FarMyLock,<PUBLIC,FAR,NODATA>
|
||
|
parmW h1
|
||
|
cBegin
|
||
|
cCall MyLock,<h1>
|
||
|
cEnd
|
||
|
|
||
|
|
||
|
externNP MyFree
|
||
|
cProc FarMyFree,<PUBLIC,FAR,NODATA>
|
||
|
parmW h2
|
||
|
cBegin
|
||
|
cCall MyFree,<h2>
|
||
|
cEnd
|
||
|
|
||
|
externNP genter
|
||
|
cProc Far_genter,<PUBLIC,FAR,NODATA,ATOMIC>
|
||
|
cBegin
|
||
|
cCall genter
|
||
|
cEnd
|
||
|
|
||
|
externNP gleave
|
||
|
cProc Far_gleave,<PUBLIC,FAR,NODATA,ATOMIC>
|
||
|
cBegin
|
||
|
cCall gleave
|
||
|
cEnd
|
||
|
|
||
|
externNP lalign
|
||
|
cProc Far_lalign,<PUBLIC,FAR,NODATA,ATOMIC>
|
||
|
cBegin
|
||
|
cCall lalign
|
||
|
cEnd
|
||
|
|
||
|
|
||
|
externNP lrepsetup
|
||
|
cProc Far_lrepsetup,<PUBLIC,FAR,NODATA,ATOMIC>
|
||
|
cBegin
|
||
|
cCall lrepsetup
|
||
|
cEnd
|
||
|
|
||
|
|
||
|
if KDEBUG
|
||
|
|
||
|
externNP lfillCC
|
||
|
cProc Far_lfillCC,<PUBLIC,FAR,NODATA,ATOMIC>
|
||
|
cBegin
|
||
|
cCall lfillCC
|
||
|
cEnd
|
||
|
endif
|
||
|
|
||
|
sEnd CODE
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
sBegin INITCODE
|
||
|
|
||
|
;-----------------------------------------------------------------------;
|
||
|
; LKExeHeader ;
|
||
|
; ;
|
||
|
; Copy of LoadExeHeader (from LDHEADER.ASM) that has been stripped ;
|
||
|
; down to the minimum needed to load the new format .EXE header for ;
|
||
|
; KERNEL.EXE. ;
|
||
|
; ;
|
||
|
; Arguments: ;
|
||
|
; parmW pMem ;
|
||
|
; parmD pfilename ;
|
||
|
; ;
|
||
|
; Returns: ;
|
||
|
; AX = segment of exe header ;
|
||
|
; ;
|
||
|
; Error Returns: ;
|
||
|
; AX = 0 ;
|
||
|
; ;
|
||
|
; Registers Preserved: ;
|
||
|
; DI,SI,DS ;
|
||
|
; ;
|
||
|
; Registers Destroyed: ;
|
||
|
; AX,BX,CX,DX,ES ;
|
||
|
; Calls: ;
|
||
|
; ;
|
||
|
; History: ;
|
||
|
; ;
|
||
|
; Thu Mar 19, 1987 08:35:32p -by- David N. Weise [davidw] ;
|
||
|
; Added this nifty comment block. ;
|
||
|
;-----------------------------------------------------------------------;
|
||
|
|
||
|
cProc LKExeHeader,<PUBLIC,NEAR>,<si,di,ds>
|
||
|
parmW pMem
|
||
|
parmD pfilename
|
||
|
localW nchars
|
||
|
cBegin
|
||
|
lds si,pfilename
|
||
|
xor ax,ax
|
||
|
mov al,ds:[si].opLen
|
||
|
inc ax ; include null byte
|
||
|
mov nchars,ax
|
||
|
|
||
|
mov ds,pMem
|
||
|
xor si,si
|
||
|
mov di,ds:[si].ne_enttab ; Compute size of resident new header
|
||
|
add di, 6 ; Room for one block of entries
|
||
|
push si
|
||
|
mov si, ds:[si].ne_enttab ; Scan current entry table
|
||
|
|
||
|
calc_next_block:
|
||
|
lodsw
|
||
|
xor cx, cx
|
||
|
mov cl, al
|
||
|
jcxz calc_ent_sized
|
||
|
|
||
|
cmp ah, ENT_UNUSED ; 6 bytes per unused block
|
||
|
jne calc_used_block
|
||
|
add di, 6
|
||
|
jmps calc_next_block
|
||
|
|
||
|
calc_used_block:
|
||
|
errnz <5-SIZE PENT>
|
||
|
mov bx, cx
|
||
|
shl bx, 1
|
||
|
add di, bx
|
||
|
add di, bx ; 5 bytes per entry
|
||
|
add di, cx
|
||
|
|
||
|
add si, bx
|
||
|
add si, cx ; Skip the block
|
||
|
cmp ah, ENT_MOVEABLE
|
||
|
jne calc_next_block
|
||
|
|
||
|
calc_moveable_block:
|
||
|
add si, bx
|
||
|
add si, cx ; Skip the block
|
||
|
jmps calc_next_block
|
||
|
|
||
|
calc_ent_sized:
|
||
|
pop si
|
||
|
mov cx,ds:[si].ne_cseg ; + 3 * #segments
|
||
|
|
||
|
; Reserve space for segment reference bytes
|
||
|
|
||
|
add di,cx
|
||
|
shl cx,1
|
||
|
|
||
|
; Reserve space for ns_handle field in segment table
|
||
|
|
||
|
add di,cx
|
||
|
errnz <10-SIZE NEW_SEG1>
|
||
|
|
||
|
if LDCHKSUM
|
||
|
|
||
|
; Reserve space for segment chksum table (2 words per segment)
|
||
|
|
||
|
add di,cx
|
||
|
add di,cx
|
||
|
endif
|
||
|
|
||
|
|
||
|
; Reserve space for file info block at end
|
||
|
|
||
|
add di,16 ; 16 bytes of slop
|
||
|
add di,nchars ; + size of file info block
|
||
|
|
||
|
xor ax,ax ; Allocate a block for header
|
||
|
cCall IGlobalAlloc,<GA_MOVEABLE,ax,di>
|
||
|
push ax
|
||
|
cCall IGlobalLock,<ax>
|
||
|
pop ax
|
||
|
push dx
|
||
|
cCall IGlobalUnlock,<ax>
|
||
|
pop ax
|
||
|
mov es,ax ; ES:DI -> new header location
|
||
|
xor di,di
|
||
|
cld ; DS:SI -> old header
|
||
|
mov cx,SIZE NEW_EXE ; Copy fixed portion of header
|
||
|
cld
|
||
|
rep movsb
|
||
|
mov cx,es:[ne_cseg] ; Copy segment table
|
||
|
mov es:[ne_segtab],di
|
||
|
recopyseg:
|
||
|
|
||
|
if ROM
|
||
|
|
||
|
; This code assumes kernel segments will not need to be reloaded from ROM
|
||
|
; and so doesn't set the ns_sector field like LoadExeHeader().
|
||
|
|
||
|
lodsw ; ns_sector has segment selector in ROM
|
||
|
mov bx,ax
|
||
|
stosw
|
||
|
else
|
||
|
movsw ; ns_sector
|
||
|
endif
|
||
|
movsw ; ns_cbseg
|
||
|
lodsw ; ns_flags
|
||
|
errnz <4-ns_flags>
|
||
|
and ax,not NS286DOS ; Clear 286DOS bits
|
||
|
if ROM
|
||
|
or ax,NENOTP+4000h+NSINROM+NSLOADED ; library code in ROM
|
||
|
else
|
||
|
or ax,NENOTP+4000h ; Mark library code segments
|
||
|
endif
|
||
|
stosw
|
||
|
movsw ; ns_minalloc
|
||
|
errnz <8-SIZE NEW_SEG>
|
||
|
if ROM
|
||
|
mov ax,bx
|
||
|
else
|
||
|
xor ax,ax
|
||
|
endif
|
||
|
stosw ; one word for ns_handle field
|
||
|
errnz <10-SIZE NEW_SEG1>
|
||
|
loop recopyseg
|
||
|
|
||
|
recopysegx:
|
||
|
mov cx,es:[ne_restab] ; Copy resource table
|
||
|
sub cx,es:[ne_rsrctab]
|
||
|
mov es:[ne_rsrctab],di
|
||
|
rep movsb
|
||
|
rerestab:
|
||
|
mov cx,es:[ne_modtab] ; Copy resident name table
|
||
|
sub cx,es:[ne_restab]
|
||
|
mov es:[ne_restab],di
|
||
|
rep movsb
|
||
|
|
||
|
mov cx,es:[ne_imptab] ; Copy module xref table
|
||
|
sub cx,es:[ne_modtab]
|
||
|
mov es:[ne_modtab],di
|
||
|
rep movsb
|
||
|
|
||
|
mov es:[ne_psegrefbytes],di ; Insert segment reference byte table
|
||
|
mov cx,es:[ne_cseg]
|
||
|
mov al,0FFh
|
||
|
rep stosb ; initialize to not-loaded condition
|
||
|
|
||
|
mov es:[ne_pretthunks],di ; Setup return thunks
|
||
|
|
||
|
if LDCHKSUM
|
||
|
mov es:[ne_psegcsum],di ; Setup segment chksum table
|
||
|
mov cx,es:[ne_cseg]
|
||
|
jcxz resetsegcsumexit
|
||
|
xor ax,ax
|
||
|
shl cx,1 ; Two words per segment
|
||
|
rep stosw
|
||
|
resetsegcsumexit:
|
||
|
endif
|
||
|
mov cx,es:[ne_enttab] ; Copy imported name table
|
||
|
sub cx,es:[ne_imptab]
|
||
|
mov es:[ne_imptab],di
|
||
|
jcxz reenttab
|
||
|
rep movsb
|
||
|
|
||
|
reenttab:
|
||
|
mov es:[ne_enttab],di
|
||
|
; Scan current entry table
|
||
|
xor ax, ax ; First entry in block
|
||
|
mov bx, di ; Pointer to info for this block
|
||
|
stosw ; Starts at 0
|
||
|
stosw ; Ends at 0
|
||
|
stosw ; And is not even here!
|
||
|
|
||
|
copy_next_block:
|
||
|
lodsw ; Get # entries and type
|
||
|
xor cx, cx
|
||
|
mov cl, al
|
||
|
jcxz copy_ent_done
|
||
|
|
||
|
mov al, ah
|
||
|
cmp al, ENT_UNUSED
|
||
|
jne copy_used_block
|
||
|
|
||
|
mov ax, es:[bx].PM_EntEnd ; Last entry in current block
|
||
|
cmp ax, es:[bx].PM_EntStart ; No current block?
|
||
|
jne end_used_block
|
||
|
|
||
|
int 3
|
||
|
add es:[bx].PM_EntStart, cx
|
||
|
add es:[bx].PM_EntEnd, cx
|
||
|
jmps copy_next_block
|
||
|
|
||
|
end_used_block:
|
||
|
mov es:[bx].PM_EntNext, di ; Pointer to next block
|
||
|
mov bx, di
|
||
|
add ax, cx ; Skip unused entries
|
||
|
stosw ; First in new block
|
||
|
stosw ; Last in new block
|
||
|
xor ax, ax
|
||
|
stosw ; End of list
|
||
|
jmps copy_next_block
|
||
|
|
||
|
copy_used_block:
|
||
|
add es:[bx].PM_EntEnd, cx ; Add entries in this block
|
||
|
cmp al, ENT_MOVEABLE
|
||
|
je copy_moveable_block
|
||
|
|
||
|
copy_fixed_block:
|
||
|
stosb ; Segno
|
||
|
movsb ; Flag byte
|
||
|
stosb ; segno again to match structure
|
||
|
movsw ; Offset
|
||
|
loop copy_fixed_block
|
||
|
jmps copy_next_block
|
||
|
|
||
|
copy_moveable_block:
|
||
|
stosb ; ENT_MOVEABLE
|
||
|
movsb ; Flag byte
|
||
|
add si, 2 ; Toss int 3Fh
|
||
|
movsb ; Copy segment #
|
||
|
movsw ; and offset
|
||
|
loop copy_moveable_block
|
||
|
jmps copy_next_block
|
||
|
|
||
|
copy_ent_done:
|
||
|
|
||
|
|
||
|
xor bx,bx
|
||
|
mov es:[bx].ne_usage,1
|
||
|
mov es:[bx].ne_pnextexe,bx
|
||
|
mov es:[bx].ne_pautodata,bx
|
||
|
|
||
|
mov cx,nchars
|
||
|
mov es:[bx].ne_pfileinfo,di
|
||
|
lds si,pfilename
|
||
|
rep movsb
|
||
|
|
||
|
SetKernelDS
|
||
|
mov ax,winVer
|
||
|
mov es:[bx].ne_expver,ax
|
||
|
if ROM
|
||
|
or es:[bx].ne_flags,NENONRES OR NEMODINROM ;have disc code & in ROM
|
||
|
else
|
||
|
or es:[bx].ne_flags,NENONRES ; Remember that we have
|
||
|
; discardable code
|
||
|
endif
|
||
|
UnSetKernelDS
|
||
|
cCall SetOwner,<es,es>
|
||
|
mov ax,es
|
||
|
reexit:
|
||
|
cEnd
|
||
|
|
||
|
ife ROM ;----------------------------------------------------------------
|
||
|
|
||
|
cProc LKAllocSegs,<PUBLIC,NEAR>,<si,di,ds>
|
||
|
parmW hExe
|
||
|
|
||
|
localW fixed_seg
|
||
|
localW SegCount
|
||
|
cBegin
|
||
|
mov ds,hExe
|
||
|
mov si,ds:[ne_segtab]
|
||
|
mov di,ds:[si].ns_minalloc
|
||
|
xor ax,ax
|
||
|
mov bx,(GA_ALLOC_LOW or GA_CODE_DATA) shl 8
|
||
|
cCall IGlobalAlloc,<bx,ax,di>
|
||
|
or ax,ax
|
||
|
jz lkallocfail
|
||
|
mov fixed_seg,ax
|
||
|
mov ds:[si].ns_handle,ax
|
||
|
and byte ptr ds:[si].ns_flags,not NSLOADED
|
||
|
or byte ptr ds:[si].ns_flags,NSALLOCED
|
||
|
|
||
|
cCall SetOwner,<ax,ds>
|
||
|
|
||
|
add si,SIZE NEW_SEG1 ; NRES segment
|
||
|
mov di,ds:[si].ns_sector
|
||
|
mov SegCount, 0 ; NRES and MISC segments
|
||
|
|
||
|
;; SetKernelDS es
|
||
|
;; cmp fWinX,0
|
||
|
;; UnSetKernelDS es
|
||
|
;; je lk1
|
||
|
;; mov di,ds:[si].ns_cbseg
|
||
|
;; xchg ds:[si].ns_minalloc,di
|
||
|
;; xchg ds:[si].ns_sector,di
|
||
|
;;lk1:
|
||
|
|
||
|
SegLoop:
|
||
|
inc SegCount
|
||
|
xor ax,ax
|
||
|
mov bh,GA_DISCARDABLE + GA_SHAREABLE + GA_CODE_DATA
|
||
|
mov bl,GA_MOVEABLE + GA_DISCCODE
|
||
|
cCall IGlobalAlloc,<bx,ax,ax>
|
||
|
or ax,ax
|
||
|
jz lkallocfail
|
||
|
mov ds:[si].ns_handle,ax ; Handle into seg table
|
||
|
and byte ptr ds:[si].ns_flags,not NSLOADED
|
||
|
or byte ptr ds:[si].ns_flags,NSALLOCED
|
||
|
mov bx,ax ; put handle into base register
|
||
|
smov es,ds
|
||
|
call set_discarded_sel_owner
|
||
|
smov es,0
|
||
|
mov bx,ds:[si].ns_sector ; Save MiscCode sector
|
||
|
add si,SIZE NEW_SEG1 ; Next segment
|
||
|
cmp SegCount, 2
|
||
|
jnz SegLoop
|
||
|
|
||
|
|
||
|
; Allocate fixed block for kernel's data segment
|
||
|
|
||
|
push bx ; Save MisCode sector
|
||
|
mov bx,ds:[si].ns_minalloc
|
||
|
xor ax,ax
|
||
|
cCall IGlobalAlloc,<ax,ax,bx>
|
||
|
pop bx
|
||
|
or ax,ax
|
||
|
jz lkallocfail
|
||
|
mov ds:[ne_pautodata], si
|
||
|
mov ds:[si].ns_handle,ax
|
||
|
and byte ptr ds:[si].ns_flags,not NSLOADED
|
||
|
or byte ptr ds:[si].ns_flags,NSALLOCED
|
||
|
|
||
|
cCall SetOwner,<ax,ds>
|
||
|
|
||
|
mov ax,di ; Return offset to NR segment
|
||
|
lkallocfail:
|
||
|
cEnd
|
||
|
|
||
|
endif ;ROM ---------------------------------------------------------
|
||
|
|
||
|
nop ; Stop linker from padding segment
|
||
|
|
||
|
sEnd INITCODE
|
||
|
|
||
|
end
|