Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3148 lines
73 KiB

  1. PAGE ,132
  2. TITLE LDBOOT - BootStrap procedure
  3. ?DFSTACK = 1
  4. .xlist
  5. include kernel.inc
  6. include newexe.inc
  7. include tdb.inc
  8. include pdb.inc
  9. include protect.inc
  10. include gpcont.inc
  11. ifdef WOW
  12. include vint.inc
  13. include doswow.inc
  14. endif
  15. .list
  16. if 0; KDEBUG
  17. ifdef WOW
  18. BootTraceOn = 1
  19. BootTrace macro char
  20. push ax
  21. mov ax,char
  22. int 3
  23. pop ax
  24. endm
  25. else
  26. BootTraceOn = 1
  27. BootTrace macro char
  28. push char
  29. call BootTraceChar
  30. endm
  31. endif
  32. else
  33. BootTrace macro char
  34. endm
  35. BootTraceOn = 0
  36. endif
  37. ; Note that the following public constants require special handling
  38. ; for ROM Windows. If you add, delete, or change this list of constants,
  39. ; you must also check the ROM Image Builder.
  40. public __ahshift
  41. public __ahincr
  42. public __0000h
  43. public __0040h
  44. public __A000h
  45. public __B000h
  46. public __B800h
  47. public __C000h
  48. public __D000h
  49. public __E000h
  50. public __F000h
  51. public __ROMBIOS
  52. public __WinFlags
  53. public __flatcs
  54. public __flatds
  55. public __MOD_KERNEL
  56. public __MOD_DKERNEL
  57. public __MOD_USER
  58. public __MOD_DUSER
  59. public __MOD_GDI
  60. public __MOD_DGDI
  61. public __MOD_KEYBOARD
  62. public __MOD_SOUND
  63. public __MOD_SHELL
  64. public __MOD_WINSOCK
  65. public __MOD_TOOLHELP
  66. public __MOD_MMEDIA
  67. public __MOD_COMMDLG
  68. ifdef FE_SB
  69. public __MOD_WINNLS
  70. public __MOD_WIFEMAN
  71. endif ; FE_SB
  72. __ahshift = 3
  73. __ahincr = 1 shl __ahshift
  74. __0000h = 00000h
  75. __0040h = 00040h
  76. __A000h = 0A000h
  77. __B000h = 0B000h
  78. __B800h = 0B800h
  79. __C000h = 0C000h
  80. __D000h = 0D000h
  81. __E000h = 0E000h
  82. __F000h = 0F000h
  83. __ROMBIOS = 0F000h
  84. __WinFlags = 1
  85. __flatcs = 1Bh
  86. __flatds = 23h
  87. __MOD_KERNEL = 0h
  88. __MOD_DKERNEL = 0h
  89. __MOD_USER = 0h
  90. __MOD_DUSER = 0h
  91. __MOD_GDI = 0h
  92. __MOD_DGDI = 0h
  93. __MOD_KEYBOARD = 0h
  94. __MOD_SOUND = 0h
  95. __MOD_SHELL = 0h
  96. __MOD_WINSOCK = 0h
  97. __MOD_TOOLHELP = 0h
  98. __MOD_MMEDIA = 0h
  99. __MOD_COMMDLG = 0h
  100. ifdef FE_SB
  101. __MOD_WINNLS = 0h ; for IME
  102. __MOD_WIFEMAN = 0h ; for WIFEMAN
  103. endif ; FE_SB
  104. BOOTSTACKSIZE = 512
  105. EXTRASTACKSIZE = (4096-BOOTSTACKSIZE)
  106. MultWIN386 EQU 16h ; Reserved to Win386
  107. MW3_ReqInstall EQU 00h ; Installation check
  108. MW3_ReqInstall_Ret_1 EQU 0FFh ; Return number 1
  109. MW3_ReqInstall_Ret_2 EQU 01h ; Return number 2
  110. MW3_ReqInstall_Ret_3 EQU 02h ; Return number 3
  111. MW3_ReqInstall_Ret_4 EQU 03h ; Return number 4
  112. DOS_FLAG_OFFSET EQU 086h
  113. externFP lstrlen
  114. externFP lstrcat
  115. externFP lstrcpy
  116. externFP IGlobalAlloc
  117. externFP IGlobalFree
  118. externFP IGlobalRealloc
  119. externFP LoadModule
  120. externFP IOpenFile
  121. externFP lrusweep
  122. externFP GetExePtr
  123. externFP GetProfileInt
  124. externFP GetPrivateProfileString
  125. externFP GetPrivateProfileInt
  126. externFP GetProcAddress
  127. externFP GetTempDrive
  128. externFP ExitKernel
  129. externFP InternalEnableDOS
  130. externFP FlushCachedFileHandle
  131. externFP SetHandleCount
  132. externFP IPrestoChangoSelector
  133. externFP GPFault
  134. externFP StackFault
  135. externFP invalid_op_code_exception
  136. externFP page_fault
  137. ifdef WOW
  138. externFP divide_overflow
  139. externFP single_step
  140. externFP breakpoint
  141. endif
  142. externFP DiagInit
  143. ifdef WOW
  144. externFP StartWOWTask
  145. externFP AllocSelector_0x47
  146. externW MOD_KERNEL
  147. externW ModCount
  148. externFP WOWGetTableOffsets
  149. externFP WOWDosWowInit
  150. externFP GetShortPathName
  151. endif
  152. if KDEBUG
  153. externFP ValidateCodeSegments
  154. endif
  155. ifdef FE_SB
  156. externFP GetSystemDefaultLangID
  157. endif
  158. externFP TermsrvGetWindowsDir
  159. externW pStackBot
  160. externW pStackMin
  161. externW pStackTop
  162. sBegin CODE
  163. externFP Int21Handler
  164. externFP Int10Handler
  165. externD prevInt10proc
  166. sEnd CODE
  167. ;------------------------------------------------------------------------
  168. ; Data Segment Variables
  169. ;------------------------------------------------------------------------
  170. DataBegin
  171. if SHERLOCK
  172. externW gpEnable
  173. endif
  174. externB graphics
  175. externB fBooting
  176. externB Kernel_flags
  177. externB fChkSum
  178. externB fCheckFree
  179. externB WOAName
  180. externB grab_name
  181. ifndef WOW
  182. externB szUserPro
  183. endif
  184. externB szBootLoad
  185. externB szCRLF
  186. externB szMissingMod
  187. externB szPleaseDoIt
  188. externB fPadCode
  189. ;externW EMScurPID
  190. ;externW PID_for_fake
  191. externW cBytesWinDir
  192. externW cBytesSysDir
  193. externW pGlobalHeap
  194. externW hExeHead
  195. externW MaxCodeSwapArea
  196. externW curTDB
  197. externW f8087
  198. externB fastFP
  199. externW topPDB
  200. externW headTDB
  201. externW winVer
  202. externD Dos_Flag_Addr
  203. ifndef WOW
  204. externB WinIniInfo
  205. externB PrivateProInfo
  206. endif
  207. externW gmove_stack
  208. externW prev_gmove_SS
  209. externW BaseDsc
  210. externW WinFlags
  211. externW hUser
  212. externW hShell
  213. externW MyCSSeg
  214. externW MyDSSeg
  215. externW MyCSAlias
  216. externB fhCache
  217. externW fhCacheEnd
  218. externW fhCacheLen
  219. externB fPokeAtSegments
  220. externB fExitOnLastApp
  221. externW segLoadBlock
  222. externD pKeyProc
  223. externD pKeyProc1
  224. externW wDefRIP
  225. externW cpShrunk
  226. externW cpShrink
  227. externW hLoadBlock
  228. externD pTimerProc
  229. externD pExitProc
  230. externD pDisableProc
  231. externD lpWindowsDir
  232. externD lpSystemDir
  233. ;if KDEBUG and SWAPPRO
  234. ;externD prevIntF0proc
  235. ;endif
  236. externD lpInt21 ; support for NOVELL stealing int 21h
  237. ifdef WOW
  238. externD pFileTable
  239. externW cBytesSys16Dir
  240. externD lpSystem16Dir
  241. externB Sys16Suffix
  242. externW cBytesSys16Suffix
  243. externW cBytesSysWx86Dir
  244. externD lpSystemWx86Dir
  245. externB SysWx86Suffix
  246. externW cBytesSysWx86Suffix
  247. externD pPMDosCURDRV
  248. externD pPMDosCDSCNT
  249. externD pPMDosPDB
  250. externD pPMDosExterr
  251. externD pPMDosExterrLocus
  252. externD pPMDosExterrActionClass
  253. externD pDosWowData
  254. globalW cbRealWindowsDir,0
  255. WINDIR_BUFSIZE equ 121
  256. achWindowsDir DB WINDIR_BUFSIZE DUP(?)
  257. achRealWindowsDir DB WINDIR_BUFSIZE DUP(?)
  258. achSystem16Dir DB 128 DUP(?)
  259. achSystemWx86Dir DB 128 DUP(?)
  260. public cbRealWindowsDir, achRealWindowsDir, achWindowsDir, achSystem16Dir
  261. externB achTermSrvWindowsDir ; windows directory path (for win.ini)
  262. endif
  263. DataEnd
  264. ;------------------------------------------------------------------------
  265. ; INITDATA Variables
  266. ;------------------------------------------------------------------------
  267. DataBegin INIT
  268. ifndef WOW
  269. ; WOW doesn't muck with the WOAName buffer -- we just leave it
  270. ; as WINOLDAP.MOD
  271. externB woa_286
  272. externB woa_386
  273. endif
  274. externB bootExecBlock
  275. externW oNRSeg
  276. externW oMSeg
  277. externW win_show
  278. externD lpBootApp
  279. staticW initTDBbias,0
  280. staticW initSP,0
  281. staticW initSSbias,0
  282. staticW segNewCS,0
  283. app_name db 68 dup(0)
  284. DataEnd INIT
  285. ;------------------------------------------------------------------------
  286. ; EMSDATA Variables
  287. ;------------------------------------------------------------------------
  288. ;------------------------------------------------------------------------
  289. externNP LoadSegment
  290. externNP genter
  291. externNP gleave
  292. externNP GlobalInit
  293. externNP DeleteTask
  294. externNP BootSchedule
  295. externNP InitFwdRef
  296. externNP SaveState
  297. externNP LKExeHeader
  298. externNP GetPureName
  299. externNP SegmentNotPresentFault
  300. externNP LDT_Init
  301. externNP alloc_data_sel
  302. externNP get_physical_address
  303. externNP set_physical_address
  304. externNP set_sel_limit
  305. externNP free_sel
  306. externFP set_discarded_sel_owner
  307. externNP SelToSeg
  308. externNP DebugDefineSegment
  309. externNP DebugFreeSegment
  310. externNP SwitchToPMODE
  311. externNP LKAllocSegs
  312. ifdef WOW
  313. externFP WOWFastBopInit
  314. endif
  315. if KDEBUG
  316. if SWAPPRO
  317. externB fSwapPro
  318. externW hSwapPro
  319. externW cur_dos_pdb
  320. endif
  321. endif
  322. ifdef FE_SB
  323. externFP FarMyIsDBCSTrailByte
  324. endif
  325. ;------------------------------------------------------------------------
  326. sBegin INITCODE
  327. assumes cs,CODE
  328. externD prevIntx6proc
  329. externD prevInt0Cproc
  330. externD prevInt0Dproc
  331. externD prevInt0Eproc
  332. externD prevInt21proc
  333. externD prevInt3Fproc
  334. ifdef WOW
  335. externD prevInt01proc
  336. externD prevInt03proc
  337. externD oldInt00proc
  338. externFP GlobalDosAlloc
  339. externFP GlobalDosFree
  340. endif
  341. externNP TextMode
  342. externNP InitDosVarP
  343. externNP GrowSFTToMax
  344. ifndef WOW
  345. externNP SetUserPro
  346. endif
  347. externNP MyLock
  348. externNP Shrink
  349. externNP DebugDebug
  350. externNP NoOpenFile
  351. externNP NoLoadHeader
  352. if SDEBUG
  353. externNP DebugInit
  354. endif
  355. ;if SWAPPRO
  356. ;externNP INTF0Handler
  357. ;endif
  358. if SDEBUG
  359. szModName db 'KERNEL',0
  360. endif
  361. ifdef WOW
  362. externNP SetOwner
  363. endif
  364. ;-----------------------------------------------------------------------;
  365. ; Bootstrap ;
  366. ; ;
  367. ; Determines whether we should initialize in a smaller amount of ;
  368. ; memory, leaving room for an EEMS swap area. If so, we rep-move the ;
  369. ; code to a lower address, and tell the PSP to report less memory ;
  370. ; available. It then does lots more of stuff. ;
  371. ; ;
  372. ; Arguments: ;
  373. ; DS:0 = new EXE header ;
  374. ; ES:0 = Program Segment Prefix block (PSP) ;
  375. ; SS:SP = new EXE header ;
  376. ; CX = file offset of new EXE header (set by KernStub) ;
  377. ; DS = automatic data segment if there is one ;
  378. ; ;
  379. ; Returns: ;
  380. ; ;
  381. ; Error Returns: ;
  382. ; ;
  383. ; Registers Preserved: ;
  384. ; ;
  385. ; Registers Destroyed: ;
  386. ; ;
  387. ; Calls: ;
  388. ; ;
  389. ; History: ;
  390. ; ;
  391. ; Sat Jun 20, 1987 06:00:00p -by- David N. Weise [davidw] ;
  392. ; Made fast booting work with real EMS. ;
  393. ; ;
  394. ; Tue Apr 21, 1987 06:31:42p -by- David N. Weise [davidw] ;
  395. ; Added some more EMS support. ;
  396. ; ;
  397. ; Thu Apr 09, 1987 02:52:37p -by- David N. Weise [davidw] ;
  398. ; Put back in the movement down if EMS. ;
  399. ; ;
  400. ; Sat Mar 14, 1987 05:55:29p -by- David N. Weise [davidw] ;
  401. ; Added this nifty comment block. ;
  402. ;-----------------------------------------------------------------------;
  403. assumes ds,DATA
  404. assumes es,nothing
  405. assumes ss,nothing
  406. cProc BootStrap,<PUBLIC,NEAR>
  407. cBegin nogen
  408. if KDEBUG
  409. jmp short Hello_WDEB_End
  410. Hello_WDEB:
  411. db 'Windows Kernel Entry',13,10,0
  412. Hello_WDEB_End:
  413. push ax
  414. push es
  415. push si
  416. xor ax, ax
  417. mov es, ax
  418. mov ax, es:[68h*4]
  419. or ax, es:[68h*4+2]
  420. jz @F
  421. mov ax,cs
  422. mov es,ax
  423. lea si,Hello_WDEB
  424. mov ah,47h
  425. int 68h
  426. @@:
  427. pop si
  428. pop es
  429. pop ax
  430. endif
  431. BootTrace 'a'
  432. cmp ax, "KO" ; OK to boot; set by kernstub.asm
  433. je @F
  434. xor ax, ax
  435. retf
  436. @@:
  437. ; Set up addressibility to our code & data segments
  438. mov MyCSSeg, cs
  439. mov MyDSSeg, ds
  440. ifdef WOW
  441. ; Get pointer to sft so that I can find do direct protect mode
  442. ; file IO operations
  443. mov CS:MyCSDS, ds
  444. push es
  445. mov ah,52h ; get pointer to internal vars
  446. int 21h
  447. mov ax, es
  448. shl ax, 4
  449. add ax, DOS_FLAG_OFFSET
  450. sub ax, 400h
  451. mov Dos_Flag_Addr.off, ax
  452. mov Dos_Flag_Addr.sel, 40h
  453. ;
  454. ; Retrieve some pointers from the DosWowData structure in DOS.
  455. ;
  456. push di
  457. push dx
  458. mov di, es:[bx+6ah] ;kernel data pointer
  459. mov pDosWowData.off, di
  460. mov pDosWowData.sel, es
  461. mov ax, word ptr es:[di].DWD_lpCurPDB
  462. ; mov dx, word ptr es:[di].DWD_lpCurPDB+2
  463. mov pPMDosPDB.off,ax
  464. mov pPMDosPDB.sel,0 ;to force gpfault if not ready
  465. mov ax, word ptr es:[di].DWD_lpCurDrv
  466. ; mov dx, word ptr es:[di].DWD_lpCurDrv+2
  467. mov pPMDosCURDRV.off,ax
  468. mov pPMDosCURDRV.sel,0 ;to force gpfault if not ready
  469. mov ax, word ptr es:[di].DWD_lpCDSCount
  470. ; mov dx, word ptr es:[di].DWD_lpCDSCount+2
  471. mov pPMDosCDSCNT.off,ax
  472. mov pPMDosCDSCNT.sel,0 ;to force gpfault if not ready
  473. mov ax, word ptr es:[di].DWD_lpExterr
  474. mov pPMDosExterr.off, ax
  475. mov pPMDosExtErr.sel, 0
  476. mov ax, word ptr es:[di].DWD_lpExterrLocus
  477. mov pPMDosExterrLocus.off, ax
  478. mov pPMDosExtErrLocus.sel, 0
  479. mov ax, word ptr es:[di].DWD_lpExterrActionClass
  480. mov pPMDosExterrActionClass.off, ax
  481. mov pPMDosExtErrActionClass.sel, 0
  482. pop dx
  483. pop di
  484. lea bx,[bx+sftHead]
  485. mov pFileTable.off,bx
  486. mov pFileTable.sel,es
  487. pop es
  488. endif ; WOW
  489. BootTrace 'b'
  490. call SwitchToPMODE ; BX -> LDT, DS -> CS(DS), SI start of memory
  491. BootTrace 'c'
  492. ReSetKernelDS
  493. mov BaseDsc,si
  494. call LDT_Init
  495. BootTrace 'd'
  496. ifdef WOW
  497. call AllocSelector_0x47
  498. call WOWFastBopInit
  499. endif
  500. if SDEBUG
  501. ; In protected mode, initialize the debugger interface NOW. Only real mode
  502. ; needs to wait until the global heap is initialized.
  503. cCall DebugInit
  504. ; In protected mode, define where our temp Code & Data segments are
  505. mov ax,codeOffset szModName
  506. cCall DebugDefineSegment,<cs,ax,0,cs,0,0>
  507. mov ax,codeOffset szModName
  508. cCall DebugDefineSegment,<cs,ax,3,ds,0,1>
  509. endif
  510. BootTrace 'e'
  511. BootTrace 'f'
  512. ifdef WOW
  513. push ax
  514. push bx
  515. mov bx, pDosWowData.sel ;use this segment
  516. mov ax, 2
  517. int 31h
  518. mov pPMDosPDB.sel,ax ;make this a PM pointer
  519. mov pPMDosCURDRV.sel,ax ;make this a PM pointer
  520. mov pPMDosCDSCNT.sel,ax ;make this a PM pointer
  521. mov pPMDosExterr.sel,ax
  522. mov pPMDosExterrLocus.sel,ax
  523. mov pPMDosExterrActionClass.sel,ax
  524. pop bx
  525. pop ax
  526. push pDosWowData.sel
  527. push pDosWowData.off
  528. call WOWDosWowInit
  529. endif
  530. ; InitDosVarP just records a few variables, it does no hooking.
  531. ; It does dos version checking and other fun stuff that
  532. ; must be done as soon as possible.
  533. call InitDosVarP
  534. or ax,ax
  535. jnz inited_ok
  536. Debug_Out "KERNEL: InitDosVarP failed"
  537. mov ax,4CFFh ; Goodbye!
  538. INT21
  539. inited_ok:
  540. BootTrace 'g'
  541. push bx
  542. mov bx, WinFlags
  543. ifndef JAPAN ; should be removed because of IBM dependent code.
  544. ; InitFwdRef routine will set 80x87 status bit in WinFlags
  545. ; and exported location #178.
  546. ; Determine if there is a co-processor present.
  547. int 11h ; get equipment word
  548. test al,2 ; this is the IBM approved method
  549. jz no_80x87 ; to check for an 8087
  550. or bh,WF1_80x87
  551. no_80x87:
  552. endif ;NOT JAPAN
  553. ifdef WOW
  554. or bh,WF1_WINNT ; Set NT flag ON
  555. endif
  556. mov WinFlags,bx
  557. pop bx
  558. ; Determine if running under Windows/386 or the 286 DOS Extender
  559. push bx
  560. mov ax,(MultWin386 SHL 8) OR MW3_ReqInstall ; Win/386 install check
  561. int 2Fh
  562. BootTrace 'h'
  563. cmp al,MW3_ReqInstall_Ret_4 ; Under WIN386 in pmode?
  564. or Kernel_flags[1],kf1_Win386
  565. or byte ptr WinFlags,WF_PMODE or WF_ENHANCED
  566. jmps InstallChkDone
  567. NotUnderWin386:
  568. or Kernel_flags[2],KF2_DOSX
  569. or byte ptr WinFlags,WF_PMODE or WF_STANDARD
  570. InstallChkDone:
  571. BootTrace 'i'
  572. pop bx
  573. ifndef WOW
  574. ; WOW doesn't muck with the WOAName buffer -- we just leave it
  575. ; as WINOLDAP.MOD
  576. push cx
  577. push di
  578. push si
  579. cld
  580. mov cx,8
  581. smov es,ds
  582. mov di,dataOffset WOAName
  583. mov si,dataOffset woa_286
  584. test Kernel_flags[2],KF2_DOSX
  585. jnz @F
  586. mov si,dataOffset woa_386
  587. @@: rep movsb
  588. pop si
  589. pop di
  590. pop cx
  591. endif
  592. BootTrace 'j'
  593. mov ax,cx
  594. mov cl,4
  595. shr ax,cl
  596. mov cpShrunk,ax
  597. ; Compute paragraph address of new EXE header from SS:SP
  598. mov bx,sp ; SS:SP -> new EXE header
  599. cCall get_physical_address,<ss>
  600. add ax,bx
  601. adc dx,0
  602. BootTrace 'k'
  603. cCall alloc_data_sel,<dx,ax,0,0FFFFh>
  604. BootTrace 'l'
  605. mov segLoadBlock,ax ; hinitexe:0 -> new EXE header
  606. ; calculate the TDB bias
  607. mov bx,dataOffset boottdb
  608. mov initTDBbias,bx
  609. ; calculate the SS bias
  610. mov bx,dataOffset stackbottom
  611. mov initSSbias,bx
  612. ; calculate the initial SP
  613. mov si,dataOffset stacktop
  614. sub si,dataOffset stackbottom
  615. mov initSP,si
  616. cCall get_physical_address,<ds>
  617. add ax,bx
  618. adc dx,0
  619. BootTrace 'm'
  620. FCLI
  621. mov prev_gmove_SS, ss ; Switch stack while we set up new SS
  622. smov ss, ds
  623. mov sp, dataOFFSET gmove_stack
  624. cCall set_physical_address,<prev_gmove_SS>
  625. xor ax, ax
  626. xchg ax, prev_gmove_SS
  627. BootTrace 'n'
  628. mov ss,ax ; switch to new stack
  629. mov sp,si
  630. FSTI
  631. xor bp,bp ; zero terminate BP chain.
  632. sub si,BOOTSTACKSIZE
  633. mov ss:[pStackBot],sp
  634. mov ss:[pStackMin],sp
  635. mov ss:[pStackTop],si
  636. cld
  637. mov es,topPDB
  638. externB szNoGlobalInit
  639. BootTrace 'o'
  640. mov ax, BaseDsc ; Free memory starts after this
  641. mov bx,segLoadBlock ; Make boot image be first busy block
  642. mov cx,es:[PDB_block_len] ; cx is end of memory
  643. mov dx,MASTER_OBJECT_SIZE
  644. cCall GlobalInit,<dx,bx,ax,cx>
  645. jc @F ; passed through from ginit
  646. or ax,ax
  647. jnz mem_init_ok
  648. @@:
  649. mov dx, codeoffset szNoGlobalInit
  650. smov ds, cs
  651. mov ah, 9
  652. int 21h ; Whine
  653. mov ax, 4CFFh
  654. int 21h ; And exit
  655. ;NoGlobalInit db "KERNEL: Unable to initialise heap",13,10,'$'
  656. mem_init_ok:
  657. mov hLoadBlock,ax ; Save handle to first busy block
  658. BootTrace 'p'
  659. mov pExitProc.sel,cs
  660. mov pExitProc.off,codeOffset ExitKernel
  661. ; Find out where we live, and where win.com lives.
  662. mov ds,topPDB
  663. UnSetKernelDS
  664. mov bx,ds
  665. mov ds,ds:[PDB_environ]
  666. xor si,si
  667. cld
  668. envloop1:
  669. lodsb
  670. or al,al ; end of item?
  671. jnz envloop1
  672. lodsb
  673. or al,al ; end of environment?
  674. jnz envloop1
  675. lodsw ; ignore argc, DS:SI -> kernel path
  676. ifdef WOW
  677. smov es, ds ; now ES:SI -> kernel path
  678. else
  679. call get_windir ; on return, DS:DI -> windir= value
  680. smov es,ds
  681. ; Record where to find the 'windows' directory.
  682. BootTrace 'q'
  683. SetKernelDS
  684. or di,di
  685. jz no_win_dir_yet
  686. mov lpWindowsDir.sel,es
  687. mov lpWindowsDir.off,di
  688. mov cBytesWinDir,cx
  689. ; Now set pointer to WIN.INI to be
  690. ; in the Windows directory
  691. push si
  692. push es
  693. smov es, ds
  694. mov si, dataoffset szUserPro+6
  695. mov di, si
  696. inc cx
  697. add di, cx ; Move up the string WIN.INI
  698. std
  699. mov cx, 4
  700. rep movsw
  701. ; Now copy Windows directory
  702. cld
  703. mov cx, cBytesWinDir
  704. mov di, dataoffset szUserPro
  705. lds si, lpWindowsDir
  706. UnSetKernelDS
  707. rep movsb
  708. mov byte ptr es:[di], '\'
  709. pop es
  710. pop si
  711. endif
  712. SetKernelDS
  713. BootTrace 'r'
  714. no_win_dir_yet:
  715. sub sp,SIZE OPENSTRUC + 127
  716. mov di,sp
  717. regptr ssdi,ss,di
  718. mov bx,OF_EXIST
  719. cCall IOpenFile,<essi,ssdi,bx>
  720. BootTrace 's'
  721. inc ax ; Test for -1
  722. jnz opn1 ; Continue if success
  723. mov dx, codeoffset NoOpenFile
  724. fail1:
  725. push dx ; Save string pointer
  726. call textmode ; Switch to text mode
  727. pop dx
  728. smov ds, cs
  729. mov ah, 9
  730. int 21h ; Tell user why we're bailing out
  731. mov ax,4CFFh ; Goodbye!
  732. INT21
  733. opn1:
  734. ; Now simulate loading ourselves from memory
  735. ; Load new EXE header for KERNEL.EXE from memory
  736. cCall LKExeHeader,<segLoadBlock,ssdi>
  737. BootTrace 't'
  738. add sp,SIZE OPENSTRUC + 127
  739. or ax,ax
  740. jnz @F
  741. mov dx, codeoffset NoLoadHeader
  742. jmp SHORT fail1
  743. @@:
  744. mov hExeHead,ax
  745. mov es,ax
  746. ifndef WOW
  747. ; Record where to find the 'system' directory.
  748. mov di,es:[ne_pfileinfo]
  749. lea di,es:[di].opFile
  750. mov lpSystemDir.sel,es
  751. mov lpSystemDir.off,di
  752. mov dx,di
  753. call GetPureName
  754. sub di,dx
  755. dec di
  756. mov cBytesSysDir,di
  757. BootTrace 'u'
  758. endif
  759. ; ndef WOW
  760. ; Make room at end of kernel data segment for stack--NOTE: DGROUP is
  761. ; assumed to be segment 4!
  762. mov bx,es:[ne_segtab]
  763. add es:[bx+(3*size NEW_SEG1)].ns_minalloc,EXTRASTACKSIZE
  764. ; Determine size of kernel's largest discardable code segment
  765. ; don't bother with swap area's anymore. Its fixed 192k (3segs)
  766. ; picked this up from Win95
  767. xor ax,ax ; No max
  768. mov es:[ne_swaparea],ax
  769. BootTrace 'v'
  770. ; Allocate memory for kernel segments
  771. cCall LKAllocSegs,<es>
  772. mov oNRSeg,ax
  773. mov oMSeg, bx ; Misc segment
  774. mov es,hExeHead
  775. ; If this is a pMode debug version, the code and data segments have already
  776. ; been defined to the debugger once. We're about to LoadSegment and define
  777. ; these segments again in their final location. Use a special form of
  778. ; DebugFreeSegment to force the debugger to pull out any breakpoints in these
  779. ; segments. If we don't do this, any existing breakpoints become INT 3's
  780. ; in the new copy of the segment and the code has to be patched by hand.
  781. ; If only the debugger was smart enough to 'move' the breakpoints when it
  782. ; saw a second define for an already loaded segment...
  783. if SDEBUG
  784. cCall DebugFreeSegment,<cs,-1>
  785. cCall DebugFreeSegment,<MyCSDS,-1>
  786. endif
  787. ; Load kernel code segment 1 (resident code)
  788. mov si,1
  789. mov ax,-1 ; Indicate loading from memory
  790. cCall LoadSegment,<es,si,cs,ax>
  791. or ax,ax
  792. jnz ll1
  793. fail2: jmp bootfail
  794. ll1:
  795. mov segNewCS,ax ; Save new CS value
  796. ; Load kernel data segment (segment 4)
  797. mov si,4
  798. mov ax,-1
  799. cCall LoadSegment,<hExeHead,si,ds,ax>
  800. or ax,ax
  801. jz fail2
  802. BootTrace 'w'
  803. ; locate the stack in the new segment
  804. mov bx,ax
  805. mov si,initSP
  806. add si,EXTRASTACKSIZE
  807. cCall get_physical_address,<ax>
  808. add ax,initSSbias
  809. adc dx,0
  810. sub ax,10h
  811. sbb dx,0
  812. or ax,10h
  813. FCLI
  814. mov prev_gmove_SS, ss ; Switch stack while we set up new SS
  815. smov ss, ds
  816. mov sp, OFFSET gmove_stack
  817. cCall set_physical_address,<prev_gmove_SS>
  818. push bx
  819. mov bx, si
  820. xor cx, cx ; cx:bx=stack len (for set_sel_limit)
  821. cCall set_sel_limit,<prev_gmove_SS>
  822. pop bx
  823. xor ax, ax
  824. xchg ax, prev_gmove_SS
  825. mov ss,ax ; Switch to new stack location
  826. mov sp,si
  827. FSTI
  828. mov ax,bx
  829. ; zero the new TDB
  830. push ax
  831. cCall get_physical_address,<ax>
  832. add ax,initTDBbias
  833. adc dx,0
  834. YAH_WELL = (SIZE TDB+15) and NOT 15
  835. cCall alloc_data_sel,<dx,ax,0,YAH_WELL>
  836. mov es,ax
  837. xor ax,ax
  838. mov di,ax
  839. mov cx,SIZE TDB
  840. cld
  841. rep stosb
  842. pop ax
  843. ; put the limits in the stack
  844. xor bp,bp ; zero terminate BP chain.
  845. mov ss:[pStackBot],sp
  846. mov ss:[pStackMin],sp
  847. mov ss:[pStackTop],10h
  848. mov ss:[0],bp ; To mark this stack as NOT linked
  849. mov ss:[2],bp ; to another, see PatchStack.
  850. mov ss:[4],bp
  851. ; initialize the new TDB
  852. sub sp,SIZE TASK_REGS
  853. mov es:[TDB_taskSS],ss
  854. mov es:[TDB_taskSP],sp
  855. mov cx,topPDB
  856. mov es:[TDB_PDB],cx ; save new PDB
  857. mov es:[TDB_DTA].off,80h ; set initial DTA
  858. mov es:[TDB_DTA].sel,cx
  859. mov bx,1 ; BX = 1
  860. mov es:[TDB_nEvents],bx ; Start this guy up!
  861. mov es:[TDB_pModule],-1 ; EMS requires -1
  862. mov bx,winVer
  863. mov es:[TDB_ExpWinVer],bx ; Windows Version #
  864. mov es:[TDB_sig],TDB_SIGNATURE ; Set signature word.
  865. ; initialize the task BP and DS
  866. push es
  867. les bx,dword ptr es:[TDB_taskSP]
  868. mov es:[bx].TASK_BP,bp ; initial BP = 0
  869. mov es:[bx].TASK_DS,bp ; initial DS = 0
  870. pop es
  871. mov ds,ax ; switch to new DS segment
  872. mov ax,segNewCS ; recover new CS value
  873. push cs ; to free the selector
  874. ; do a far return to the new code segment
  875. push ax
  876. mov ax,codeOffset new_code
  877. push ax
  878. ret_far ; FAR return to new code segment
  879. public new_code
  880. new_code:
  881. pop ax
  882. push es
  883. cCall free_sel,<ax> ; Free old CS selector
  884. cCall IPrestoChangoSelector,<cs,MyCSAlias> ; Change our CS Alias
  885. mov es,MyCSAlias ; Change MyCSDS to new DS
  886. assumes es,CODE
  887. mov ax,ds
  888. xchg ax,es:MyCSDS
  889. assumes es,nothing
  890. cCall free_sel,<ax> ; Free old DS selector
  891. call DebugDebug ; do after MyCSDS changes
  892. mov pExitProc.sel,cs ; reset this!!
  893. ;;; pusha
  894. ;;; cCall get_physical_address,<cs>
  895. ;;; add ax, codeOffset end_page_locked
  896. ;;; adc dx, 0
  897. ;;; mov bx, dx
  898. ;;; mov cx, ax
  899. ;;; mov di, cs
  900. ;;; lsl di, di
  901. ;;; sub di, codeOffset end_page_locked
  902. ;;; xor si, si
  903. ;;; mov ax, 0601h
  904. ;;; int 31h ; Unlock some of Kernel!
  905. ;;; popa
  906. cCall SelToSeg,<ds> ; Save DS segment value
  907. mov MyDSSeg,ax
  908. cCall SelToSeg,<cs> ; Set segment equivalent
  909. mov MyCSSeg, ax
  910. ; calculate the maximum amount that we will allow SetSwapAreaSize to set
  911. mov ax,-1 ; They can only harm themselves.
  912. mov MaxCodeSwapArea,ax
  913. ifndef WOW ; WOW uses 32 bit profile api's
  914. ; Allocate a handle for WIN.INI
  915. xor ax,ax
  916. mov bx,GA_SHAREABLE shl 8 OR GA_MOVEABLE
  917. cCall IGlobalAlloc,<bx,ax,ax>
  918. mov [WinIniInfo.hBuffer], ax
  919. or ax,ax
  920. jz nowinini
  921. mov bx,ax ; put handle into base register
  922. mov ax,hExeHead
  923. mov es,ax
  924. call set_discarded_sel_owner
  925. ; Set up the filename
  926. mov word ptr [WinIniInfo.lpProFile], dataoffset szUserPro
  927. mov word ptr [WinIniInfo.lpProFile][2], ds
  928. nowinini:
  929. ; Allocate a handle for Private Profiles
  930. xor ax,ax
  931. mov bx,GA_SHAREABLE shl 8 OR GA_MOVEABLE
  932. cCall IGlobalAlloc,<bx,ax,ax>
  933. mov [PrivateProInfo.hBuffer],ax
  934. or ax,ax
  935. jz noprivate
  936. mov bx,ax ; put handle into base register
  937. mov ax,hExeHead
  938. mov es,ax
  939. call set_discarded_sel_owner
  940. noprivate:
  941. endif; WOW
  942. ifdef WOW
  943. ; Allocate a ~128K discardable code selector to hide the
  944. ; GrowHeap - heap not sorted bugs, also present in Win 3.1.
  945. ;
  946. ; Since our system DLLs (like krnl386, user, gdi etc) contain a few
  947. ; discardable codesgements (of approx 40K), we need not be precise
  948. ;
  949. push es
  950. mov ax, 0C000H ; hiword is 01h , totalsize 0x1c000 bytes
  951. mov bx, GA_MOVEABLE OR GA_DISCCODE
  952. cCall IGlobalAlloc,<bx,01h,ax>
  953. or ax,ax
  954. jz short nogrowheap
  955. cCall SetOwner, <ax, hExeHead>
  956. nogrowheap:
  957. pop es
  958. endif; WOW
  959. ; Now shrink off exe header and segment 1 of KERNEL.EXE
  960. mov si,2 ; Segment number
  961. xor ax,ax
  962. xchg oNRSeg,ax
  963. nofastboot:
  964. sub ax,cpShrunk
  965. mov cpShrink,ax ; Amount to shrink by
  966. cCall MyLock,<hLoadBlock>
  967. mov bx,ax
  968. xchg segLoadBlock,ax
  969. cCall get_physical_address,<ax>
  970. mov cx,dx
  971. xchg bx,ax
  972. cCall get_physical_address,<ax>
  973. sub bx,ax
  974. sbb cx,dx
  975. REPT 4
  976. shr cx,1
  977. rcr bx,1
  978. ENDM
  979. mov ax,bx
  980. add cpShrink,ax
  981. push ax
  982. cCall Shrink
  983. pop ax
  984. sub cpShrunk,ax
  985. ; Load kernel code segment 2 (non-resident code)
  986. cCall MyLock,<hLoadBlock>
  987. mov bx,-1 ; Indicate loading from memory
  988. cCall LoadSegment,<hExeHead,si,ax,bx>
  989. or ax,ax
  990. jnz ll2
  991. pop es
  992. jmp bootfail
  993. ll2:
  994. inc si ; On to segment 3
  995. xor ax, ax
  996. xchg ax, oMSeg ; Once back only!
  997. or ax, ax
  998. jnz nofastboot
  999. pop es
  1000. call genter
  1001. smov ds, es
  1002. UnSetKernelDS
  1003. SetKernelDS es
  1004. ;;;mov ax,EMScurPID ; In case an EMS fast boot is going down.
  1005. ;;;mov ds:[TDB_EMSPID],ax
  1006. ;;;mov ax,ds:[TDB_EMSPID]
  1007. ;;;mov PID_for_fake,ax
  1008. ;;;mov EMScurPID,ax
  1009. mov curTDB,ds
  1010. mov headTDB,ds
  1011. push es
  1012. ; vectors
  1013. SaveVec MACRO vec
  1014. mov ax, 35&vec
  1015. DOSCALL
  1016. mov [di.off], bx
  1017. mov [di.sel], es
  1018. add di, 4
  1019. ENDM
  1020. push di
  1021. mov di, TDB_INTVECS
  1022. SaveVec 00h
  1023. SaveVec 02h
  1024. SaveVec 04h
  1025. SaveVec 06h
  1026. SaveVec 07h
  1027. SaveVec 3Eh
  1028. SaveVec 75h
  1029. ifdef WOW
  1030. ;; Hook Int10 so we can filter calls in WOW (see intnn.asm)
  1031. push es
  1032. push ds
  1033. mov ax,3510h
  1034. INT21
  1035. mov ax,codeOffset prevInt10proc
  1036. SetKernelCSDword ax,es,bx
  1037. mov ax,2510h
  1038. smov ds,cs
  1039. mov dx,codeOFFSET Int10Handler
  1040. INT21
  1041. pop ds
  1042. pop es
  1043. endif
  1044. pop di
  1045. cCall SaveState,<ds>
  1046. pop es
  1047. mov ds,pGlobalHeap
  1048. call gleave
  1049. UnSetKernelDS es
  1050. mov ax, 32 ; Kernel wants a big handle table
  1051. cCall SetHandleCount,<ax>
  1052. SetKernelDS
  1053. ;
  1054. ; The following variable initialization is done here to avoid having
  1055. ; relocations in Kernel's data segment.
  1056. ;
  1057. mov lpInt21.off,codeOFFSET Int21Handler
  1058. mov lpInt21.sel,cs
  1059. ;
  1060. ; Before we hook exception handlers, make sure the DPMI exception
  1061. ; handler stack is set up the way Windows likes it.
  1062. ;
  1063. mov bl,6
  1064. mov ax,0202h ; DPMI get exception handler vector
  1065. int 31h
  1066. push cx
  1067. push dx
  1068. mov cx,cs
  1069. lea dx,fixing_stack
  1070. mov bl,6
  1071. mov ax,0203h ; DPMI set exception handler vector
  1072. int 31h
  1073. pop dx
  1074. pop cx
  1075. ;
  1076. ; Generate an invalid opcode exception fault. This causes DPMI to call
  1077. ; our "exception handler."
  1078. ;
  1079. db 0fh,0ffh
  1080. fixing_stack:
  1081. push bp
  1082. mov bp,sp ; BP -> BP RETIP RETCS EC IP CS FL SP SS
  1083. ;
  1084. ; Restore the previous invalid exception handler vector.
  1085. ;
  1086. mov bl,6
  1087. mov ax,0203h
  1088. int 31h
  1089. ;
  1090. ; Replace the return address on the DPMI fault handler routine with
  1091. ; our exit code.
  1092. ;
  1093. lea ax,done_fixing_stack
  1094. mov [bp+8],ax
  1095. mov [bp+10],cs
  1096. lea ax,[bp+16]
  1097. mov ss:[pStackBot],ax
  1098. mov ss:[pStackMin],sp
  1099. mov ss:[pStackTop],offset pStackBot + 150
  1100. mov sp,bp
  1101. pop bp
  1102. retf
  1103. done_fixing_stack:
  1104. mov es, MyCSAlias
  1105. assumes es, CODE
  1106. ; Hook not present fault for segment reloader.
  1107. mov ax,0202h ; Record old not present fault.
  1108. mov bl,0Bh
  1109. int 31h
  1110. mov prevInt3Fproc.off,dx
  1111. mov prevInt3Fproc.sel,cx
  1112. mov ax,0203h ; Hook not present fault.
  1113. mov cx,cs
  1114. mov dx,codeOffset SegmentNotPresentFault
  1115. int 31h
  1116. ; Hook GP fault in order to terminate app.
  1117. mov bl, 0Dh ; GP Fault
  1118. mov ax, 0202h
  1119. int 31h
  1120. mov prevInt0Dproc.off, dx
  1121. mov prevInt0Dproc.sel, cx
  1122. mov ax, 0203h
  1123. mov cx, cs
  1124. mov dx, codeOffset GPFault
  1125. int 31h
  1126. ; Hook invalid op-code in order to terminate app.
  1127. mov bl, 06h ; invalid op-code
  1128. mov ax, 0202h
  1129. int 31h
  1130. mov prevIntx6proc.off, dx
  1131. mov prevIntx6proc.sel, cx
  1132. mov ax, 0203h
  1133. mov cx, cs
  1134. mov dx, codeOffset invalid_op_code_exception
  1135. int 31h
  1136. ; Hook stack fault in order to terminate app.
  1137. mov bl, 0Ch ; stack fault
  1138. mov ax, 0202h
  1139. int 31h
  1140. mov prevInt0Cproc.off, dx
  1141. mov prevInt0Cproc.sel, cx
  1142. mov ax, 0203h
  1143. mov cx, cs
  1144. mov dx, codeOffset StackFault
  1145. int 31h
  1146. ; Hook bad page fault in order to terminate app.
  1147. mov bl, 0Eh ; page fault
  1148. mov ax, 0202h
  1149. int 31h
  1150. mov prevInt0Eproc.off, dx
  1151. mov prevInt0Eproc.sel, cx
  1152. mov ax, 0203h
  1153. mov cx, cs
  1154. mov dx, codeOffset page_fault
  1155. int 31h
  1156. ifdef WOW
  1157. ; Hook divide overflow trap in order to get better WOW debugging.
  1158. mov bl, 00h ; divide overflow
  1159. mov ax, 0202h
  1160. int 31h
  1161. mov oldInt00proc.off, dx
  1162. mov oldInt00proc.sel, cx
  1163. mov ax, 0203h
  1164. mov cx, cs
  1165. mov dx, codeOffset divide_overflow
  1166. int 31h
  1167. ; Hook single step trap in order to get better WOW debugging.
  1168. mov bl, 01h ; single step
  1169. mov ax, 0202h
  1170. int 31h
  1171. mov prevInt01proc.off, dx
  1172. mov prevInt01proc.sel, cx
  1173. mov ax, 0203h
  1174. mov cx, cs
  1175. mov dx, codeOffset single_step
  1176. int 31h
  1177. ; Hook breakpoint trap in order to get better WOW debugging.
  1178. mov bl, 03h ; page fault
  1179. mov ax, 0202h
  1180. int 31h
  1181. mov prevInt03proc.off, dx
  1182. mov prevInt03proc.sel, cx
  1183. mov ax, 0203h
  1184. mov cx, cs
  1185. mov dx, codeOffset breakpoint
  1186. int 31h
  1187. endif
  1188. assumes es, nothing
  1189. ; Do a slimy fix-up of __WinFlags containing processor and protect mode flags
  1190. xor ax,ax
  1191. mov dx,178
  1192. cCall GetProcAddress,<hExeHead,ax,dx>
  1193. mov ax,WinFlags
  1194. mov es:[bx],ax
  1195. ifdef WOW
  1196. ; get WOW32 thunk table offsets and do fixups
  1197. ; WARNING: WOW32 has a dependency on this being called after
  1198. ; kernel is done booting and addresses are fixed
  1199. push ds
  1200. push dataoffset MOD_KERNEL
  1201. call far ptr WOWGetTableOffsets
  1202. mov si, dataoffset MOD_KERNEL
  1203. mov cx, ModCount ; # fixups to do
  1204. mov di, 570 ; first ordinal of the group (DANGER hardcoded from kernel.def)
  1205. Mexico:
  1206. push si
  1207. push di
  1208. push cx
  1209. push hExeHead
  1210. push 0
  1211. push di
  1212. call GetProcAddress
  1213. pop cx
  1214. pop di
  1215. pop si
  1216. mov ax,[si]
  1217. mov es:[bx],ax
  1218. inc si ; point to next word
  1219. inc si
  1220. inc di ; get next ordinal
  1221. loop Mexico
  1222. endif
  1223. ; Do a very slimy fix-up of the runtime constant __0000h
  1224. cCall GetProcAddress,<hExeHead,0,183>
  1225. mov si,bx
  1226. mov bx,00000h
  1227. mov ax,2
  1228. int 31h
  1229. mov es:[si],ax
  1230. ; Do a very slimy fix-up of the runtime constant __0040h
  1231. cCall GetProcAddress,<hExeHead,0,193>
  1232. mov si,bx
  1233. mov bx,00040h
  1234. mov ax,2
  1235. int 31h
  1236. mov es:[si],ax
  1237. ; Do a very slimy fix-up of the runtime constant __ROMBIOS
  1238. cCall GetProcAddress,<hExeHead,0,173>
  1239. mov si,bx
  1240. mov bx,0F000h
  1241. mov ax,2
  1242. int 31h
  1243. mov es:[si],ax
  1244. ; Do a very slimy fix-up of the runtime constant __F000h
  1245. cCall GetProcAddress,<hExeHead,0,194>
  1246. mov si,bx
  1247. mov bx,0F000h
  1248. mov ax,2
  1249. int 31h
  1250. mov es:[si],ax
  1251. ; Do a very slimy fix-up of the runtime constant __A000h
  1252. cCall GetProcAddress,<hExeHead,0,174>
  1253. mov si,bx
  1254. mov bx,0A000h
  1255. mov ax,2
  1256. int 31h
  1257. mov es:[si],ax
  1258. ; Do a very slimy fix-up of the runtime constant __B000h
  1259. cCall GetProcAddress,<hExeHead,0,181>
  1260. mov si,bx
  1261. mov bx,0B000h
  1262. mov ax,2
  1263. int 31h
  1264. mov es:[si],ax
  1265. ; Do a very slimy fix-up of the runtime constant __B800h
  1266. cCall GetProcAddress,<hExeHead,0,182>
  1267. mov si,bx
  1268. mov bx,0B800h
  1269. mov ax,2
  1270. int 31h
  1271. mov es:[si],ax
  1272. ; Do a very slimy fix-up of the runtime constant __C000h
  1273. cCall GetProcAddress,<hExeHead,0,195>
  1274. mov si,bx
  1275. mov bx,0C000h
  1276. mov ax,2
  1277. int 31h
  1278. mov es:[si],ax
  1279. ; Do a very slimy fix-up of the runtime constant __D000h
  1280. cCall GetProcAddress,<hExeHead,0,179>
  1281. mov si,bx
  1282. mov bx,0D000h
  1283. mov ax,2
  1284. int 31h
  1285. mov es:[si],ax
  1286. ; Do a very slimy fix-up of the runtime constant __E000h
  1287. cCall GetProcAddress,<hExeHead,0,190>
  1288. mov si,bx
  1289. mov bx,0E000h
  1290. mov ax,2
  1291. int 31h
  1292. mov es:[si],ax
  1293. ifndef WOW
  1294. cCall SetUserPro ; Get WIN.INI filename from environment
  1295. endif
  1296. CheckKernelDS
  1297. ; Free high memory copy of KERNEL.EXE
  1298. cCall IGlobalFree,<hLoadBlock>
  1299. mov hLoadBlock,ax
  1300. .386
  1301. mov fs, ax
  1302. mov gs, ax
  1303. .286p
  1304. ifndef WOW
  1305. cmp lpWindowsDir.sel,ax
  1306. jnz got_win_dir
  1307. mov si,dataOffset szUserPro
  1308. mov di,dataOffset [WinIniInfo.ProBuf]
  1309. cCall IOpenFile,<dssi,dsdi,OF_PARSE>
  1310. lea di,[di].opfile
  1311. mov lpWindowsDir.sel,ds
  1312. mov lpWindowsDir.off,di
  1313. mov dx,di
  1314. call GetPureName
  1315. sub di,dx
  1316. dec di
  1317. mov cBytesWinDir,di
  1318. got_win_dir:
  1319. endif
  1320. ifdef WOW
  1321. ; Regular Windows kernel sets up the Windows directory very early in
  1322. ; boot, before WOW kernel loads WOW32.DLL.
  1323. ;
  1324. ; It turns out we can delay setting up the 16-bit copy of the
  1325. ; windows directory (referred by lpWindowsDir) until here, where
  1326. ; we're in protected mode and about to set up the system directories
  1327. ; as well. This allows us to call a GetShortPathName thunk in
  1328. ; WOW32.
  1329. ;
  1330. mov ds,topPDB
  1331. UnSetKernelDS
  1332. mov ds,ds:[PDB_environ]
  1333. call get_windir ; on return, DS:DI -> windows dir
  1334. smov es,ds
  1335. SetKernelDS
  1336. ; Record where to find the 'windows' directory.
  1337. BootTrace 'q'
  1338. mov lpWindowsDir.sel,es
  1339. mov lpWindowsDir.off,di
  1340. mov cBytesWinDir,cx
  1341. ; Record where to find the 'system32' directory.
  1342. mov ax,hExeHead
  1343. mov es,ax
  1344. mov di,es:[ne_pfileinfo]
  1345. lea di,es:[di].opFile
  1346. mov lpSystemDir.sel,es
  1347. mov lpSystemDir.off,di
  1348. mov dx,di
  1349. call GetPureName
  1350. sub di,dx
  1351. dec di
  1352. mov cBytesSysDir,di
  1353. BootTrace 'u'
  1354. ;
  1355. ; Under WOW there are two system directories: \nt\system and \nt\system32.
  1356. ; lpSystemDir points to \nt\system32, while lpSystem16Dir points to
  1357. ; \nt\system. We return the latter from GetSystemDirectory, since we want
  1358. ; applications to install their shared stuff in \nt\system, but we want
  1359. ; to search \nt\system32 before \nt\system when loading modules.
  1360. ; Set up lpSystem16Dir using the Windows dir + \system.
  1361. ; Note that the string pointed to by lpSystem16Dir is not null terminated!
  1362. mov lpSystem16Dir.sel,ds
  1363. mov lpSystem16Dir.off,dataoffset achSystem16Dir
  1364. cld
  1365. mov si,dataoffset achRealWindowsDir
  1366. mov es,lpSystem16Dir.sel
  1367. mov di,lpSystem16Dir.off
  1368. mov cx,cbRealWindowsDir
  1369. rep movsb ; copy Windows dir
  1370. mov si,dataoffset Sys16Suffix
  1371. mov cx,cBytesSys16Suffix
  1372. rep movsb ; tack on "\system"
  1373. mov cx,cbRealWindowsDir
  1374. add cx,cBytesSys16Suffix
  1375. mov cBytesSys16Dir,cx
  1376. ;
  1377. ; build the Wx86 system directory "Windir\Sys32x86"
  1378. ;
  1379. mov lpSystemWx86Dir.sel,ds
  1380. mov lpSystemWx86Dir.off,dataoffset achSystemWx86Dir
  1381. mov es,lpSystemWx86Dir.sel
  1382. mov di,lpSystemWx86Dir.off
  1383. mov cx,cbRealWindowsDir
  1384. mov si,dataoffset achRealWindowsDir
  1385. rep movsb ; copy System dir (Windows\System32)
  1386. mov si,dataoffset SysWx86Suffix
  1387. mov cx,cBytesSysWx86Suffix
  1388. rep movsb ; tack on "\Wx86"
  1389. mov cx,cbRealWindowsDir
  1390. add cx,cBytesSysWx86Suffix
  1391. mov cBytesSysWx86Dir,cx
  1392. @@:
  1393. ; WOW DPMI Supports wants to call GlobalDosAlloc and GlobalDosFree so that
  1394. ; We don't have to write the same code for DPMI support. So we call DPMI
  1395. ; Here with the addresses of those routines so he can call us back.
  1396. mov bx,cs
  1397. mov si,bx
  1398. mov dx,codeOffset GlobalDosAlloc
  1399. mov di,codeOffset GlobalDosFree
  1400. mov ax,4f3h
  1401. int 31h
  1402. ; Now that we've built up the system dir from the windows dir, set
  1403. ; the windows dir to where it should be for this user.
  1404. push es
  1405. cld
  1406. mov di,offset achTermsrvWindowsDir
  1407. cCall TermsrvGetWindowsDir,<ds, di, MaxFileLen>
  1408. or ax, ax
  1409. jz @F ; ax = 0 -> error, just leave windows dir
  1410. smov es,ds
  1411. mov cx,-1
  1412. xor ax,ax
  1413. repnz scasb
  1414. not cx
  1415. dec cx ; length of windows directory
  1416. mov lpWindowsDir.sel,ds
  1417. mov lpWindowsDir.off,offset achTermsrvWindowsDir
  1418. mov cBytesWinDir,cx
  1419. @@:
  1420. pop es
  1421. endif
  1422. ; Under win 2.11 we allowed the ":" syntax to replace the shell.
  1423. ; We no longer allow this, however to avoid messing up people
  1424. ; with batch files that have ":" in them we will strip the
  1425. ; ":" out of the command line. But we retain the :: syntax
  1426. ; for the OS/2 VM!!
  1427. ; We also do the check for the /b switch here. This puts us in "diagnostic
  1428. ; mode and we set a flag to say this. Later, we will call the DiagInit()
  1429. ; function to open the log file, etc.
  1430. push ds
  1431. cld
  1432. mov ds,topPDB
  1433. UnSetKernelDS
  1434. push ds
  1435. pop es
  1436. mov si,80h
  1437. xor ax,ax
  1438. lodsb
  1439. or al,al
  1440. jz no_colon
  1441. mov cx,ax
  1442. @@: lodsb
  1443. cmp al,' '
  1444. loopz @B
  1445. cmp al,':'
  1446. jnz no_colon
  1447. cmp byte ptr [si],':'
  1448. jz no_colon
  1449. mov byte ptr [si][-1],' '
  1450. no_colon:
  1451. cmp al,'/' ;Switch character?
  1452. je CheckSwitch ;Yes
  1453. cmp al,'-' ;Other switch character?
  1454. jne NoSwitch ;Nope.
  1455. CheckSwitch:
  1456. lodsb ;Get next char
  1457. or al,32 ;Convert to lowercase if necessary
  1458. cmp al,'b' ;Diagnostic mode?
  1459. jnz NoSwitch ;Nope
  1460. cCall DiagInit ;Initialize diagnostic mode
  1461. mov WORD PTR [si-2],2020h ;Blank out the switch
  1462. NoSwitch:
  1463. pop ds
  1464. ReSetKernelDS
  1465. ;** Reset secret flag for memory manager. Fixed segments will go
  1466. ;** >1MB after this
  1467. and fBooting, NOT 2
  1468. ;** We want to grow the SFT *before* loading the modules,
  1469. ;** not after, like was the case previous to win3.1
  1470. call GrowSFTToMax ;add to SFT chain in p mode
  1471. if 1
  1472. ; old ldinit.c
  1473. cld
  1474. push ds
  1475. smov es,ds
  1476. xor ax,ax
  1477. xor cx,cx
  1478. mov ds,topPDB
  1479. UnSetKernelDS
  1480. mov si,80h
  1481. lodsb
  1482. or al,al
  1483. jz gwaphics_done
  1484. mov cl,al
  1485. lodsb
  1486. cmp al,' '
  1487. mov al,ah
  1488. jnz gwaphics_done
  1489. lodsb
  1490. cmp al,':'
  1491. mov al,ah
  1492. jnz gwaphics_done
  1493. lodsb
  1494. cmp al,':'
  1495. mov al,ah
  1496. jnz gwaphics_done
  1497. mov di,dataOffset app_name
  1498. find_delineator:
  1499. lodsb
  1500. stosb
  1501. cmp al,' '
  1502. ja find_delineator
  1503. mov es:[di][-1],ah
  1504. mov ds:[80h],ah ; assume no arguments
  1505. jnz gwaphics_done
  1506. add cx,82h
  1507. sub cx,si
  1508. smov es,ds
  1509. mov di,80h
  1510. mov al,cl
  1511. stosb
  1512. rep movsb
  1513. gwaphics_done:
  1514. pop ds
  1515. ReSetKernelDS
  1516. or ax,ax
  1517. jz @F
  1518. mov graphics,0
  1519. @@:
  1520. else
  1521. cld
  1522. xor ax,ax
  1523. xor bx,bx
  1524. endif
  1525. jmps SlowBoot
  1526. bootfail:
  1527. mov al,1
  1528. cCall ExitKernel,<ax>
  1529. cEnd nogen
  1530. sEnd INITCODE
  1531. ;-----------------------------------------------------------------------;
  1532. ; SlowBoot ;
  1533. ; ;
  1534. ; ;
  1535. ; Arguments: ;
  1536. ; ;
  1537. ; Returns: ;
  1538. ; ;
  1539. ; Error Returns: ;
  1540. ; ;
  1541. ; Registers Preserved: ;
  1542. ; ;
  1543. ; Registers Destroyed: ;
  1544. ; ;
  1545. ; Calls: ;
  1546. ; ;
  1547. ; History: ;
  1548. ; ;
  1549. ; Sat Mar 14, 1987 05:52:22p -by- David N. Weise [davidw] ;
  1550. ; Added this nifty comment block. ;
  1551. ;-----------------------------------------------------------------------;
  1552. DataBegin INIT
  1553. BootSect db 'BOOT',0
  1554. BootFile db 'SYSTEM.INI',0
  1555. FilesCached db 'CACHEDFILEHANDLES',0
  1556. IdleSegLoad db 'LOADSEGMENTSATIDLE',0
  1557. ifdef WOW
  1558. ExitLastApp db 'CLOSEONLASTAPPEXIT',0
  1559. endif
  1560. if SHERLOCK
  1561. szGPC db 'GPCONTINUE',0
  1562. endif
  1563. szDebugSect db 'DEBUG',0
  1564. szOutputTo db 'OUTPUTTO', 0
  1565. szAux db 0 ;'AUX', 0 ; don't return a default
  1566. if KDEBUG
  1567. szKRInfo db 'KERNELINFO', 0
  1568. szKRBreak db 'KERNELBREAK', 0
  1569. szWin3Info db 'WIN3INFO', 0
  1570. szWin3Break db 'WIN3BREAK', 0
  1571. endif
  1572. BootBufLen equ 80
  1573. BootBuf db BootBufLen dup (?)
  1574. bootmods label byte
  1575. DB 'SYSTEM.DRV',0
  1576. winmods label byte
  1577. ifdef WOW
  1578. DB 'KEYBOARD.DRV',0
  1579. szAfterKeyboardDriver label byte ;Used so we can tell key driver loaded
  1580. DB 'MOUSE.DRV',0
  1581. ifdef FE_SB
  1582. szBeforeWifeMan label byte ;Used so we can tell key driver loaded
  1583. DB 'WIFEMAN.DLL', 0 ;WIFE manager has to be loaded before display driver
  1584. endif
  1585. DB 'VGA.DRV',0
  1586. DB 'SOUND.DRV',0
  1587. DB 'COMM.DRV',0
  1588. DB 'USER.EXE',0
  1589. DB 'GDI.EXE',0
  1590. ifdef FE_SB
  1591. szBeforeWinNls label byte ;Used so we can tell key driver loaded
  1592. DB 'WINNLS.DLL', 0 ;bug #112335
  1593. endif
  1594. else
  1595. DB 'KEYBOARD.DRV',0
  1596. szAfterKeyboardDriver label byte ;Used so we can tell key driver loaded
  1597. DB 'MOUSE.DRV',0
  1598. ifdef FE_SB
  1599. szBeforeWifeMan label byte ;Used so we can tell key driver loaded
  1600. DB 'WIFEMAN.DLL', 0 ;WIFE manager has to be loaded before
  1601. ;display driver
  1602. endif
  1603. DB 'DISPLAY.DRV',0
  1604. DB 'SOUND.DRV',0
  1605. DB 'COMM.DRV',0
  1606. DB 'FONTS.FON',0
  1607. DB 'OEMFONTS.FON',0 ; For Internationals use.
  1608. DB 'GDI.EXE',0
  1609. DB 'USER.EXE',0
  1610. ifdef FE_SB
  1611. szBeforeWinNls label byte ;Used so we can tell key driver loaded
  1612. DB 'WINNLS.DLL', 0
  1613. endif
  1614. endif
  1615. ifdef WOW
  1616. defapp label byte
  1617. DB 'WOWEXEC.EXE',0
  1618. else
  1619. defapp label byte
  1620. DB 'PROGMAN.EXE',0
  1621. endif
  1622. Shell label byte
  1623. DB 'WOWSHELL',0
  1624. ;** Ordinal strings for two of the Keyboard driver exports
  1625. keymodstr DB 'KEYBOARD',0
  1626. keyprocstr DB '#5',0 ; keyprocstr = AnsiToOem
  1627. keyprocstr1 DB '#6',0 ; keyprocstr = OemToAnsi
  1628. DataEnd INIT
  1629. sBegin INITCODE
  1630. assumes cs,CODE
  1631. assumes ds,nothing
  1632. assumes es,nothing
  1633. if BootTraceOn
  1634. cProc BootTraceChar,<PUBLIC,NEAR,NODATA>, <ax, dx>
  1635. parmW char
  1636. cBegin
  1637. mov dx, 3fdh
  1638. @@: in al, dx
  1639. test al, 20h
  1640. jz @B
  1641. mov ax, char
  1642. mov dx, 3f8h
  1643. out dx, al
  1644. cEnd
  1645. endif ; BootTraceOn
  1646. cProc ttywrite,<PUBLIC,NEAR,NODATA>, <ds, si>
  1647. parmD s
  1648. cBegin
  1649. ; cCall lstrlen,<s>
  1650. ; mov cx, ax
  1651. ; lds bx, s
  1652. ; mov bx,1
  1653. ; mov ah,40h
  1654. ; int 21h
  1655. lds si, s
  1656. cld
  1657. mov ah, 2
  1658. tty1:
  1659. lodsb
  1660. mov dl, al
  1661. or dl, dl
  1662. jz tty2
  1663. int 21h
  1664. jmps tty1
  1665. tty2:
  1666. cEnd
  1667. ifdef WOW
  1668. cProc LoadFail,<PUBLIC,NEAR,NODATA>, <ds,si,di,cx>
  1669. parmD s
  1670. cBegin
  1671. ;** Put Up a Dialog Box If we can't load a module
  1672. ; since szPleaseDoIt resides in protected cs we can't concat the module
  1673. ; name to it -- so we need to copy it to the stack
  1674. ;szPleaseDoIt db "Please re-install the following module to your system32
  1675. ; directory: ",13,10,9,9,0
  1676. mov di,sp ; save current stack pointer
  1677. sub sp,100h ; allocate for new concat'd string on the stack
  1678. mov si,sp ; save the start of the stack string
  1679. push ss ; copy szPleaseDoIt to the stack buffer
  1680. push si
  1681. push cs
  1682. push codeOFFSET szPleaseDoIt
  1683. call lstrcpy
  1684. push ss ; concat module name to string on stack
  1685. push si
  1686. lds cx, s ; get the module name
  1687. push ds
  1688. push cx
  1689. call lstrcat
  1690. push ss ;push finished stack string now
  1691. push si
  1692. push cs ;szMissingMod db "KERNEL: Missing 16-bit module:",0
  1693. push codeOFFSET szMissingMod ; Set Caption
  1694. push 0 ;No left button
  1695. push SEB_CLOSE + SEB_DEFBUTTON ;Button 1 style
  1696. push 0 ;No right button
  1697. externFP kSYSERRORBOX
  1698. call kSYSERRORBOX ;Put up the system message
  1699. mov sp,di ; restore sp
  1700. cEnd
  1701. else // non-WOW
  1702. cProc LoadFail,<PUBLIC,NEAR,NODATA>, <ds>
  1703. parmD s
  1704. cBegin
  1705. SetKernelDS
  1706. cCall TextMode
  1707. mov bx, dataoffset szCRLF
  1708. cCall ttywrite, dsbx
  1709. mov bx, dataoffset szCRLF
  1710. cCall ttywrite, dsbx
  1711. mov bx, dataoffset szBootLoad
  1712. cCall ttywrite, dsbx
  1713. cCall ttywrite, s
  1714. mov bx, dataoffset szCRLF
  1715. cCall ttywrite, dsbx
  1716. cEnd
  1717. endif
  1718. cProc SlowBoot,<PUBLIC,NEAR>
  1719. cBegin nogen
  1720. CheckKernelDS
  1721. ReSetKernelDS
  1722. GPPI macro sect, key, defval, file, storeit
  1723. push ds
  1724. push dataoffset sect
  1725. push ds
  1726. push dataoffset key
  1727. push defval
  1728. push ds
  1729. push dataoffset file
  1730. call GetPrivateProfileInt
  1731. ifb <storeit>
  1732. mov defval, ax
  1733. endif
  1734. endm
  1735. GPPS macro sect, key, defval, here, hereLen, file
  1736. push ds
  1737. push dataoffset sect
  1738. push ds
  1739. push dataoffset key
  1740. push ds
  1741. push dataoffset defval
  1742. push ds
  1743. push dataoffset here
  1744. push hereLen
  1745. push ds
  1746. push dataoffset file
  1747. call GetPrivateProfileString
  1748. endm
  1749. GPPS1 macro sect, key, defval, here, hereLen, file
  1750. push ds
  1751. push dataoffset sect
  1752. push ds
  1753. push key
  1754. push ds
  1755. push defval
  1756. push ds
  1757. push dataoffset here
  1758. push hereLen
  1759. push ds
  1760. push dataoffset file
  1761. call GetPrivateProfileString
  1762. endm
  1763. GPI macro sect, key, defval, storeit
  1764. push ds
  1765. push dataoffset sect
  1766. push ds
  1767. push dataoffset key
  1768. push defval
  1769. call GetProfileInt
  1770. ifb <storeit>
  1771. mov defval, ax
  1772. endif
  1773. endm
  1774. if SHERLOCK
  1775. GPI szKernel, szGPC, gpEnable
  1776. endif
  1777. if KDEBUG
  1778. ifdef DISABLE
  1779. GPPI szDebugSect, szKRInfo, _krInfoLevel, BootFile
  1780. GPPI szDebugSect, szKRBreak, _krBreakLevel, BootFile
  1781. GPPI szDebugSect, szWin3Info, _Win3InfoLevel, Bootfile
  1782. GPPI szDebugSect, szWin3Break, _Win3BreakLevel, Bootfile
  1783. endif
  1784. endif ;KDEBUG
  1785. GPPS szDebugSect, szOutputTo, szAux, BootBuf, BootBufLen, BootFile
  1786. or ax, ax
  1787. jz @F
  1788. cmp ax, BootBufLen-2
  1789. jz @F
  1790. mov ah, 3ch ; creat file (zero length)
  1791. xor cx, cx
  1792. mov dx, dataOffset BootBuf
  1793. DOSCALL
  1794. jc @F
  1795. mov bx, ax
  1796. mov ah, 3eh ; now close it
  1797. DOSCALL
  1798. jc @F
  1799. mov ax, 3d42h ; open inherit, deny none, read/write
  1800. DOSCALL
  1801. jc @F
  1802. mov bx, ax ; dup handle
  1803. mov cx, 3 ; force AUX to be this file
  1804. mov ah, 46h
  1805. DOSCALL
  1806. mov ah, 3eh ; close temp file
  1807. DOSCALL
  1808. mov wDefRIP, 'i' ; since AUX is redirected, assume Ignore RIP
  1809. @@:
  1810. GPPI BootSect, FilesCached, MAXFHCACHELEN, BootFile, nostore
  1811. cmp ax, MINFHCACHELEN ; Validate length
  1812. jae @F
  1813. mov ax, MINFHCACHELEN
  1814. @@: cmp ax, MAXFHCACHELEN
  1815. jbe @F
  1816. mov ax, MAXFHCACHELEN
  1817. @@: mov fhCacheLen, ax ; Adjust # of cached file handles
  1818. shl ax, 1
  1819. shl ax, 1
  1820. add ax, dataoffset fhCache
  1821. mov fhCacheEnd, ax
  1822. GPPI BootSect, IdleSegLoad, 1, BootFile, nostore
  1823. mov fPokeAtSegments, al
  1824. ifdef WOW
  1825. GPPI BootSect, ExitLastApp, 0, BootFile, nostore
  1826. mov fExitOnLastApp, al
  1827. endif
  1828. mov bootExecBlock.lpfcb1.off,dataOffset win_show
  1829. mov bootExecBlock.lpfcb1.sel,ds
  1830. mov es,topPDB
  1831. mov bootExecBlock.lpcmdline.off,80h
  1832. mov bootExecBlock.lpcmdline.sel,es
  1833. mov lpBootApp.off,dataOffset app_name
  1834. mov lpBootApp.sel,ds
  1835. cmp graphics,1
  1836. jnz sb1
  1837. mov lpBootApp.off,dataOffset defapp
  1838. mov lpBootApp.sel,ds
  1839. sb1: mov di,dataOffset bootMods
  1840. sbloop1:
  1841. cCall LoadNewExe,<di>
  1842. SetKernelDS es
  1843. mov cx,-1
  1844. xor ax,ax
  1845. cld
  1846. repnz scasb
  1847. cmp di,dataOffset winmods
  1848. jb sbloop1
  1849. cmp graphics,1
  1850. jz sbloop2
  1851. ; cCall InitFwdRef
  1852. jmps sb4
  1853. UnSetKernelDS es
  1854. sbloop2: ; load USER.EXE, GDI.EXE
  1855. ifdef FE_SB
  1856. ;** If we just load the fae east modules, we want to
  1857. ;** checks the system locale vale which is far east
  1858. ;** locale.
  1859. ;** If system locale is not far east, then we skip
  1860. ;** to load far east module.
  1861. cmp di,dataOffset szBeforeWifeMan
  1862. je SB_DoFarEastModule
  1863. cmp di,dataOffset szBeforeWinNls
  1864. jne SB_DoLoadModule
  1865. SB_DoFarEastModule:
  1866. cCall GetSystemDefaultLangID
  1867. ; return: ax is system locale value
  1868. cmp ax,411h
  1869. je SB_DoLoadModule
  1870. cmp ax,412h
  1871. je SB_DoLoadModule
  1872. cmp ax,404h
  1873. je SB_DoLoadModule
  1874. cmp ax,804h
  1875. je SB_DoLoadModule
  1876. cmp ax,0c04h
  1877. je SB_DoLoadModule
  1878. ; skip to next module
  1879. mov cx,-1
  1880. xor ax,ax
  1881. cld
  1882. repnz scasb
  1883. jmp SB_NotKeyboardDriver
  1884. SB_DoLoadModule:
  1885. endif
  1886. cCall LoadNewExe,<di>
  1887. push ax ; Save hInst return value
  1888. SetKernelDS es
  1889. mov cx,-1
  1890. xor ax,ax
  1891. cld
  1892. repnz scasb
  1893. pop si ; Get hInst of latest module in SI
  1894. ;** If we just loaded the keyboard driver, we want to
  1895. ;** point our explicit link variables to the AnsiToOem and
  1896. ;** OemToAnsi functions so OpenFile can use them for the
  1897. ;** remaining boot modules
  1898. cmp di,dataOffset szAfterKeyboardDriver
  1899. jne SB_NotKeyboardDriver
  1900. push ds ; Save regs we care about
  1901. push di
  1902. regptr pStr,ds,bx
  1903. mov bx,dataOffset keyprocstr
  1904. cCall GetProcAddress,<si,pStr>
  1905. mov pKeyProc.off,ax
  1906. mov pKeyProc.sel,dx
  1907. mov bx,dataOffset keyprocstr1
  1908. cCall GetProcAddress,<si,pStr>
  1909. mov pKeyProc1.off,ax
  1910. mov pKeyProc1.sel,dx
  1911. pop di
  1912. pop ds
  1913. SB_NotKeyboardDriver:
  1914. cmp di,dataOffset defapp
  1915. jb sbloop2
  1916. ; OPTIMIZE BEGIN
  1917. ; OPTIMIZE END
  1918. sb4:
  1919. cCall InitFwdRef ; Gets stuff we can't dynalink to
  1920. cCall InternalEnableDOS ; Enable int21 hooks
  1921. ;sb4:
  1922. call check_TEMP
  1923. ; Get the shell name from SYSTEM.INI
  1924. mov ax,dataoffset Shell
  1925. GPPS1 BootSect, ax, lpBootApp.off, BootBuf, BootBufLen, BootFile
  1926. ;** Here we need to convert the command line to ANSI
  1927. cmp WORD PTR pKeyProc1[2],0 ; Paranoia...
  1928. jz @F
  1929. ;** Zero terminate the string before passing to OemToAnsi
  1930. mov es,bootExecBlock.lpcmdline.sel
  1931. mov bl,es:[80h] ; Get length byte
  1932. xor bh,bh
  1933. xchg BYTE PTR es:[bx+81h],bh ; Replace terminator char with zero
  1934. ;** Call the keyboard driver
  1935. push es ; Save the seg reg
  1936. push bx ; Save offset and char saved
  1937. push es
  1938. push 81h ; Always starts here (fixed offset)
  1939. push es
  1940. push 81h
  1941. cCall [pKeyProc1] ; Call OemToAnsi in keyboard driver
  1942. pop bx ; Get saved info
  1943. pop es
  1944. mov al,bh ; Saved char from string
  1945. xor bh,bh
  1946. mov BYTE PTR es:[bx+81h],al ; Replace the character
  1947. @@:
  1948. mov ax,dataOffset bootExecBlock
  1949. regptr dsax,ds,ax
  1950. cmp graphics,1
  1951. jz @F
  1952. cCall LoadModule,<lpBootApp,dsax>
  1953. jmps asdf
  1954. @@: cCall FlushCachedFileHandle,<hUser> ; in case 100 fonts are loaded
  1955. farptr lpBootBuf,ds,di
  1956. mov di, dataoffset BootBuf
  1957. cCall LoadModule,<lpBootBuf,dsax>
  1958. asdf:
  1959. cmp ax,32
  1960. jbe sb6
  1961. cCall GetExePtr,<ax>
  1962. mov hShell, ax
  1963. jmp bootdone
  1964. sb6:
  1965. ReSetKernelDS
  1966. les bx, lpBootApp
  1967. krDebugOut DEB_ERROR, "BOOT: unable to load @ES:BX"
  1968. cCall LoadFail,<lpBootApp>
  1969. ; cmp pDisableProc.sel,0 ; Is there a USER around yet?
  1970. ; jz @F
  1971. ; cCall pDisableProc
  1972. ;@@:
  1973. jmp bootfail
  1974. UnSetKernelDS
  1975. cEnd nogen
  1976. ;------------------------------------------------------------------------
  1977. assumes ds,nothing
  1978. assumes es,nothing
  1979. cProc LoadNewExe,<PUBLIC,NEAR>,<si,di>
  1980. parmW pname
  1981. cBegin
  1982. farptr lpparm,ax,ax
  1983. farptr lpBootBuf,ds,di
  1984. mov di, dataoffset BootBuf
  1985. CheckKernelDS
  1986. ReSetKernelDS
  1987. ifdef WOW
  1988. ; ATM Alters system.ini registry boot section to load its own SYSTEM.DRV
  1989. ; However on WOW this causes us to fail to load correctly. Also we
  1990. ; would be hard pushed to support the current 16 bit ATM since it relies
  1991. ; on internals of 16 bit GDI which are not present in WOW.
  1992. ; For this Beta I'm going to ignore the bootsection of the registry
  1993. ; when loading drivers and thus ATM will not get installed.
  1994. ; At least the user will be protected from not being able to boot WOW
  1995. ; BUGBUG - Consider
  1996. ; MattFe Oct9 92
  1997. mov di,pname
  1998. else
  1999. GPPS1 BootSect, pname, pname, BootBuf, BootBufLen, BootFile
  2000. endif
  2001. xor ax,ax
  2002. cCall LoadModule,<lpBootBuf,lpparm>
  2003. cmp ax,2
  2004. jne lne1
  2005. krDebugOut DEB_ERROR, "Can't find @DS:DI"
  2006. ; kerror ERR_LDBOOT,<BOOT: Unable to find file - >,ds,di
  2007. jmps lne4
  2008. lne1:
  2009. cmp ax,11
  2010. jne lne2
  2011. krDebugOut DEB_ERROR, "Invalid EXE file @DS:DI"
  2012. ; kerror ERR_LDBOOT,<BOOT: Invalid .EXE file - >,ds,di
  2013. jmps lne4
  2014. lne2:
  2015. cmp ax,15
  2016. jnz lne3
  2017. krDebugOut DEB_ERROR, "Invalid protect mode EXE file @DS:DI"
  2018. ; kerror ERR_LDBOOT,<BOOT: Invalid protect mode .EXE file - >,ds,di
  2019. jmps lne4
  2020. lne3:
  2021. cmp ax, 4
  2022. jne lne3a
  2023. krDebugOut DEB_ERROR, "Out of files (set FILES=30 in CONFIG.SYS) @DS:DI"
  2024. ; kerror ERR_LDFILES,<BOOT: Out of files, (set FILES=30 in CONFIG.SYS) loading - >,ds,di
  2025. jmps lne4
  2026. lne3a:
  2027. cmp ax, 32
  2028. jae lnex
  2029. NoLoadIt:
  2030. ; kerror ERR_LDBOOT,<BOOT: Unable to load - >,ds,pname
  2031. krDebugOut DEB_ERROR, "Unable to load @DS:DI (#ax)"
  2032. lne4:
  2033. cCall LoadFail,dsdi
  2034. mov ax,1
  2035. cCall ExitKernel,<ax>
  2036. lnex:
  2037. UnSetKernelDS
  2038. cEnd
  2039. sEnd INITCODE
  2040. ;-----------------------------------------------------------------------;
  2041. ; BootDone ;
  2042. ; ;
  2043. ; Boot is done when all of modules are loaded. Here we do a bit of ;
  2044. ; clean up, such as validating code segments, initing free memory to ;
  2045. ; CCCC, freeing up the fake TDB, and finally reallocating the init ;
  2046. ; code away. ;
  2047. ; ;
  2048. ; Arguments: ;
  2049. ; none ;
  2050. ; ;
  2051. ; Returns: ;
  2052. ; nothing ;
  2053. ; ;
  2054. ; Error Returns: ;
  2055. ; ;
  2056. ; Registers Preserved: ;
  2057. ; ;
  2058. ; Registers Destroyed: ;
  2059. ; all ;
  2060. ; ;
  2061. ; Calls: ;
  2062. ; ;
  2063. ; History: ;
  2064. ; ;
  2065. ; Wed Apr 15, 1987 08:53:23p -by- David N. Weise [davidw] ;
  2066. ; Added this nifty comment block. ;
  2067. ;-----------------------------------------------------------------------;
  2068. DataBegin INIT
  2069. externB beg_initdata
  2070. szKernel DB 'KERNEL',0
  2071. szWindows DB 'WINDOWS',0
  2072. if KDEBUG
  2073. szDebugOptions DB 'DebugOptions',0
  2074. szDebugFilter DB 'DebugFilter',0
  2075. szChecksum DB 'EnableSegmentChecksum',0
  2076. szSweepFreak DB 'LRUSweepFrequency',0
  2077. sz80x87 DB 'NoUse80x87',0
  2078. szFastFP DB 'FastFP', 0
  2079. externW DebugOptions
  2080. externW DebugFilter
  2081. ifdef DISABLE
  2082. externB fLoadTrace
  2083. endif
  2084. endif ; KDEBUG
  2085. ifdef SDEBUG
  2086. szEMSDebug DB 'EnableEMSDebug',0
  2087. endif
  2088. szgrab_386 DB '386GRABBER',0
  2089. if SWAPPRO
  2090. szSwapPro DB 'SwapProfile',0
  2091. szSwapFile DB 'SWAPPRO.DAT',0
  2092. endif
  2093. DataEnd INIT
  2094. sBegin INITCODE
  2095. assumes cs,CODE
  2096. assumes ds,nothing
  2097. assumes es,nothing
  2098. externB beg_initcode
  2099. cProc BootDone,<PUBLIC,NEAR>
  2100. cBegin nogen
  2101. SetKernelDS
  2102. if KDEBUG
  2103. ; Get win.ini [Windows] DebugOptions
  2104. GPI szWindows, szDebugOptions, DebugOptions
  2105. ; Get win.ini [Windows] DebugFilter
  2106. GPI szWindows, szDebugFilter, DebugFilter
  2107. ; Now set various internal flags based on DebugOptions
  2108. xor ax,ax
  2109. test DebugOptions,DBO_CHECKHEAP
  2110. jz @F
  2111. inc ax
  2112. @@:
  2113. mov es,pGlobalHeap
  2114. mov es:[hi_check],ax
  2115. test DebugOptions,DBO_CHECKFREE
  2116. jz @F
  2117. or Kernel_flags,kf_check_free
  2118. @@:
  2119. ifdef DISABLE
  2120. xor ax,ax
  2121. test DebugOptions,DBO_LOADTRACE
  2122. jz @F
  2123. mov fLoadTrace, al
  2124. @@:
  2125. endif ; DISABLE
  2126. test DebugOptions,DBO_DISABLEGPTRAPPING
  2127. jz wants_trapping
  2128. mov ax,0203h ; Reset GP fault.
  2129. mov bl,0Dh
  2130. mov cx,prevInt0Dproc.sel
  2131. mov dx,prevInt0Dproc.off
  2132. int 31h
  2133. mov ax,0203h ; Reset invalid op-code exception.
  2134. mov bl,06h
  2135. mov cx,prevIntx6proc.sel
  2136. mov dx,prevIntx6proc.off
  2137. int 31h
  2138. mov ax,0203h ; Reset page fault.
  2139. mov bl,0Eh
  2140. mov cx,prevInt0Eproc.sel
  2141. mov dx,prevInt0Eproc.off
  2142. int 31h
  2143. wants_trapping:
  2144. if SWAPPRO
  2145. GPI szKernel, szSwapPro, 1, nostore
  2146. mov fSwapPro, al
  2147. mov bx,TopPDB
  2148. mov ah,50h
  2149. pushf
  2150. FCLI
  2151. call prevInt21Proc
  2152. lea dx,szSwapFile
  2153. xor cx,cx
  2154. mov ah,3Ch
  2155. pushf
  2156. FCLI
  2157. call prevInt21Proc
  2158. mov hSwapPro,ax
  2159. mov bx,cur_dos_pdb
  2160. mov ah,50h
  2161. pushf
  2162. FCLI
  2163. call prevInt21Proc
  2164. endif
  2165. GPI szKernel, szChecksum, 1, nostore
  2166. mov fChkSum,al
  2167. GPI szKernel, sz80x87, 0, nostore
  2168. or ax,ax
  2169. jz wants_8087
  2170. mov f8087,0
  2171. and WinFlags,NOT WF1_80x87 ;Turn off corresponding WinFlags bit
  2172. wants_8087:
  2173. GPI szKernel, szFastFP, 1, nostore
  2174. mov fastFP, al
  2175. GPI szKernel, szSweepFreak, 500, nostore
  2176. else
  2177. mov ax, 500
  2178. endif ; KDEBUG
  2179. ifdef WOW
  2180. xor ax,ax
  2181. endif
  2182. or ax,ax
  2183. jz nolrusweep
  2184. test WinFlags[1], WF1_PAGING
  2185. jnz short nolrusweep
  2186. mov bx,codeOffset lrusweep
  2187. regptr csbx,cs,bx
  2188. xor dx,dx
  2189. cCall pTimerProc,<dx,ax,csbx>
  2190. nolrusweep:
  2191. if SDEBUG
  2192. GPI szKernel, szEMSDebug, 0, nostore
  2193. or ax,ax
  2194. jz no_EMS_debug_wanted
  2195. or Kernel_flags,kf_EMS_debug
  2196. no_EMS_debug_wanted:
  2197. endif
  2198. if LDCHKSUM
  2199. cCall ValidateCodeSegments
  2200. endif
  2201. if KDEBUG
  2202. mov fCheckFree,0
  2203. endif
  2204. ; Get the shell name from SYSTEM.INI
  2205. GPPS BootSect, szgrab_386, szgrab_386, grab_name, 128, BootFile
  2206. mov es,curTDB ; ES = TDB of fake task
  2207. push es
  2208. cCall DeleteTask,<es> ; Flush bogus task
  2209. pop es
  2210. xor dx,dx
  2211. mov es:[TDB_sig],dx ; Clear signature word.
  2212. mov curTDB,dx ; Let someone else be current task
  2213. ; switch to the temp stack since we're about to Realloc the present one away
  2214. mov ax, ss
  2215. FCLI
  2216. SetKernelDS ss
  2217. mov sp,dataOffset gmove_stack
  2218. FSTI
  2219. cCall free_sel,<ax>
  2220. ; Shrink DGROUP down to its post initialization size
  2221. mov cx,dataOFFSET beg_initdata ; don't need init data
  2222. ; dx doubles as high word and specifies fixed
  2223. ; reallocation
  2224. xor dx,dx
  2225. cCall IGlobalReAlloc,<ds,dx,cx,dx> ; Realloc DGROUP
  2226. xor dx,dx
  2227. ; Now shrink the resident CODE segment
  2228. mov cx,codeOFFSET beg_initcode ; dont need init code
  2229. ; cCall IGlobalReAlloc,<cs,dxcx,dx>
  2230. ; jmps BootSchedule ; Jump to schedule first app
  2231. push cs ; Arguments to GlobalReAlloc
  2232. push dx
  2233. push cx
  2234. push dx
  2235. push cs ; Where GlobalReAlloc will eventually return
  2236. mov ax,codeOFFSET BootSchedule
  2237. push ax
  2238. jmp near ptr IGlobalReAlloc ; Jump to GlobalReAlloc
  2239. UnSetKernelDS ss
  2240. UnSetKernelDS
  2241. cEnd nogen
  2242. ;-----------------------------------------------------------------------;
  2243. ; check_TEMP
  2244. ;
  2245. ; If the environment variable TEMP points to garbage then GetTempFile
  2246. ; screws up. We fix it by wiping out the TEMP string if it points
  2247. ; to garbage.
  2248. ;
  2249. ; Entry:
  2250. ; none
  2251. ;
  2252. ; Returns:
  2253. ;
  2254. ; Registers Preserved:
  2255. ; all
  2256. ;
  2257. ; History:
  2258. ; Thu 11-May-1989 16:39:34 -by- David N. Weise [davidw]
  2259. ; Wrote it.
  2260. ;-----------------------------------------------------------------------;
  2261. assumes ds,nothing
  2262. assumes es,nothing
  2263. cProc check_TEMP,<PUBLIC,NEAR>,<ds,es>
  2264. ifdef FE_SB
  2265. localW pMyBuf
  2266. endif
  2267. cBegin
  2268. pusha
  2269. SetKernelDS
  2270. sub sp,130
  2271. mov di,sp
  2272. CheckKernelDS
  2273. mov ds,TopPDB
  2274. UnSetKernelDS
  2275. mov ds,ds:[PDB_environ]
  2276. xor si, si ; assume DS:SI points to environment
  2277. cCall GetTempDrive,<si>
  2278. smov es,ss
  2279. cld
  2280. stosw
  2281. ifdef FE_SB
  2282. mov pMyBuf,di ; save string offset(exclude D:)
  2283. endif
  2284. stmp2:
  2285. lodsw
  2286. or al,al ; no more enviroment
  2287. ifdef FE_SB
  2288. jnz @F ; I hate this
  2289. jmp stmpNo1
  2290. @@:
  2291. else
  2292. jz stmpNo1
  2293. endif
  2294. cmp ax,'ET' ; Look for TEMP=
  2295. jne stmp3
  2296. lodsw
  2297. cmp ax,'PM'
  2298. jne stmp3
  2299. lodsb
  2300. cmp al,'='
  2301. je stmpYes
  2302. stmp3: lodsb
  2303. or al,al
  2304. jnz stmp3
  2305. jmp stmp2
  2306. stmpYes:
  2307. push si ; save pointer to TEMP
  2308. push ds
  2309. push si ; spaces are legal, but they
  2310. lookForSpace: ; confuse too many apps, so
  2311. lodsb ; we treat them as illegal
  2312. cmp al, ' '
  2313. jz stmpFoundSpace
  2314. or al, al
  2315. jnz lookForSpace
  2316. pop si
  2317. cmp byte ptr [si+1],':'
  2318. jne stmpnodrive
  2319. and byte ptr [si],NOT 20h ; springboard needs this!
  2320. dec di
  2321. dec di
  2322. stmpnodrive:
  2323. lodsb
  2324. or al,al
  2325. jz stmpNo
  2326. stosb
  2327. jmp stmpnodrive
  2328. stmpNo:
  2329. mov ax,'~\'
  2330. cmp es:[di-1],al ; does it already end in \
  2331. jnz stmpNoF ; no, just store it
  2332. dec di ; override it
  2333. ifdef FE_SB
  2334. push si
  2335. mov si,pMyBuf
  2336. call FarMyIsDBCSTrailByte ;is that '\' a DBCS trailing byte?
  2337. cmc
  2338. adc di,0 ;skip it if yes.
  2339. pop si
  2340. endif
  2341. stmpNoF:
  2342. stosw
  2343. xor ax,ax
  2344. stosb ; zero terminate it
  2345. pop es ; recover pointer to TEMP
  2346. pop di
  2347. smov ds,ss
  2348. mov dx,sp
  2349. mov ax,5B00h
  2350. xor cx,cx
  2351. DOSCALL
  2352. jnc stmpClose
  2353. cmp al,80 ; Did we fail because the file
  2354. jz stmpNo1 ; already exists?
  2355. stmpNukeIt:
  2356. sub di,5 ; Get the TEMP= part.
  2357. @@: mov al,'x'
  2358. xchg al,es:[di]
  2359. inc di
  2360. or al,al
  2361. jnz @B
  2362. mov byte ptr es:[di-1],0
  2363. jmps stmpNo1
  2364. stmpClose:
  2365. mov bx,ax
  2366. mov ah,3Eh
  2367. DOSCALL
  2368. mov ah,41h
  2369. DOSCALL
  2370. stmpNo1:
  2371. add sp,130
  2372. popa
  2373. cEnd
  2374. stmpFoundSpace:
  2375. pop si
  2376. pop es
  2377. pop di
  2378. jmps stmpNukeIt
  2379. ;-----------------------------------------------------------------------;
  2380. ; get_windir
  2381. ;
  2382. ; Get a pointer to the 'windows' directory.
  2383. ;
  2384. ; Entry:
  2385. ; DS => environment string
  2386. ;
  2387. ; Returns:
  2388. ; CX = length of string
  2389. ; DI => WFP of 'windows' directory
  2390. ;
  2391. ; Registers Preserved:
  2392. ; all
  2393. ;
  2394. ; History:
  2395. ; Mon 16-Oct-1989 23:17:23 -by- David N. Weise [davidw]
  2396. ; Wrote it!
  2397. ;-----------------------------------------------------------------------;
  2398. assumes ds,nothing
  2399. assumes es,nothing
  2400. ifdef WOW
  2401. ;-----------------------------------------------------------------------;
  2402. ; original get_windir looks for the environment variable 'windir' (all
  2403. ; lowercase) to set the 'windows' directory.
  2404. ;
  2405. ; On NT the equivalent environment variable is 'SystemRoot' (all
  2406. ; uppercase). Hence the code is different.
  2407. ;
  2408. ; - nanduri
  2409. ;
  2410. ; There are some customers that used the undocumented trick on win31
  2411. ; of moving windir to some network location by putting win.com there.
  2412. ; The result would be that the "Windows Directory" would point
  2413. ; to the network location, and the system directory would be local.
  2414. ; Currently, the way WINDIR is supported involves hacks in a couple
  2415. ; of different places. What would be best is if you could do a
  2416. ; "set windir=xxxx" in your autoexec.nt and we would look for windir
  2417. ; here and we would code it to emulate win31 behavior. However, that's
  2418. ; broken right now, and windir is only regenerated after krnlx86.exe
  2419. ; has finished booting. So the approach taken here is to look for
  2420. ; a new environment variable called win16dir, and if it exists, make
  2421. ; the windows directory point to it. Systemroot is still used to
  2422. ; generate the system directory.
  2423. ;
  2424. ; We want to allow NT to be installed into a directory with a long
  2425. ; name, so we use GetShortPathName on the directory we get from
  2426. ; either SystemRoot or Win16Dir variables.
  2427. ; -- DaveHart 9-Feb-96
  2428. ;-----------------------------------------------------------------------;
  2429. szSystemRoot DB 'SYSTEMROOT=',0
  2430. szWin16Dir DB 'WIN16DIR=',0
  2431. cProc get_windir,<PUBLIC,NEAR>
  2432. cBegin nogen
  2433. push es
  2434. mov ax, cs ; the string is in 'cs', see above
  2435. mov es, ax
  2436. mov di, codeoffset szSystemRoot
  2437. call get_env_var_ptr
  2438. push dx
  2439. mov dx, ds
  2440. mov es, dx
  2441. SetKernelDS
  2442. mov si, dataoffset achRealWindowsDir
  2443. regptr esdi,es,di
  2444. regptr dssi,ds,si
  2445. mov cx, WINDIR_BUFSIZE
  2446. push dx
  2447. cCall GetShortPathName, <esdi, dssi, cx>
  2448. pop dx
  2449. mov cbRealWindowsDir,ax
  2450. mov ds, dx ;restore ds
  2451. pop dx
  2452. assumes ds,nothing
  2453. push cx
  2454. push di
  2455. mov ax, cs ; the string is in 'cs', see above
  2456. mov es, ax
  2457. mov di, codeoffset szWin16Dir
  2458. call get_env_var_ptr
  2459. or di, di ;does win16dir exist?
  2460. jz gw_not
  2461. add sp, 4 ;throw away systemroot
  2462. jmp short gw_cont
  2463. gw_not:
  2464. pop di
  2465. pop cx
  2466. gw_cont:
  2467. ; Now ds:di points to the Windows directory string in
  2468. ; the environment block. It may be a long pathname,
  2469. ; so fix it up.
  2470. smov es, ds
  2471. SetKernelDS
  2472. mov si, dataoffset achWindowsDir
  2473. regptr esdi,es,di
  2474. regptr dssi,ds,si
  2475. mov cx, WINDIR_BUFSIZE
  2476. cCall GetShortPathName, <esdi, dssi, cx>
  2477. mov cx, ax
  2478. smov ds, es
  2479. assumes ds,nothing
  2480. pop es
  2481. ret
  2482. cEnd nogen
  2483. cProc get_env_var_ptr,<PUBLIC,NEAR>
  2484. cBegin nogen
  2485. cld
  2486. push si
  2487. xor si,si
  2488. push di
  2489. mov cx,-1
  2490. xor ax,ax
  2491. repnz scasb
  2492. not cx
  2493. dec cx ; length of szSystemRoot
  2494. pop di
  2495. gw_cmp:
  2496. mov al, [si]
  2497. or al, al
  2498. jz gw_exit
  2499. push di
  2500. push cx
  2501. repz cmpsb ; compare the inputstring with szSystemRoot
  2502. pop cx
  2503. pop di
  2504. jnz gw_next ; not szSystemRoot
  2505. xor cx,cx ; yes szSystemRoot, cx=0 indicates so
  2506. mov di,si
  2507. gw_next:
  2508. lodsb
  2509. or al,al
  2510. jnz gw_next ; skip to the terminating NULL.
  2511. or cx,cx ; cx==0 implies... found szSystemRoot
  2512. jnz gw_cmp ; compare with the next environment string
  2513. mov cx,si ; here if found szSystemRoot.
  2514. sub cx,di
  2515. mov ax,di
  2516. dec cx
  2517. gw_exit:
  2518. mov di,ax
  2519. pop si
  2520. ret
  2521. cEnd nogen
  2522. ;-----------------------------------------------------------------------;
  2523. ; original get_windir is within the 'else' 'endif' block
  2524. ;
  2525. ;-----------------------------------------------------------------------;
  2526. else
  2527. cProc get_windir,<PUBLIC,NEAR>
  2528. cBegin nogen
  2529. cld
  2530. push si
  2531. xor di,di
  2532. xor si,si
  2533. gw: lodsw
  2534. or al,al ; no more enviroment
  2535. jz gw_exit
  2536. cmp ax,'iw' ; Look for windir=
  2537. jne @F
  2538. lodsw
  2539. cmp ax,'dn'
  2540. jne @F
  2541. lodsw
  2542. cmp ax,'ri'
  2543. jne @F
  2544. lodsb
  2545. cmp al,'='
  2546. je gw_got_it
  2547. @@: lodsb
  2548. or al,al
  2549. jnz @B
  2550. jmp gw
  2551. gw_got_it:
  2552. mov di,si
  2553. @@: lodsb
  2554. or al,al
  2555. jnz @B
  2556. mov cx,si
  2557. sub cx,di
  2558. dec cx
  2559. gw_exit:
  2560. pop si
  2561. ret
  2562. cEnd nogen
  2563. endif
  2564. sEnd INITCODE
  2565. ;------------------------------------------------------------------------
  2566. sBegin STACK
  2567. ; Boot TDB
  2568. boottdb equ this byte
  2569. DB SIZE TDB dup (0)
  2570. ; do a clumsy paragraph alignment
  2571. rept 16
  2572. if ($ - boottdb) and 0Fh
  2573. db 0
  2574. endif
  2575. endm
  2576. ; Dummy arena entry so boot SS looks like a valid object
  2577. DB 'M'
  2578. DW -1
  2579. DW (BOOTSTACKSIZE + 31)/16
  2580. DB 0
  2581. DW 5 DUP (0)
  2582. ; Another in case we have to tweek the low order bit of SS
  2583. DB 'M'
  2584. DW -1
  2585. DW (BOOTSTACKSIZE + 15)/16
  2586. DB 0
  2587. DW 5 DUP (0)
  2588. ; Boot stack
  2589. stackbottom equ this word
  2590. DB BOOTSTACKSIZE DUP (0)
  2591. stacktop equ this word
  2592. DW -1
  2593. sEnd STACK
  2594. end BootStrap