Source code of Windows XP (NT5)
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.

2318 lines
67 KiB

  1. PAGE ,132
  2. TITLE DXBOOT.ASM -- Dos Extender Startup Code
  3. ; Copyright (c) Microsoft Corporation 1988-1991. All Rights Reserved.
  4. ;****************************************************************
  5. ;* *
  6. ;* DXBOOT.ASM - Dos Extender Startup Code *
  7. ;* *
  8. ;****************************************************************
  9. ;* *
  10. ;* Module Description: *
  11. ;* *
  12. ;* This module contains real mode initialization code that *
  13. ;* initializes the dos extender itself. This includes *
  14. ;* allocating and initializing the descriptor tables, and *
  15. ;* relocating the dos extender for protected mode operation. *
  16. ;* *
  17. ;****************************************************************
  18. ;* Revision History: *
  19. ;* *
  20. ;* 01/29/92 mattfe Build for MIPS *
  21. ;* 12/19/90 amitc NetHeapSize default made 4k from 8k *
  22. ;* 12/03/90 amitc Added support for 'Win30CommDriver' switch *
  23. ; in system.ini *
  24. ;* 10/09/90 earleh split LDT from GDT and reduced XMS handles *
  25. ;* needed to boot program to 1 *
  26. ;* 08/08/90 earleh DOSX and client privilege ring determined *
  27. ;* by equate in pmdefs.inc *
  28. ;* 05/07/90 jimmat Started VCPI related changes. *
  29. ;* 04/09/90 jimmat Detect if on 286 & 287 installed. *
  30. ;* 04/02/90 jimmat Added PM Int 70h handler. *
  31. ;* 09/27/89 jimmat Changes to use FindFile to locate child *
  32. ;* program. *
  33. ;* 08/29/89 jimmat Now hooks real mode Int 2Fh chain. *
  34. ;* 08/20/89 jimmat Removed A20 code since HIMEM version 2.07 *
  35. ;* now works properly across processor resets. *
  36. ;* 07/28/89 jimmat Int PM Int 30h & 41h to be ignored, not *
  37. ;* reflected to real mode. *
  38. ;* 07/14/89 jimmat Added call to EMMDisable *
  39. ;* 06/16/89 jimmat Ifdef'd combined DOSX/child .EXE code *
  40. ;* 05/22/89 jimmat Added Int 13h/25h/26h/67h hooks. *
  41. ;* 05/18/89 jimmat Added setting of real mode Int 30h hook. *
  42. ;* 03/31/89 jimmat Added Priv Level to selectors during *
  43. ;* relocation and removed some dead code. *
  44. ;* 03/15/89 jimmat Added INT 31h hook *
  45. ;* 03/11/89 jimmat Added support for TSS & LDT & ring 1 *
  46. ;* 03/07/89 jimmat Converted to use WDEB386 debugger *
  47. ;* 02/25/89 (GeneA): added support for combined exe file where *
  48. ;* the Dos Extender and the child reside in the same exe *
  49. ;* file. *
  50. ;* 02/17/89 (GeneA): fixed error handling code during init. *
  51. ;* 02/14/89 (GeneA): added initialization of INT15h vector, *
  52. ;* and changed segment limit of BIOS_CODE segment to *
  53. ;* 64k. *
  54. ;* 02/14/89 (GeneA): added code to copy protected mode code *
  55. ;* segment up into extended memory. Also code to allocate *
  56. ;* and copy GDT and IDT in extended memory. *
  57. ;* 01/31/89 (GeneA): reorganization of code. This module now *
  58. ;* contains only code for initializing the Dos Extender *
  59. ;* itself. *
  60. ;* 01/25/89 (GeneA): moved code for loading and relocating *
  61. ;* the child program here from dxinit.asm *
  62. ;* 01/24/89 (Genea): removed routines for hooking into real *
  63. ;* mode int 2Fh. (part of removing real mode int 2Fh *
  64. ;* interface from the dos extender). *
  65. ;* 12/13/88 (GeneA): created by moving code from DXINIT.ASM *
  66. ;* *
  67. ;****************************************************************
  68. .286p
  69. .287
  70. ; -------------------------------------------------------
  71. ; INCLUDE FILE DEFINITIONS
  72. ; -------------------------------------------------------
  73. .xlist
  74. .sall
  75. include segdefs.inc
  76. include gendefs.inc
  77. include pmdefs.inc
  78. include dpmi.inc
  79. ifdef WOW_x86
  80. include vdmtib.inc
  81. endif
  82. include intmac.inc
  83. include dbgsvc.inc
  84. .list
  85. ; -------------------------------------------------------
  86. ; GENERAL SYMBOL DEFINITIONS
  87. ; -------------------------------------------------------
  88. ;
  89. ; This structure defines the format of the EXE file header.
  90. EXEHDR struc
  91. idExeFile dw ? ;magic number to identify EXE file
  92. cbLastPage dw ? ;number of bytes in last page of the file
  93. crgbFileLen dw ? ;number of 512 byte pages in the file
  94. clpRelocLen dw ? ;number of relocation entries in the table
  95. cparHdrSize dw ? ;number of 16 byte paragraphs in header
  96. cparMinAlloc dw ?
  97. cparMaxAlloc dw ?
  98. segStackInit dw ? ;initial stack segment
  99. offStackInit dw ? ;initial stack pointer
  100. wCheckSum dw ?
  101. offCodeInit dw ? ;initial program counter
  102. segCodeInit dw ? ;initial code segment
  103. wRelocOffset dw ? ;byte offset of relocation table
  104. idOverlay dw ? ;overlay number
  105. EXEHDR ends
  106. ;
  107. ; This structure defines the parameter block to the XMS driver block
  108. ; move function.
  109. XMSMOVE struc
  110. cbxmsLen dd ? ;length of memory block
  111. hxmsSource dw ? ;XMS source block handle
  112. oxmsSource dd ? ;source offset
  113. hxmsDest dw ? ;XMS destination block handle
  114. oxmsDest dd ? ;destination offset
  115. XMSMOVE ends
  116. NOP_OPCODE equ 090h ; NO-OP opcode
  117. IRET_OPCODE equ 0CFh ; IRET opcode
  118. FAR_JMP_OPCODE equ 0EAh ; JMP FAR opcode
  119. SHORT_JMP_OPCODE equ 0EBh ; JMP SHORT opcode
  120. ; -------------------------------------------------------
  121. ; EXTERNAL SYMBOL DEFINITIONS
  122. ; -------------------------------------------------------
  123. extrn PMIntr31:NEAR
  124. extrn PMIntr13:NEAR
  125. extrn PMIntr19:NEAR
  126. extrn PMIntr28:NEAR
  127. extrn PMIntr25:NEAR
  128. extrn PMIntr26:NEAR
  129. extrn PMIntr4B:NEAR
  130. extrn PMIntrDos:NEAR
  131. extrn PMIntrMisc:NEAR
  132. extrn PMIntrVideo:NEAR
  133. extrn PMIntrMouse:NEAR
  134. extrn PMIntrIgnore:NEAR
  135. extrn PMIntrEntryVector:NEAR
  136. extrn PMFaultEntryVector:NEAR
  137. extrn ReadINIFile:NEAR
  138. ifdef NEC_98 ;
  139. extrn PMIntrSound:NEAR ; for Sound Bios
  140. extrn PMIntrExDos:NEAR ; for Extend Dos Function
  141. extrn PMIntr11dummy:NEAR
  142. extrn PMIntrPrinter:NEAR
  143. extrn PMIntrCalTi:NEAR
  144. extrn PMIntrGraph:NEAR
  145. endif ;NEC_98 ;
  146. extrn EMMDisable:NEAR
  147. extrn FindFIle:NEAR
  148. ifdef WOW_x86
  149. extrn NpxExceptionHandler:near
  150. extrn EndNpxExceptionHandler:near
  151. endif
  152. extrn RmUnsimulateProc:FAR
  153. extrn PmUnsimulateProc:FAR
  154. extrn PMFaultHandlerIRET:NEAR
  155. extrn PMFaultHandlerIRETD:NEAR
  156. extrn PMIntHandlerIRET:NEAR
  157. extrn PMIntHandlerIRETD:NEAR
  158. extrn PMDosxIret:NEAR
  159. extrn PMDosxIretd:NEAR
  160. extrn RMCallBackBop:FAR
  161. extrn RMtoPMReflector:FAR
  162. extrn RmSaveRestoreState:far
  163. extrn PmSaveRestoreState:far
  164. extrn RmRawModeSwitch:far
  165. extrn PmRawModeSwitch:far
  166. extrn DPMI_MsDos_API:far
  167. extrn VCD_PM_Svc_Call:far
  168. extrn XmsControl:far
  169. extrn HungAppExit:far
  170. DXPMCODE segment
  171. extrn CodeEndPM:NEAR
  172. externFP NSetSegmentDscr
  173. DXPMCODE ends
  174. ; -------------------------------------------------------
  175. ; DATA SEGMENT DEFINITIONS
  176. ; -------------------------------------------------------
  177. DXDATA segment
  178. extrn selGDT:WORD
  179. extrn segGDT:WORD
  180. extrn selIDT:WORD
  181. extrn segIDT:WORD
  182. extrn bpGDT:FWORD
  183. extrn bpIDT:FWORD
  184. extrn sysTSS:WORD
  185. extrn segPSP:WORD
  186. extrn selPSP:WORD
  187. extrn hmemDOSX:WORD
  188. extrn f286_287:BYTE
  189. extrn bpRmIVT:FWORD
  190. extrn fhExeFile:WORD
  191. extrn idCpuType:WORD
  192. extrn cdscGDTMax:WORD
  193. extrn rgbXfrBuf0:BYTE
  194. extrn rgbXfrBuf1:BYTE
  195. extrn clpRelocItem:WORD
  196. extrn plpRelocItem:WORD
  197. extrn lpfnXMSFunc:DWORD
  198. ifdef NEC_98 ;
  199. extrn fPCH98:BYTE ; PC-H98 flag
  200. extrn fNHmode:BYTE ; NHmode flag
  201. endif ;NEC_98 ;
  202. extrn lpfnUserMouseHandler:DWORD
  203. extrn fUsingHMA:BYTE
  204. ifdef WOW_x86
  205. extrn rgwWowStack:word
  206. extrn FastBop:fword
  207. endif
  208. extrn pbHwIntrStack:word
  209. IFNDEF WOW_x86
  210. extrn IretBopTable:BYTE
  211. ENDIF
  212. public fDebug
  213. fDebug db 0
  214. szModName db 'DOSX',0 ;Our module name for use by WDEB386
  215. if DEBUG
  216. public lpchFileName
  217. lpchFileName dd ?
  218. endif
  219. INIFileName db 'SYSTEM.INI',0 ;.INI file to read
  220. public NetHeapSize, Int28Filter
  221. INIKeywords label byte
  222. db '[standard]',0
  223. db 'netheapsize',0
  224. NetHeapSize dw 4 ;default is 8k
  225. db 'int28filter',0
  226. Int28Filter dw 10 ;default is every 10th
  227. if DEBUG ;------------------------------------------------------------
  228. public fTraceDOS
  229. db 'tracedos',0
  230. fTraceDOS dw 0
  231. public fTraceFault
  232. db 'tracefault',0
  233. fTraceFault dw 0
  234. public fTraceA20
  235. db 'tracea20',0
  236. fTraceA20 dw 1
  237. public TrapDOS
  238. db 'trapdos',0
  239. TrapDOS dw 0
  240. db 'tableslow',0
  241. fTablesLow dw 0
  242. public fTraceReflect
  243. db 'tracereflect',0
  244. fTraceReflect dw 0
  245. public fTraceMode
  246. db 'tracemode',0
  247. fTraceMode dw 0
  248. endif ;DEBUG --------------------------------------------------------
  249. db 0
  250. szExeExtension db '.exe',0
  251. ; The following set of variables are used when copying our Pmode data
  252. ; structures into a HIMEM-allocated block.
  253. public lmaIDT,lmaGDT,lmaDXPMCODE
  254. CBIDTOFF = 0
  255. CBGDTOFF = CDSCIDTDEFAULT * 8
  256. IFNDEF WOW_x86
  257. CBDXPMCODEOFF = CBGDTOFF + GDT_SIZE
  258. ELSE
  259. ;
  260. ; Since we have no GDT for wow, we do not need space for it.
  261. ;
  262. CBDXPMCODEOFF = CBGDTOFF
  263. ENDIF
  264. CBTABLESIZE = CBDXPMCODEOFF
  265. .errnz CBIDTOFF and 0fh
  266. .errnz CBGDTOFF and 0fh
  267. .errnz CBDXPMCODEOFF and 0fh
  268. lmaIDT dd CBIDTOFF
  269. lmaGDT dd CBGDTOFF
  270. lmaDXPMCODE dd CBDXPMCODEOFF
  271. lmaLDT dd CBDXPMCODEOFF
  272. extrn rgwStack:WORD
  273. DXDATA ends
  274. DXSTACK segment
  275. extrn ResetStack:WORD
  276. DXSTACK ends
  277. ; -------------------------------------------------------
  278. page
  279. ; -------------------------------------------------------
  280. ; CODE SEGMENT VARIABLES
  281. ; -------------------------------------------------------
  282. DXCODE segment
  283. ;************************************************************************
  284. ;
  285. ; REMEMBER... any code segment variables defined in this file
  286. ; will be discarded after initialization.
  287. ;
  288. ;************************************************************************
  289. extrn CodeEnd:NEAR
  290. extrn segDXCode:WORD
  291. extrn segDXData:WORD
  292. extrn selDgroup:WORD
  293. ErrMsg MACRO name
  294. extrn ER_&name:BYTE
  295. ERC_&name equ offset ER_&name
  296. ENDM
  297. ErrMsg CPUTYPE
  298. ErrMsg DXINIT
  299. ErrMsg PROTMODE
  300. ErrMsg NOHIMEM
  301. ErrMsg EXTMEM
  302. ErrMsg NOEXE
  303. extrn RMInt2FHandler:NEAR
  304. extrn PrevInt2FHandler:DWORD
  305. szWinKernel db 'krnl386.exe',0
  306. lpfnPrevXMS dd 0
  307. DXCODE ends
  308. DXPMCODE segment
  309. extrn selDgroupPM:WORD
  310. extrn segDXCodePM:WORD
  311. extrn segDXDataPM:WORD
  312. DXPMCODE ends
  313. ; -------------------------------------------------------
  314. page
  315. DXCODE segment
  316. assume cs:DXCODE
  317. ; -------------------------------------------------------
  318. ; MAIN INITIALIZATION ROUTINES
  319. ; -------------------------------------------------------
  320. ; InitDosExtender -- This routine is the executive
  321. ; for initializing the dos extender.
  322. ;
  323. ; Input: none
  324. ; Output: various global tables and variables initialized.
  325. ; Dos Extender relocated for protected mode execution
  326. ; and moved into extended memory.
  327. ; Errors: returns CY set if error occurs, pointer to error message
  328. ; in DX
  329. ; Uses:
  330. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  331. public InitDosExtender
  332. InitDosExtender:
  333. ; Init the key code & data segment variables.
  334. mov ax,cs
  335. mov segDXCode,ax
  336. mov ax,ds
  337. mov segDXData,ax
  338. mov selDgroup,ax
  339. push es
  340. mov ax,seg DXPMCODE
  341. mov es,ax
  342. assume es:DXPMCODE
  343. mov selDgroupPM,SEL_DXDATA or STD_RING
  344. mov segDXCodePM,cs
  345. mov segDXDataPM,ds
  346. pop es
  347. assume es:DGROUP
  348. ; Do an initial shrink of our program memory. This assumes that DXPMCODE
  349. ; is the last segment in program.
  350. mov bx,(offset DXPMCODE:CodeEndPM) + 10h
  351. shr bx,4
  352. add bx,seg DXPMCODE
  353. sub bx,segPSP
  354. mov es,segPSP
  355. dossvc 4Ah
  356. push ds
  357. pop es
  358. ; Determine the type of CPU we are running on and make sure it is
  359. ; at least an 80286.
  360. call CheckCPUType
  361. cmp ax,2
  362. jae indx14
  363. mov ax,ERC_CPUTYPE
  364. jmp indx80
  365. indx14:
  366. ; If running on a 286, see if there is a 287 coprocessor installed
  367. ifdef NEC_98 ;
  368. ;------------------- 90/08/15 --------------------
  369. ;check N/H at system area BIOS_FLAG(0:501h)
  370. ;if H mode, fNHmode bit on.
  371. push es
  372. push ax
  373. mov ax,0
  374. mov es,ax
  375. test byte ptr es:[501h],8h ;if Hmode
  376. jz not_Hmode
  377. mov fNHmode,0FFh ;Now! Running on Hmode!!! 90/07/07
  378. not_Hmode:
  379. pop ax
  380. pop es
  381. ;------------------- 90/08/15 --------------------
  382. ; If running on a 286, see if there is a 287 coprocessor installed
  383. cmp al,2 ;286 processor?
  384. jnz EMM_Disable
  385. test fNHmode,0FFh
  386. jz Copro_Nmode
  387. ;----- 90/07/04 in -----
  388. ; check co-processor exist at memory-switch
  389. ;----------------- Hmode -----------------
  390. push ds
  391. push bx
  392. ;;;;;;;; mov bx,0Eh
  393. mov bx,0E000h ;90/10/04 bug
  394. mov ds,bx
  395. mov bx,3FEAh
  396. mov al,byte ptr ds:[bx]
  397. pop bx
  398. pop ds
  399. test al,08h ;0=none,1=exists
  400. jmp Coprocessor
  401. Copro_Nmode:
  402. ;----------------- Nmode -----------------
  403. push ds
  404. push bx
  405. ;;;;;;;; mov bx,0Ah
  406. mov bx,0A000h ;90/10/04 bug
  407. mov ds,bx
  408. mov bx,3FEAh
  409. mov al,byte ptr ds:[bx]
  410. pop bx
  411. pop ds
  412. test al,08h ;0=none,1=exists
  413. Coprocessor:
  414. jz EMM_Disable
  415. inc f286_287 ; yup, 286 & 287
  416. EMM_Disable:
  417. else ;NEC_98 ;
  418. cmp al,2 ;286 processor?
  419. jnz @f
  420. int 11h ;math coprocessor installed?
  421. test al,2
  422. jz @f
  423. ifndef WOW_x86
  424. inc f286_287 ; yup, 286 & 287
  425. endif
  426. @@:
  427. endif ;NEC_98 ;
  428. ; If on a 386 or greater, try to disable the EMM drivers we know about
  429. call EMMDisable
  430. ; Check if the machine is already running in protected mode. If so, we
  431. ; can't run.
  432. ifndef WOW_x86
  433. smsw ax
  434. test ax,1 ;check the protected mode bit
  435. jz @f
  436. mov ax,ERC_PROTMODE
  437. jmp indx80
  438. endif
  439. @@:
  440. ; Get the full pathname of our EXE file, it's needed in a couple of places
  441. call GetExeName
  442. jnc @F
  443. mov ax,ERC_DXINIT
  444. jmp indx80
  445. @@:
  446. ; Determine if the real mode Int 28h vector points anywhere. If it doesn't
  447. ; then we don't need to reflect Int 28h calls from protected to real mode.
  448. ; The user can still override this by putting a Int28Filter= entry in
  449. ; SYSTEM.INI.
  450. push es
  451. mov ax,3528h
  452. int 21h
  453. assume es:NOTHING
  454. cmp byte ptr es:[bx],IRET_OPCODE ;Int 28h -> IRET?
  455. jne @f
  456. mov Int28Filter,0 ; yes, don't need to reflect
  457. @@:
  458. pop es
  459. assume es:DGROUP
  460. ; Read SYSTEM.INI for any parameter overrides - NOTE: requires GetExeName
  461. ; having been run first!
  462. mov bx,offset INIKeywords
  463. mov dx,offset INIFileName
  464. call ReadINIFile
  465. ; Check that the HIMEM.SYS driver is installed so that we can use it
  466. ; for extended memory management.
  467. call SetupHimemDriver
  468. jnc @F ; Himem is OK.
  469. mov ax,ERC_NOHIMEM
  470. jmp indx80
  471. @@:
  472. ifdef NEC_98 ;
  473. push es
  474. xor ax, ax
  475. mov es, ax
  476. test byte ptr es:[458h], 80h ; if NESA
  477. jz not_MC
  478. mov fPCH98, 0FFh ; it's a NPC NESA
  479. not_MC:
  480. pop es
  481. assume es:DGROUP
  482. endif ;NEC_98 ;
  483. ; Hook the real mode int vectors
  484. mov ax,352Fh ;get previous Int 2Fh vector
  485. int 21h
  486. assume es:NOTHING
  487. mov word ptr [PrevInt2FHandler],bx
  488. mov word ptr [PrevInt2FHandler+2],es
  489. push ds
  490. pop es
  491. assume es:DGROUP
  492. mov ax,cs ;point to our rMode Int 2Fh
  493. mov ds,ax
  494. assume ds:NOTHING
  495. mov dx,offset DXCODE:RMInt2FHandler
  496. mov ax,252Fh
  497. int 21h
  498. push es
  499. pop ds
  500. assume ds:DGROUP
  501. ; Allocate and initialize the descriptor tables and TSS.
  502. cCall AllocateExtMem
  503. jnc indx20
  504. mov ax,ERC_EXTMEM
  505. jmp indx80
  506. indx20:
  507. push es
  508. push bx
  509. push dx
  510. push di
  511. push si
  512. ;
  513. ; Bop to initialize 32 bit support.
  514. ;
  515. mov di, sp ;original stack offset
  516. push SEL_DXPMCODE OR STD_RING
  517. push offset DXPMCODE:HungAppExit
  518. push SEL_DXPMCODE OR STD_RING
  519. push offset DXPMCODE:XmsControl
  520. push SEL_DXPMCODE OR STD_RING
  521. push offset DXPMCODE:DPMI_MsDos_API
  522. push SEL_DXPMCODE OR STD_RING
  523. push offset DXPMCODE:VCD_PM_Svc_Call
  524. push SEL_DXPMCODE OR STD_RING
  525. push offset DXPMCODE:PmRawModeSwitch
  526. push segDXCode
  527. push offset DXCODE:RmRawModeSwitch
  528. push SEL_DXPMCODE OR STD_RING
  529. push offset DXPMCODE:PmSaveRestoreState
  530. push segDXCode
  531. push offset DXCODE:RmSaveRestoreState
  532. mov bx,cdscGDTMax
  533. shl bx,3
  534. dec bx
  535. push bx ;Initial LDT size
  536. push selGDT
  537. push SEL_DXPMCODE OR STD_RING ;pm reflector seg
  538. push segDXCode
  539. push offset DXCODE:RMtoPMReflector
  540. push segDXCode
  541. push offset DXCODE:RMCallBackBop
  542. push SEL_DXPMCODE OR STD_RING
  543. push offset DXPMCODE:PMDosxIretd
  544. push SEL_DXPMCODE OR STD_RING
  545. push offset DXPMCODE:PMDosxIret
  546. push SEL_DXPMCODE OR STD_RING
  547. push offset DXPMCODE:PMIntHandlerIRETD
  548. push SEL_DXPMCODE OR STD_RING
  549. push offset DXPMCODE:PMIntHandlerIRET
  550. push SEL_DXPMCODE OR STD_RING
  551. push offset DXPMCODE:PMFaultHandlerIRETD
  552. push SEL_DXPMCODE OR STD_RING
  553. push offset DXPMCODE:PMFaultHandlerIRET
  554. push SEL_DXCODE OR STD_RING
  555. push segDXCode
  556. push SEL_DXPMCODE OR STD_RING
  557. push offset DXPMCODE:PmUnsimulateProc
  558. push segDXCode
  559. push offset DXCODE:RmUnsimulateProc
  560. push word ptr CB_STKFRAME
  561. push segDXData
  562. mov si,sp ;pass stack offset
  563. DPMIBOP InitDosxRM
  564. mov sp, di ;restore stack
  565. ifdef WOW_x86
  566. mov word ptr [FastBop],bx
  567. mov word ptr [FastBop + 2],dx
  568. mov word ptr [FastBop + 4],es
  569. endif
  570. pop si
  571. pop di
  572. pop dx
  573. pop bx
  574. pop es
  575. call InitGlobalDscrTable ;set up the GDT
  576. call SendDbgNotification ;tell NTSD about our segments
  577. call InitIntrDscrTable ;set up the IDT
  578. ifndef WOW_x86 ;bugbug
  579. call InitTaskStateSeg ;set up the TSS
  580. endif
  581. if DEBUG
  582. ; DOSX is written such that it does not require any segment fix ups for
  583. ; protected mode operation. This wasn't always the case, and it's easy
  584. ; to make create dependencies so the routine CheckDOSXFixUps exists in
  585. ; the debug version to check for segment fix ups in non-initialization
  586. ; code.
  587. call CheckDOSXFixUps
  588. jnc @F
  589. mov ax,ERC_DXINIT
  590. jmp short indx80
  591. @@:
  592. endif ;DEBUG
  593. ; Move the Extended memory segment up into extended memory.
  594. mov dx,seg DXPMCODE
  595. call MoveDosExtender
  596. jc indx80
  597. ; Move the GDT and IDT up into extended memory.
  598. call MoveDscrTables
  599. ; Parse the command line, and locate the child exe file
  600. call ParseCommandLine
  601. IFNDEF WHEN_COMMAND_COM_WORKS
  602. if WINDOWS ;--------------------------------------------------------
  603. ; If this is a Windows specific version of DOSX, we only run one child EXE
  604. ; (krnl?86.exe).
  605. push ds
  606. push cs
  607. pop ds
  608. assume ds:NOTHING
  609. mov si,offset DXCODE:szWinKernel
  610. mov di,offset RELOC_BUFFER
  611. call strcpy
  612. pop ds
  613. assume ds:DGROUP
  614. endif ;WINDOWS -------------------------------------------------
  615. call FindFile ;setup done by ParseCommandLine
  616. jnc indx70
  617. mov ax,ERC_NOEXE
  618. jmp short indx80
  619. indx70:
  620. ENDIF
  621. ; Initialized okay!
  622. clc
  623. jmp short indx90
  624. ; Error occured. Free any extended memory blocks allocated and then
  625. ; return the error code.
  626. indx80: push ax ;save the error code
  627. ;
  628. ; If we have allocated an extended memory block, then free it.
  629. ; If we have allocated the HMA, then free it.
  630. ;
  631. mov dx,hmemDOSX
  632. or dx,dx
  633. jz @F
  634. xmssvc 0Dh
  635. xmssvc 0Ah
  636. @@:
  637. cmp fUsingHMA,0
  638. je @F
  639. xmssvc 2
  640. @@:
  641. indxEXIT:
  642. pop ax ;restore the error code
  643. stc ;set error flag
  644. indx90: ret
  645. ; -------------------------------------------------------
  646. ; AllocateExtMem -- Allocates memory used by DOSX for
  647. ; system tables and protected mode
  648. ; code.
  649. ; Allocates a temporary buffer in
  650. ; DOS memory for building the
  651. ; IDT and GDT.
  652. ; Input: none
  653. ; Output: none
  654. ; Uses: Flags
  655. ; Error: Carry set if cannot allocate memory.
  656. ;
  657. ; History:
  658. ; 10/05/90 - earleh wrote it
  659. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  660. cProc AllocateExtMem,<PUBLIC,NEAR>,<ax,bx,dx>
  661. cBegin
  662. ; If there is sufficient XMS memory, increase the size of the GDT/LDT
  663. ; up to the max of 8k selectors.
  664. add word ptr lmaLDT,offset DXPMCODE:CodeEndPM
  665. adc word ptr lmaLDT+2,0
  666. add word ptr lmaLDT,0Fh ;make sure LDT is para aligned
  667. adc word ptr lmaLDT+2,0
  668. and word ptr lmaLDT,0FFF0h
  669. @@:
  670. xmssvc 08h ;Query Free Extended memory
  671. cmp dx,1024 ;is there more than 1 meg available?
  672. jb @f
  673. mov cdscGDTMax,CDSCMAXLDT ; yes, max out the GDT size
  674. @@:
  675. mov ax,cdscGDTMax
  676. xor dx,dx
  677. shl ax,3
  678. adc dx,0
  679. add ax,word ptr lmaLDT
  680. adc dx,word ptr lmaLDT+2
  681. add ax,1023d
  682. adc dx,0 ; DX:AX = total extended memory needed
  683. shl dx,6
  684. shr ax,10d
  685. or dx,ax ; DX = kbytes needed
  686. mov si,dx ; SI = kbytes needed
  687. xmssvc 09h ; allocate the XMS block
  688. or ax,ax
  689. jz axm_error
  690. mov hmemDOSX,dx
  691. xmssvc 0Ch ; lock it, DX:BX = address
  692. or ax,ax
  693. jz axm_error
  694. axm_address:
  695. add word ptr lmaIDT,bx ; relocate tables & Pmode code
  696. adc word ptr lmaIDT+2,dx
  697. add word ptr lmaGDT,bx
  698. adc word ptr lmaGDT+2,dx
  699. add word ptr lmaDXPMCODE,bx
  700. adc word ptr lmaDXPMCODE+2,dx
  701. add word ptr lmaLDT,bx
  702. adc word ptr lmaLDT+2,dx
  703. mov bx,(CDSCIDTDEFAULT + GDT_SELECTORS + 1) shr 1
  704. dossvc 48h ; get a DOS block for building tables
  705. jc axm_error ; abort if error
  706. mov segIDT,ax
  707. mov selIDT,ax
  708. add ax,CDSCIDTDEFAULT shr 1
  709. mov segGDT,ax
  710. mov selGDT,ax
  711. clc
  712. jmp axm_exit
  713. axm_error:
  714. stc
  715. axm_exit:
  716. cEnd
  717. ; -------------------------------------------------------
  718. ; SetupHimemDriver -- This routine checks that an XMS driver
  719. ; is installed and sets up for calling it.
  720. ;
  721. ; Input: none
  722. ; Output: none
  723. ; Errors: returns CY set if no driver available
  724. ; Uses: AX, all other registers preserved
  725. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  726. public SetupHimemDriver
  727. SetupHimemDriver proc near
  728. push bx
  729. push es
  730. ; Check to see if there is an XMS driver resident.
  731. mov ax,4300h
  732. int 2Fh
  733. cmp al,80h
  734. jnz sthd80
  735. ; There is an XMS driver resident, so init for calling it.
  736. mov ax,4310h
  737. int 2Fh
  738. mov word ptr [lpfnXMSFunc],bx
  739. mov word ptr [lpfnXMSFunc+2],es
  740. ; Make sure this is the proper XMS/driver version
  741. xmssvc 0 ;returns XMS vers in ax, driver vers in bx
  742. cmp ax,300h ;assume okay if XMS 3.0 or above
  743. jae @f
  744. cmp ax,200h ;require at least XMS 2.00
  745. jb sthd80
  746. cmp bx,21Ch ;if XMS 2.x, require driver version 2.28+
  747. jb sthd80 ; (himem used to have minor vers in decimal)
  748. @@:
  749. ; Verify that the XMS driver's A20 functions work
  750. xmssvc 5 ;local enable
  751. or ax,ax
  752. jz sthd80
  753. xmssvc 7 ;query A20
  754. push ax
  755. xmssvc 6 ;local disable
  756. or ax,ax
  757. pop ax ;recover query status
  758. jz sthd80
  759. or ax,ax ;should be NZ, (A20 enabled status)
  760. jz sthd80
  761. ; Looks good to me...
  762. clc
  763. jmp short sthd90
  764. ; No XMS driver resident or wrong version or we couldn't enable A20.
  765. sthd80: stc
  766. sthd90: pop es
  767. pop bx
  768. ret
  769. SetupHimemDriver endp
  770. ; -------------------------------------------------------
  771. ; MoveDosExtender -- This routine will move the Dos Extender
  772. ; protected mode segment up into extended memory.
  773. ; The himem driver function for moving memory blocks is used.
  774. ; The parameter block for this function is built in rgbXfrBuf0.
  775. ;
  776. ; Input: DX - real mode segment address of the segment to move
  777. ; Output: none
  778. ; Errors: returns CY set if error, Error code in AX
  779. ; Uses: AX used, all else preserved
  780. ; modifies rgbXfrBuf0
  781. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  782. public MoveDosExtender
  783. MoveDosExtender proc near
  784. push bx
  785. push cx
  786. push dx
  787. push si
  788. cmp fUsingHMA,0
  789. je mvdx40
  790. ;
  791. ; Our extended memory block is actually the HMA. Enable A20 and do
  792. ; the move ourselves.
  793. ;
  794. xmssvc 5 ;local enable
  795. push di
  796. push ds
  797. push es
  798. mov cx,offset DXPMCODE:CodeEndPM
  799. inc cx
  800. and cx,0FFFEh
  801. mov di,CBDXPMCODEOFF+10h
  802. xor si,si
  803. dec si
  804. mov es,si
  805. inc si
  806. mov ds,dx
  807. assume ds:NOTHING
  808. ;
  809. ; DS:SI = segIDT:0
  810. ; ES:DI = 0FFFF:CBDXPMCODEOFF+10h
  811. ; CX = code size
  812. ;
  813. cld
  814. rep movsb
  815. pop es
  816. assume ds:DGROUP
  817. pop ds
  818. pop di
  819. xmssvc 6 ;local disable
  820. jmp mvdx65
  821. mvdx40:
  822. ; Move the data up into extended memory using the XMS driver's function.
  823. mov si,offset DGROUP:rgbXfrBuf0
  824. mov cx,offset DXPMCODE:CodeEndPM
  825. inc cx
  826. and cx,0FFFEh
  827. mov word ptr [si].cbxmsLen,cx
  828. mov word ptr [si].oxmsSource+2,dx ;real mode code segment address
  829. mov ax,hmemDOSX
  830. mov word ptr [si].hxmsDest,ax
  831. xor ax,ax
  832. mov word ptr [si].cbxmsLen+2,ax
  833. mov [si].hxmsSource,ax
  834. mov word ptr [si].oxmsSource,ax
  835. mov word ptr [si].oxmsDest,CBDXPMCODEOFF
  836. mov word ptr [si].oxmsDest+2,ax
  837. xmssvc 0Bh
  838. mvdx65:
  839. clc
  840. jmp short mvdx90
  841. ; Error occured
  842. mvdx80: stc
  843. mvdx90: pop si
  844. pop dx
  845. pop cx
  846. pop bx
  847. ret
  848. MoveDosExtender endp
  849. ; -------------------------------------------------------
  850. ; MoveDscrTables -- This routine will move the GDT
  851. ; and IDT up into extended memory. The himem driver
  852. ; function for moving memory blocks is used. The parameter
  853. ; block for this function is built in rgbXfrBuf0.
  854. ;
  855. ; Input: none
  856. ; Output: none
  857. ; Errors: returns CY set if error occurs. Error code in AX
  858. ; Uses: AX, all else preserved
  859. ; modifies rgbXfrBuf0
  860. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  861. public MoveDscrTables
  862. MoveDscrTables proc near
  863. push bx
  864. push si
  865. push es
  866. cmp fUsingHMA,0
  867. je @F
  868. ;
  869. ; Our extended memory block is actually the HMA. Enable A20 and do
  870. ; the move ourselves.
  871. ;
  872. xmssvc 5 ;local enable
  873. push ds
  874. push di
  875. push cx
  876. mov cx,CBTABLESIZE
  877. mov di,10h
  878. xor si,si
  879. dec si
  880. mov es,si
  881. inc si
  882. mov ds,segIDT
  883. assume ds:NOTHING
  884. ;
  885. ; DS:SI = segIDT:0
  886. ; ES:DI = 0FFFF:10
  887. ; CX = tables size
  888. ;
  889. cld
  890. rep movsb
  891. pop cx
  892. pop di
  893. pop ds
  894. assume ds:DGROUP
  895. xmssvc 6 ;local disable
  896. clc
  897. jmp mvdt_ret
  898. @@:
  899. ; Move the GDT and IDT together.
  900. mov si,offset DGROUP:rgbXfrBuf0
  901. mov word ptr [si].cbxmsLen,CBTABLESIZE
  902. mov word ptr [si].cbxmsLen+2,0
  903. mov ax,segIDT
  904. mov word ptr [si].oxmsSource+2,ax
  905. mov ax,hmemDOSX
  906. mov word ptr [si].hxmsDest,ax
  907. xor ax,ax
  908. mov [si].hxmsSource,ax
  909. mov word ptr [si].oxmsSource,ax
  910. mov word ptr [si].oxmsDest,ax
  911. mov word ptr [si].oxmsDest+2,ax
  912. xmssvc 0Bh
  913. IFDEF WOW
  914. ;
  915. ; Move the initialized selectors from the gdt to the ldt
  916. ;
  917. mov word ptr [si].cbxmsLen,GDT_SIZE
  918. mov word ptr [si].cbxmsLen+2,0
  919. mov ax,segGDT
  920. mov word ptr [si].oxmsSource+2,ax
  921. mov ax,hmemDOSX
  922. mov word ptr [si].hxmsDest,ax
  923. xor ax,ax
  924. mov word ptr [si].hxmsSource,ax
  925. mov word ptr [si].oxmsSource,ax
  926. mov word ptr [si].oxmsDest+2,ax
  927. mov word ptr [si].oxmsDest,CBTABLESIZE + offset DXPMCODE:CodeEndPM
  928. xmssvc 0Bh
  929. ENDIF
  930. mvdt_ret:
  931. mov es,segIDT ;free the low memory copy
  932. dossvc 49h
  933. pop es
  934. pop si
  935. pop bx
  936. ret
  937. MoveDscrTables endp
  938. ; -------------------------------------------------------
  939. ; Send Debugger Notification
  940. SendDbgNotification proc near
  941. IFDEF WOW
  942. ;
  943. ; Send load notification to the debugger for DXDATA
  944. ;
  945. push 1 ; data
  946. push ds ; exe name
  947. push offset EXEC_DXNAME
  948. push ds ; module name
  949. push offset szModName
  950. push 0
  951. push SEL_DXDATA OR STD_RING
  952. push DBG_SEGLOAD
  953. BOP BOP_DEBUGGER
  954. add sp,16
  955. ;
  956. ; Send load notification to the debugger for DXCODE
  957. ;
  958. push 0 ; code
  959. push ds ; exe name
  960. push offset EXEC_DXNAME
  961. push ds ; module name
  962. push offset szModName
  963. push 1
  964. push SEL_DXCODE OR STD_RING
  965. push DBG_SEGLOAD
  966. BOP BOP_DEBUGGER
  967. add sp,16
  968. ;
  969. ; Send load notification to the debugger
  970. ;
  971. push 0 ; code
  972. push ds ; exe name
  973. push offset EXEC_DXNAME
  974. push ds ; module name
  975. push offset szModName
  976. push 2
  977. push SEL_DXPMCODE OR STD_RING
  978. push DBG_SEGLOAD
  979. BOP BOP_DEBUGGER
  980. add sp,16
  981. ENDIF
  982. ret
  983. SendDbgNotification endp
  984. ; -------------------------------------------------------
  985. ; InitGlobalDscrTable -- This function will allocate a memory
  986. ; buffer from DOS and then initialize it as a global
  987. ; descriptor table. It will also initialize all global
  988. ; variables associated with GDT management.
  989. ; Descriptors in the range 0 - SEL_USER are given statically
  990. ; defined meanings. Descriptors from SEL_USER up are defined
  991. ; dynamically when a program is loaded or when dynamic memory
  992. ; management calls occur.
  993. ;
  994. ; NOTE: This routine works in real mode. The buffer where
  995. ; the GDT is built is in low memory.
  996. ;
  997. ; Input: AX - number of descriptors to initialize
  998. ; Output: none
  999. ; Errors: CY set if unable to obtain memory for the GDT
  1000. ; Uses: AX used, all other registers preserved
  1001. ; bpGDT initialized.
  1002. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  1003. public InitGlobalDscrTable
  1004. InitGlobalDscrTable proc near
  1005. push bx
  1006. push cx
  1007. push dx
  1008. push di
  1009. push es
  1010. mov word ptr [bpGDT+0],GDT_SIZE - 1
  1011. mov ax,word ptr lmaGDT
  1012. mov word ptr [bpGDT+2],ax
  1013. mov ax,word ptr lmaGDT+2
  1014. mov word ptr [bpGDT+4],ax
  1015. ;
  1016. ; Start by initializing the GDT to 0.
  1017. ;
  1018. mov cx,GDT_SIZE shr 1
  1019. mov es,segGDT
  1020. assume es:NOTHING
  1021. xor ax,ax
  1022. mov di,ax
  1023. rep stosw
  1024. ; Next, initialize the statically defined descriptors.
  1025. ;
  1026. ; Set up a descriptor for our protected mode code.
  1027. xor ax,ax ;AX = 0
  1028. mov dx,cs ;our code segment paragraph address
  1029. call B_ParaToLinear ;convert to linear byte address
  1030. mov cx,offset CodeEnd
  1031. cCall NSetSegmentDscr,<SEL_DXCODE,bx,dx,ax,cx,STD_CODE>
  1032. ; Set up another one, but ring 0 this time. Limit should be 0FFFFh
  1033. ; or 386 reset to real mode will not work properly.
  1034. mov cx,0FFFFh
  1035. cCall NSetSegmentDscr,<SEL_DXCODE0,bx,dx,ax,cx,ARB_CODE0>
  1036. ;
  1037. ; Set up one for the other segment, and a Ring 0 alias.
  1038. ;
  1039. mov cx,offset CodeEndPM
  1040. mov bx,word ptr lmaDXPMCODE
  1041. mov dx,word ptr lmaDXPMCODE+2
  1042. cCall NSetSegmentDscr,<SEL_DXPMCODE,dx,bx,0,cx,STD_CODE>
  1043. cCall NSetSegmentDscr,<SEL_NBPMCODE,dx,bx,0,cx,STD_CODE>
  1044. ifndef WOW_x86
  1045. cCall NSetSegmentDscr,<SEL_EH,dx,bx,0,cx,EH_CODE>
  1046. else
  1047. cCall NSetSegmentDscr,<SEL_EH,dx,bx,0,cx,STD_CODE>
  1048. endif
  1049. mov cx,0FFFFh
  1050. ; Set up a descriptor for our protected mode data and stack area.
  1051. mov dx,ds ;our data segment paragraph address
  1052. call B_ParaToLinear ;convert to linear byte address
  1053. cCall NSetSegmentDscr,<SEL_DXDATA,bx,dx,ax,cx,STD_DATA>
  1054. IFNDEF WOW_x86
  1055. ; Set up descriptor for IRET HOOKS
  1056. push dx
  1057. push bx
  1058. add dx,offset IretBopTable
  1059. adc bx,0
  1060. cCall NSetSegmentDscr,<SEL_IRETHOOK,bx,dx,ax,cx,STD_CODE>
  1061. pop bx
  1062. pop dx
  1063. ELSE
  1064. ; Set up descriptor for IRET HOOKS
  1065. push dx
  1066. push bx
  1067. add dx,offset FastBop
  1068. adc bx,0
  1069. cCall NSetSegmentDscr,<SEL_IRETHOOK,bx,dx,ax,cx,STD_CODE>
  1070. pop bx
  1071. pop dx
  1072. ENDIF
  1073. IFNDEF WOW_x86
  1074. ; And another one of those for ring 0
  1075. cCall NSetSegmentDscr,<SEL_DXDATA0,bx,dx,ax,cx,ARB_DATA0>
  1076. ENDIF
  1077. ;
  1078. ; Set up descriptors pointing to our PSP and environment.
  1079. mov dx,segPSP ;segment address of the PSP
  1080. call B_ParaToLinear ;convert to linear byte address
  1081. cCall NSetSegmentDscr,<SEL_PSP,bx,dx,ax,cx,STD_DATA>
  1082. mov selPSP,SEL_PSP
  1083. ;
  1084. push es
  1085. mov es,segPSP
  1086. assume es:PSPSEG
  1087. mov dx,segEnviron
  1088. call B_ParaToLinear
  1089. cCall NSetSegmentDscr,<SEL_ENVIRON,bx,dx,ax,7FFFH,STD_DATA>
  1090. pop es
  1091. assume es:nothing
  1092. ; Set up a descriptor that points to the GDT.
  1093. mov dx,word ptr [bpGDT+2] ;get the GDT linear byte address
  1094. mov bx,word ptr [bpGDT+4]
  1095. mov cx,word ptr [bpGDT+0] ;get the GDT segment size
  1096. cCall NSetSegmentDscr,<SEL_GDT,bx,dx,ax,cx,STD_DATA>
  1097. ; Set up a descriptor for the LDT and an LDT data alias.
  1098. mov cx,cdscGDTMax ;get count of descriptors
  1099. shl cx,3
  1100. dec cx
  1101. mov dx,word ptr lmaLDT
  1102. mov bx,word ptr lmaLDT+2
  1103. IFNDEF WOW_x86
  1104. cCall NSetSegmentDscr,<SEL_LDT,bx,dx,ax,cx,STD_LDT>
  1105. ENDIF
  1106. cCall NSetSegmentDscr,<SEL_LDT_ALIAS,bx,dx,ax,cx,STD_DATA>
  1107. ; set up a readonly selector to the LDT for the wow kernel
  1108. cCall NSetSegmentDscr,<SEL_WOW_LDT,bx,dx,ax,cx,STD_DATA>
  1109. ; Set up descriptors pointing to the BIOS code and data areas
  1110. mov cx,0FFFFH ; CX = 0FFFFH
  1111. cCall NSetSegmentDscr,<SEL_BIOSCODE,000fh,ax,ax,cx,STD_CODE>
  1112. mov dx,40h*16
  1113. cCall NSetSegmentDscr,<SEL_BIOSDATA,ax,dx,ax,cx,STD_DATA>
  1114. ; Set up a descriptor pointing to the real mode interrupt vector table.
  1115. cCall NSetSegmentDscr,<SEL_RMIVT,ax,ax,ax,cx,STD_DATA>
  1116. IFNDEF WOW_x86
  1117. ; Setup a selector and data alias for the TSS
  1118. mov dx,ds ;get base address of TSS
  1119. call B_ParaToLinear ; (it may not be para aligned)
  1120. add dx,offset DGROUP:sysTSS
  1121. adc bx,ax
  1122. mov cx,(TYPE TSS286) - 1
  1123. cCall NSetSegmentDscr,<SEL_TSS,bx,dx,ax,cx,STD_TSS>
  1124. cCall NSetSegmentDscr,<SEL_TSS_ALIAS,bx,dx,ax,cx,STD_DATA>
  1125. ENDIF
  1126. ;
  1127. ; Pass address of HwIntr stack, and form pointer to lockcount in
  1128. ; VdmTib. This enables us to coordinate stack switching with
  1129. ; the nt kernel and the monitor. These components will switch
  1130. ; the stack on Hw Interrupt reflection, dosx will switch it
  1131. ; back at iret.
  1132. ;
  1133. push es
  1134. mov ax,SEL_DXDATA or STD_RING
  1135. mov es, ax
  1136. mov bx, pbHwIntrStack
  1137. DPMIBOP InitPmStackInfo
  1138. pop es
  1139. IFDEF WOW_x86
  1140. ;
  1141. ; Create a code selector for the NPX emulation exception handler
  1142. ;
  1143. mov ax,offset EndNpxExceptionHandler
  1144. sub ax,offset NpxExceptionHandler
  1145. mov bx,offset DXPMCODE:NpxExceptionHandler
  1146. add bx,word ptr lmaDXPMCODE
  1147. mov dx,word ptr lmaDXPMCODE + 2
  1148. cCall NSetSegmentDscr,<SEL_NPXHDLR,dx,bx,0,ax,STD_CODE>
  1149. ENDIF
  1150. clc ;worked! make sure CY is clear
  1151. ; All done
  1152. igdt90: pop es
  1153. pop di
  1154. pop dx
  1155. pop cx
  1156. pop bx
  1157. ret
  1158. InitGlobalDscrTable endp
  1159. ; -------------------------------------------------------
  1160. ; InitIntrDscrTable -- This function will initialize the
  1161. ; specified memory buffer as an Interrupt Descriptor Table,
  1162. ; and set up all of the control variables associated with
  1163. ; the IDT.
  1164. ;
  1165. ; NOTE: This routine works in real mode. The buffer where
  1166. ; the IDT is built is in low memory.
  1167. ; NOTE: The InitGlobalDscrTable function must be called before
  1168. ; this function can be called.
  1169. ;
  1170. ; Input: AX - number of descriptors to initialize
  1171. ; Output: none
  1172. ; Errors: CY set if unable to obtain the memory required
  1173. ; Uses: AX, all other registers preserved
  1174. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  1175. public InitIntrDscrTable
  1176. InitIntrDscrTable proc near
  1177. push bx
  1178. push cx
  1179. push dx
  1180. push si
  1181. push di
  1182. push es
  1183. ifndef WOW_x86
  1184. ; Save the current pointer to the real mode interrupt vector table.
  1185. sidt fword ptr bpRmIVT
  1186. endif
  1187. mov es,selIDT
  1188. assume es:NOTHING
  1189. mov cx,256 ;number of descriptors in table
  1190. shl cx,3 ;convert to count of bytes
  1191. dec cx ;compute segment size limit
  1192. mov word ptr [bpIDT+0],cx
  1193. mov dx,word ptr lmaIDT
  1194. mov word ptr [bpIDT+2],dx
  1195. mov bx,word ptr lmaIDT+2
  1196. mov word ptr [bpIDT+4],bx
  1197. cCall NSetSegmentDscr,<SEL_IDT,bx,dx,0,cx,STD_DATA>
  1198. ; Fill the IDT with interrupt gates that point to the fault handler and
  1199. ; interrupt reflector entry vector.
  1200. xor di,di
  1201. mov dx,offset DXPMCODE:PmIntrEntryVector
  1202. mov cx,256
  1203. iidt23: mov es:[di].offDest,dx
  1204. mov es:[di].selDest,SEL_DXPMCODE or STD_RING
  1205. mov es:[di].cwParam,0
  1206. mov es:[di].arbGate,STD_TRAP ; BUGBUG- int gates not set up
  1207. mov es:[di].rsvdGate,0
  1208. add dx,5
  1209. add di,8
  1210. loop iidt23
  1211. ; Now, fix up the ones that don't point to the interrupt reflector.
  1212. ; BUGBUG In dxstrt.asm, these are x86 ONLY.
  1213. mov es:[1h*8].offDest,offset PMIntrIgnore
  1214. mov es:[3h*8].offDest,offset PMIntrIgnore
  1215. ifdef NEC_98 ;
  1216. mov es:[11h*8].offDest,offset PMIntr11dummy
  1217. mov es:[18h*8].offDest,offset PMIntrVideo
  1218. mov es:[1ah*8].offDest,offset PMIntrPrinter
  1219. mov es:[1bh*8].offDest,offset PMIntr13
  1220. mov es:[1ch*8].offDest,offset PMIntrCalTi
  1221. mov es:[1dh*8].offDest,offset PMIntrGraph
  1222. mov es:[1fh*8].offDest,offset PMIntrMisc
  1223. else ;NEC_98 ;
  1224. mov es:[10h*8].offDest,offset PMIntrVideo
  1225. mov es:[13h*8].offDest,offset PMIntr13
  1226. mov es:[15h*8].offDest,offset PMIntrMisc
  1227. mov es:[19h*8].offDest,offset PMIntr19
  1228. endif ;NEC_98 ;
  1229. mov es:[21h*8].offDest,offset DXPMCODE:PMIntrDos
  1230. mov es:[25h*8].offDest,offset DXPMCODE:PMIntr25
  1231. mov es:[26h*8].offDest,offset DXPMCODE:PMIntr26
  1232. mov es:[28h*8].offDest,offset DXPMCODE:PMIntr28
  1233. mov es:[30h*8].offDest,offset DXPMCODE:PMIntrIgnore
  1234. mov es:[31h*8].offDest,offset DXPMCODE:PMIntr31
  1235. mov es:[33h*8].offDest,offset DXPMCODE:PMIntrMouse
  1236. mov es:[41h*8].offDest,offset DXPMCODE:PMIntrIgnore
  1237. ifndef WOW_x86
  1238. mov es:[4Bh*8].offDest,offset DXPMCODE:PMIntr4B
  1239. ifdef NEC_98 ;
  1240. ; Sound BIOS Int D2h handler
  1241. mov es:[0D2h*8].offDest,offset DXPMCODE:PMIntrSound
  1242. ; Extended DOS Int DCh handler (KANA/KANJI)
  1243. mov es:[0DCh*8].offDest,offset DXPMCODE:PMIntrExDos
  1244. endif ;NEC_98 ;
  1245. endif
  1246. ;
  1247. ; Set up the IDT, and dpmi32 state
  1248. ;
  1249. mov ax,es ; Idt selector
  1250. mov bx,VDM_INT_16
  1251. DPMIBOP InitIDT
  1252. mov ax,5 ; handler increment
  1253. mov cx,SEL_DXPMCODE OR STD_RING
  1254. mov dx,offset DXPMCODE:PmFaultEntryVector
  1255. DPMIBOP InitExceptionHandlers
  1256. .286p
  1257. ; All done
  1258. iidt90: pop es
  1259. pop di
  1260. pop si
  1261. pop dx
  1262. pop cx
  1263. pop bx
  1264. ret
  1265. InitIntrDscrTable endp
  1266. ; -------------------------------------------------------
  1267. ;
  1268. ; InitTaskStateSeg -- This function initializes the
  1269. ; TSS for the DOS Extender.
  1270. ;
  1271. ; Input: none
  1272. ; Output: none
  1273. ; Errors: returns CY if unable to allocate memory
  1274. ; Uses: all registers preserved
  1275. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  1276. public InitTaskStateSeg
  1277. InitTaskStateSeg proc near
  1278. push ax
  1279. push cx
  1280. push di
  1281. ; As a start, zero out the TSS
  1282. xor al,al
  1283. mov cx,type TSS286
  1284. mov di,offset DGROUP:sysTSS
  1285. rep stosb
  1286. ; Set the LDT selector
  1287. mov sysTSS.tss_ldt,SEL_LDT
  1288. ; Set the ring 0 stack seg/pointer, we don't bother to set the others
  1289. ; since nothing runs below DOSX's ring. Currently very little code runs
  1290. ; ring 0 - just when switching between real/proteted modes.
  1291. mov sysTSS.tss_ss0,SEL_DXDATA0
  1292. mov sysTSS.tss_sp0,offset DGROUP:ResetStack
  1293. ; That's all it takes
  1294. pop di
  1295. pop cx
  1296. pop ax
  1297. clc
  1298. ret
  1299. InitTaskStateSeg endp
  1300. ; -------------------------------------------------------
  1301. ; MISC. STARTUP ROUTINES
  1302. ; -------------------------------------------------------
  1303. ; *** CheckCPUType - Set global variable for CPU type
  1304. ;
  1305. ; This routine relies on Intel-approved code that takes advantage
  1306. ; of the documented behavior of the high nibble of the flag word
  1307. ; in the REAL MODE of the various processors. The MSB (bit 15)
  1308. ; is always a one on the 8086 and 8088 and a zero on the 286 and
  1309. ; 386. Bit 14 (NT flag) and bits 13/12 (IOPL bit field) are
  1310. ; always zero on the 286, but can be set on the 386.
  1311. ;
  1312. ; For future compatibility of this test, it is strongly recommended
  1313. ; that this specific instruction sequence be used. The exit codes
  1314. ; can of course be changed to fit a particular need.
  1315. ;
  1316. ; CALLABLE FROM REAL MODE ONLY
  1317. ;
  1318. ; ENTRY: NONE
  1319. ;
  1320. ; EXIT: AX holds CPU type ( 0=8086,80186; 2=80286; 3=80386; 4=80486 )
  1321. ;
  1322. ; USES: AX, DS must point to DX data segment
  1323. ; idCpuType initialized
  1324. ;
  1325. ; Modified: 07-31-90 Earleh added code from Kernel, originally
  1326. ; supplied by Intel, to check for 80486. Added check
  1327. ; for V86 mode just in case a Limulator or something
  1328. ; is active.
  1329. ;
  1330. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  1331. public CheckCPUType
  1332. CheckCPUType proc near
  1333. .8086
  1334. pushf ; save flags during cpu test
  1335. pushf
  1336. pop ax ; flags to ax
  1337. and ax, 0fffh ; clear bits 12-15
  1338. push ax ; push immediate is bad op-code on 8086
  1339. npopf ; try to put that in the flags
  1340. pushf
  1341. pop ax ; look at what really went into flags
  1342. and ah,0f0h ; mask off high flag bits
  1343. cmp ah,0f0h ; Q: was high nibble all ones ?
  1344. mov ax, 0
  1345. jz cidx ; Y: 8086
  1346. .286p
  1347. smsw ax
  1348. test ax,1 ; Protected mode?
  1349. jnz cid386 ; V86! Gotta be at least a 386.
  1350. push 0f000h ; N: try to set the high bits
  1351. npopf ; ... in the flags
  1352. pushf
  1353. pop ax ; look at actual flags
  1354. and ah,0f0h ; Q: any high bits set ?
  1355. mov ax, 2 ; at least 286
  1356. jz cidx ; N: 80286 - exit w/ Z flag set
  1357. ; Y: 80386 - Z flag reset
  1358. ; 386 or 486? See if we can set the AC (Alignment check) bit in Eflags
  1359. ; Need to insure stack is DWORD aligned for this to work properly
  1360. .386
  1361. cid386:
  1362. mov ax, 3
  1363. push cx
  1364. push ebx
  1365. mov cx,sp ; Assume stack aligned
  1366. and cx,0011b ; set "pop" count
  1367. sub sp,cx ; Move to DWORD aligned
  1368. pushfd ; save entry flags (DWORD)
  1369. push dword ptr 40000h ; AC bit
  1370. popfd
  1371. pushfd
  1372. pop ebx
  1373. popfd ; Recover entry flags (DWORD)
  1374. add sp,cx ; pop off alignment bytes
  1375. test ebx,40000h ; Did AC bit set?
  1376. pop ebx
  1377. pop cx
  1378. jz short cidx ; No, 386
  1379. .286p
  1380. inc ax ; At least 80486...
  1381. cidx:
  1382. mov idCpuType,ax ;store CPU type in global
  1383. npopf ; restore flags after cpu test
  1384. CheckCPUType endp
  1385. ; -------------------------------------------------------
  1386. ; B_ParaToLinear
  1387. ;
  1388. ; This function will convert a paragraph address in the lower
  1389. ; megabyte of memory space into a linear address for use in
  1390. ; a descriptor table. This is a local duplicate of the function
  1391. ; ParaToLinear in DXUTIL.ASM. This is duplicated here to avoid
  1392. ; having to make far calls to it during the initialization.
  1393. ;
  1394. ; Input: DX - paragraph address
  1395. ; Output: DX - lower word of linear address
  1396. ; BX - high word of linear address
  1397. ; Errors: none
  1398. ; Uses: DX, BX used, all else preserved
  1399. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  1400. B_ParaToLinear proc near
  1401. xor bh,bh
  1402. mov bl,dh
  1403. shr bl,4
  1404. shl dx,4
  1405. ret
  1406. B_ParaToLinear endp
  1407. if DEBUG ;-------------------------------------------------------
  1408. ; -------------------------------------------------------
  1409. ; CheckDOSXFixUps -- This routine will check for segment fix ups
  1410. ; in non-initialization code that need to be converted from
  1411. ; a segment to selector.
  1412. ;
  1413. ; This routine works by opening the EXE file that we were
  1414. ; loaded from and examining the relocation table.
  1415. ;
  1416. ; 10-09-90 Earleh modified so that references in initialization
  1417. ; code are not edited.
  1418. ;
  1419. ; 11-12-90 JimMat renamed from RelocateDosExtender and it now
  1420. ; only checks for fix ups in DEBUG version since all fix ups
  1421. ; in post-initialization code have been removed.
  1422. ;
  1423. ; Input: none
  1424. ; Output: none
  1425. ; Errors: returns CY set if error occurs
  1426. ; Uses: AX, all else preserved
  1427. ; modifies lpchFileName
  1428. assume ds:DGROUP,es:NOTHING,ss:DGROUP
  1429. public CheckDOSXFixUps
  1430. CheckDOSXFixUps proc near
  1431. push bp
  1432. mov bp,sp
  1433. push bx
  1434. push dx
  1435. push si
  1436. push di
  1437. push es
  1438. ; Find the path to our exe fie.
  1439. mov word ptr [lpchFileName],offset EXEC_DXNAME
  1440. mov word ptr [lpchFileName+2],ds
  1441. ; Set up for reading the relocation table from the exe file.
  1442. call B_InitRelocBuffer
  1443. jc rldx90 ;get out if error
  1444. ; Go down through the relocation table and for each fixup item,
  1445. ; patch in our selector.
  1446. mov bx,segPSP
  1447. add bx,10h ;the relocation table items are relative
  1448. ; to the initial load address of our program
  1449. ; image which is immediately after the PSP
  1450. rldx40: call B_GetRelocationItem ;get next relocation table entry
  1451. jz rldx60 ;if end of table, get out
  1452. mov di,ax ;offset of relocation item
  1453. add dx,bx ;adjust relocation item segment for our load
  1454. ; address
  1455. mov es,dx ;
  1456. ;
  1457. ; Do not fixup instructions in initialization code.
  1458. ;
  1459. cmp dx,seg DXCODE
  1460. jne rldx41
  1461. cmp di,offset DXCODE:CodeEnd
  1462. jnc rldx40
  1463. rldx41:
  1464. cmp dx,seg DXPMCODE
  1465. jne rldx42
  1466. cmp di,offset DXPMCODE:CodeEndPM
  1467. jnc rldx40
  1468. rldx42:
  1469. mov ax,es:[di] ;get the current fixup contents
  1470. cmp ax,seg DXCODE ;is it the mixed mode segment?
  1471. jnz rldx44
  1472. extrn lCodeSegLoc:WORD
  1473. cmp di,offset DXCODE:lCodeSegLoc ;special far jmp to flush
  1474. jz rldx40 ; pre-fetch queue? ok if so.
  1475. ; Shouldn't get here--tell developer he messed something up!
  1476. int 3 ;****************************************
  1477. mov word ptr es:[di],SEL_DXCODE or STD_RING
  1478. jmp short rldx40
  1479. rldx44: cmp ax,seg DXPMCODE ;is it the protected mode only segment
  1480. jnz rldx40
  1481. ; Shouldn't get here--tell developer he messed something up!
  1482. int 3 ;****************************************
  1483. mov word ptr es:[di],SEL_DXPMCODE or STD_RING
  1484. jmp rldx40 ;and repeat for the next one
  1485. ; We have gone through the entire relocation table, so close up the exe file
  1486. rldx60: mov bx,fhExeFile
  1487. dossvc 3Eh
  1488. ;
  1489. clc
  1490. jmp short rldx90
  1491. ;
  1492. ; Error occured
  1493. rldx80: stc
  1494. ;
  1495. ; All done
  1496. rldx90: pop es
  1497. pop di
  1498. pop si
  1499. pop dx
  1500. pop bx
  1501. mov sp,bp
  1502. pop bp
  1503. ret
  1504. CheckDOSXFixUps endp
  1505. ; -------------------------------------------------------
  1506. ; B_InitRelocBuffer -- This routine will open the EXE
  1507. ; file and initialize for reading the relocation table
  1508. ; as part of relocating the program for protected mode
  1509. ; execution.
  1510. ;
  1511. ; Input: lpchFileName - pointer to exe file name
  1512. ; Output: none
  1513. ; Errors: returns CY set if error occurs
  1514. ; Uses: AX modified, all other registers preserved
  1515. ; sets up static variables:
  1516. ; clpRelocItem, plpRelocItem, fhExeFile
  1517. ; modifies rgbXfrBuf1 at offset RELOC_BUFFER
  1518. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  1519. public B_InitRelocBuffer
  1520. B_InitRelocBuffer proc near
  1521. push bx
  1522. push cx
  1523. push dx
  1524. push si
  1525. ;
  1526. ; Open the EXE file.
  1527. push ds
  1528. lds dx,lpchFileName
  1529. mov al,0
  1530. dossvc 3Dh ;attempt to open the exe file
  1531. pop ds
  1532. jc inrl80 ;get out if error occurs
  1533. ;
  1534. mov fhExeFile,ax ;store the file handle
  1535. mov bx,ax ;file handle to BX also
  1536. ; Read the EXE file header, so that we can get information about
  1537. ; the relocation table.
  1538. mov dx,offset RELOC_BUFFER
  1539. mov si,dx
  1540. mov cx,32
  1541. dossvc 3Fh
  1542. jc inrl80 ;get out if error
  1543. cmp ax,32
  1544. jnz inrl80
  1545. ;
  1546. ; Get the important values from the exe file header.
  1547. cmp [si].idExeFile,5A4Dh ;make sure it is an EXE file
  1548. jnz inrl80
  1549. mov ax,[si].clpRelocLen ;number of relocation items
  1550. mov clpRelocItem,ax
  1551. mov plpRelocItem,0FFFFh ;init the pointer to the first one
  1552. ; to a bogus value to force the initial
  1553. ; buffer to be loaded
  1554. ;
  1555. ; Get the location of the relocation table, and move the file pointer
  1556. ; to its start.
  1557. xor cx,cx
  1558. mov dx,[si].wRelocOffset
  1559. mov al,cl
  1560. dossvc 42h
  1561. jnc inrl90
  1562. ;
  1563. ; Error occured
  1564. inrl80: stc
  1565. ;
  1566. ; All done
  1567. inrl90: pop si
  1568. pop dx
  1569. pop cx
  1570. pop bx
  1571. ret
  1572. B_InitRelocBuffer endp
  1573. ; -------------------------------------------------------
  1574. ; B_GetRelocationItem -- This routine will return the next
  1575. ; relocation table entry from the exe file being relocated.
  1576. ;
  1577. ; Input: none
  1578. ; Output: AX - offset of relocation item pointer
  1579. ; DX - segment of relocation item pointer
  1580. ; Errors: returns ZR true if end of table and no more items
  1581. ; Uses: AX, DX modified, all other registers preserved
  1582. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  1583. public B_GetRelocationItem
  1584. B_GetRelocationItem proc near
  1585. push si
  1586. ;
  1587. cmp clpRelocItem,0 ;are there any relocation items left?
  1588. jz gtrl90 ;get out if not
  1589. ;
  1590. ; Check if the buffer is empty. The buffer for the relocation table is
  1591. ; at offset RELOC_BUFFER in the buffer rgbXfrBuf1, and is 512 bytes long.
  1592. cmp plpRelocItem,offset RELOC_BUFFER + 512
  1593. jc gtrl40
  1594. ;
  1595. ; The buffer is empty, so we need to read the next part of it in.
  1596. push cx
  1597. push bx
  1598. push dx
  1599. mov ax,clpRelocItem ;number of items left in file
  1600. shl ax,2 ;multiply by size of relocation item
  1601. jc gtrl22 ;check for overflow
  1602. cmp ax,512 ;check if bigger than the buffer
  1603. jc gtrl24
  1604. gtrl22: mov ax,512 ;use buffer size as size of transfer
  1605. gtrl24: mov cx,ax
  1606. mov dx,offset RELOC_BUFFER
  1607. mov plpRelocItem,dx ;pointer to next reloc item to return
  1608. mov bx,fhExeFile
  1609. dossvc 3Fh
  1610. pop dx
  1611. pop bx
  1612. jc gtrl28 ;if error occured
  1613. cmp ax,cx ;or, if we didn't get as much as we asked
  1614. jnz gtrl28 ; for, we have an error
  1615. pop cx
  1616. jmp short gtrl40
  1617. ;
  1618. gtrl28: pop cx
  1619. stc
  1620. jmp short gtrl90
  1621. ;
  1622. ; Get the next relocation item from the buffer.
  1623. gtrl40: mov si,plpRelocItem
  1624. lods word ptr [si] ;get the offset part of the reloc item
  1625. mov dx,ax
  1626. lods word ptr [si] ;get the segment part of the reloc item
  1627. xchg dx,ax ;put offset in AX, and segment in DX
  1628. mov plpRelocItem,si ;store the updated pointer
  1629. dec clpRelocItem ;and bump the count down by 1
  1630. or si,si ;clear the zero flag
  1631. ;
  1632. ; All done.
  1633. gtrl90: pop si
  1634. ret
  1635. B_GetRelocationItem endp
  1636. endif ;DEBUG --------------------------------------------------------
  1637. ; -------------------------------------------------------
  1638. ; GetExeName -- This routine will put a copy of the complete
  1639. ; path name to the dos extender's exe file. In a name
  1640. ; buffer in rgbXfrBuf1.
  1641. ;
  1642. ; Input: none
  1643. ; Output: EXEC_DXNAME buffer updated with complete pathname.
  1644. ; Errors: returns CY set if environment not correctly built.
  1645. ; Uses: all preserved
  1646. assume ds:DGROUP,es:DGROUP,ss:DGROUP
  1647. public GetExeName
  1648. GetExeName proc near
  1649. push ax
  1650. push si
  1651. push di
  1652. push ds
  1653. ; The name of the current program is stored at the end of the environment
  1654. ; table. There are two bytes of 0 to indicate end of table, a byte
  1655. ; with a 1 in it followed by another byte of 0 and then the null terminated
  1656. ; string with the current program name.
  1657. gtxe20: mov ds,segPSP
  1658. assume ds:PSPSEG
  1659. mov ds,segEnviron
  1660. assume ds:NOTHING
  1661. xor si,si
  1662. gtxe22: lods byte ptr [si] ;get next byte from environment
  1663. or al,al ;test if 0
  1664. jnz gtxe22 ;if not, keep looking
  1665. lods byte ptr [si] ;get next byte
  1666. or al,al ;see if it is 0 also
  1667. jnz gtxe22
  1668. ; We have found the double 0 at the end of the environment. So
  1669. ; we can now get the name. At the end of the environment is an
  1670. ; argc, argv construct. (i.e. a word giving the count of strings
  1671. ; followed by an array of strings). Under DOS, argc is always 1,
  1672. ; so check that there is a word of 1 here. If not, this environment
  1673. ; wasn't built correctly and we don't know what is here.
  1674. lods word ptr [si]
  1675. cmp ax,1
  1676. jnz gtxe80
  1677. ; We have the pointer to the name, now copy it.
  1678. mov di,offset EXEC_DXNAME
  1679. call strcpy
  1680. clc
  1681. jmp short gtxe90
  1682. ; We have an error.
  1683. gtxe80: stc ;set error condition flag
  1684. gtxe90: pop ds
  1685. pop di
  1686. pop si
  1687. pop ax
  1688. ret
  1689. GetExeName endp
  1690. ; -------------------------------------------------------
  1691. ; COMMAND LINE PARSING ROUTINES
  1692. ; -------------------------------------------------------
  1693. ; ParseCommandLine -- This function will examine the dos
  1694. ; command line that caused the Dos Extender to be exec'd
  1695. ; and determine what the user wants done. It will set
  1696. ; up the various buffers required for the child program
  1697. ; to be loaded.
  1698. ;
  1699. ; NOTE: the child exe file name read from the command line
  1700. ; is placed in RELOC_BUFFER in the case where the child
  1701. ; name is specified on the command line. This buffer is
  1702. ; used later when reading the relocation table while
  1703. ; performing the fixups on the child.
  1704. ;
  1705. ; Input: none
  1706. ; Output: AL - 0 if empty command line, else non-zero
  1707. ; parse buffers in rgbXfrBuf1 set up.
  1708. ; Errors: none
  1709. ; Uses: AX, all else preserved
  1710. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  1711. public ParseCommandLine
  1712. ParseCommandLine proc near
  1713. push si
  1714. push di
  1715. push ds
  1716. mov ds,segPSP
  1717. assume ds:PSPSEG
  1718. mov si,81h ;pointer to command line in PSP
  1719. ; Skip any white space in front of the child program name.
  1720. prsc12: lods byte ptr [si]
  1721. cmp al,' '
  1722. jz prsc12
  1723. dec si
  1724. ; Copy the command line tail following the program name to the command
  1725. ; line buffer for use when we load the child.
  1726. prsc40: push si ;save current point in parse
  1727. mov di,offset EXEC_CMNDLINE + 1
  1728. xor dl,dl ;count characters in command line tail
  1729. prsc42: lods byte ptr [si] ;get the next character
  1730. stos byte ptr [di] ;store it into the output buffer
  1731. cmp al,0Dh ;is it the end of the line?
  1732. jz prsc44
  1733. inc dl ;count the character
  1734. jmp prsc42
  1735. prsc44: mov es:[EXEC_CMNDLINE],dl ;store the character count
  1736. pop si ;restore the buffer pointer
  1737. ; Now we want to set up the two default FCB's by letting DOS parse the
  1738. ; first two parameters on the command line.
  1739. mov di,offset EXEC_FCB0
  1740. mov al,1
  1741. dossvc 29h
  1742. mov di,offset EXEC_FCB1
  1743. mov al,1
  1744. dossvc 29h
  1745. prsc90:
  1746. pop ds
  1747. pop di
  1748. pop si
  1749. ret
  1750. ParseCommandLine endp
  1751. ; -------------------------------------------------------
  1752. ; strcpy -- copy a null terminated string.
  1753. ;
  1754. ; Input: DS:SI - pointer to source string
  1755. ; ES:DI - pointer to destination buffer
  1756. ; Output: ES:DI - pointer to end of destination string
  1757. ; Errors: none
  1758. ; Uses: DI modified, all else preserved
  1759. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  1760. public strcpy
  1761. strcpy proc near
  1762. push ax
  1763. push si
  1764. stcp10: lods byte ptr [si]
  1765. stos byte ptr [di]
  1766. or al,al
  1767. jnz stcp10
  1768. dec di
  1769. pop si
  1770. pop ax
  1771. ret
  1772. strcpy endp
  1773. ; -------------------------------------------------------
  1774. ; strcmpi -- This function will perform a case insensitive
  1775. ; comparison of two null terminated strings.
  1776. ;
  1777. ; Input: DS:SI - string 1
  1778. ; ES:DI - string 2
  1779. ; Output: ZR if the strings match, else NZ
  1780. ; CY set if string 1 less than string 2
  1781. ; Errors: none
  1782. ; Uses: all registers preserved
  1783. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  1784. public strcmpi
  1785. strcmpi proc near
  1786. push si
  1787. push di
  1788. stcm20: mov al,byte ptr ds:[si]
  1789. call toupper
  1790. mov ah,al
  1791. mov al,byte ptr es:[di]
  1792. call toupper
  1793. cmp ah,al
  1794. jnz stcm90
  1795. or al,ah
  1796. jz stcm90
  1797. inc si
  1798. inc di
  1799. jmp stcm20
  1800. stcm90: pop di
  1801. pop si
  1802. ret
  1803. strcmpi endp
  1804. ; -------------------------------------------------------
  1805. ; IsFileNameChar -- This function will examine the
  1806. ; character in AL and determine if it is a legal character
  1807. ; in an MS-DOS file name.
  1808. ;
  1809. ; Input: AL - character to test
  1810. ; Output: ZR true if character is legal in a file name
  1811. ; Errors: none
  1812. ; Uses: all registers preserved
  1813. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  1814. IsFileNameChar proc near
  1815. push ax
  1816. cmp al,20h ;is it a control character
  1817. jbe isfc80 ;if so, it isn't valid
  1818. cmp al,':'
  1819. jz isfc80
  1820. cmp al,';'
  1821. jz isfc80
  1822. cmp al,','
  1823. jz isfc80
  1824. cmp al,'='
  1825. jz isfc80
  1826. cmp al,'+'
  1827. jz isfc80
  1828. cmp al,'<'
  1829. jz isfc80
  1830. cmp al,'>'
  1831. jz isfc80
  1832. cmp al,'|'
  1833. jz isfc80
  1834. cmp al,'/'
  1835. jz isfc80
  1836. cmp al,'"'
  1837. jz isfc80
  1838. cmp al,'['
  1839. jz isfc80
  1840. cmp al,']'
  1841. jz isfc80
  1842. xor al,al
  1843. jmp short isfc90
  1844. ; Not a valid file name character
  1845. isfc80: or al,0FFh
  1846. isfc90: pop ax
  1847. ret
  1848. IsFileNameChar endp
  1849. ; -------------------------------------------------------
  1850. ; toupper -- This function will convert the character
  1851. ; in AL into upper case.
  1852. ;
  1853. ; Input: AL - character to convert
  1854. ; Output: AL - upper case character
  1855. ; Errors: none
  1856. ; Uses: AL modified, all else preserved
  1857. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  1858. public toupper
  1859. toupper proc near
  1860. cmp al,'a'
  1861. jb toup90
  1862. cmp al,'z'
  1863. ja toup90
  1864. sub al,'a'-'A'
  1865. toup90:
  1866. ret
  1867. toupper endp
  1868. ; -------------------------------------------------------
  1869. DXCODE ends
  1870. ;
  1871. ;****************************************************************
  1872. end