|
|
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:
movsw ; ns_sector movsw ; ns_cbseg lodsw ; ns_flags errnz <4-ns_flags> and ax,not NS286DOS ; Clear 286DOS bits or ax,NENOTP+4000h ; Mark library code segments stosw movsw ; ns_minalloc errnz <8-SIZE NEW_SEG> xor ax,ax 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 or es:[bx].ne_flags,NENONRES ; Remember that we have ; discardable code UnSetKernelDS cCall SetOwner,<es,es> mov ax,es reexit: cEnd
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
nop ; Stop linker from padding segment
sEnd INITCODE
end
|