BIOSINIT.A86
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:49k
源码类别:

操作系统开发

开发平台:

Asm

  1. ;    File              : $BIOSINIT.A86$
  2. ;
  3. ;    Description       :
  4. ;
  5. ;    Original Author   : DIGITAL RESEARCH
  6. ;
  7. ;    Last Edited By    : $CALDERA$
  8. ;
  9. ;-----------------------------------------------------------------------;
  10. ;    Copyright Work of Caldera, Inc. All Rights Reserved.
  11. ;      
  12. ;    THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
  13. ;    PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
  14. ;    ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
  15. ;    WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
  16. ;    THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
  17. ;    HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
  18. ;    AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
  19. ;    AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
  20. ;    COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
  21. ;    CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
  22. ;    TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
  23. ;    CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
  24. ;    AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
  25. ;    CIVIL LIABILITY.
  26. ;-----------------------------------------------------------------------;
  27. ;
  28. ;    *** Current Edit History ***
  29. ;    *** End of Current Edit History ***
  30. ;
  31. ;    $Log$
  32. ;    BIOSINIT.A86 1.43 93/12/03 00:38:19
  33. ;    Fix bug in AllocHMA when base not para aligned
  34. ;    BIOSINIT.A86 1.42 93/11/29 21:40:03
  35. ;    Fill in name field of system DMD's (owner=8) with 'SC'
  36. ;    BIOSINIT.A86 1.41 93/11/18 15:43:14 
  37. ;    Add primitive multi-master checking
  38. ;    BIOSINIT.A86 1.40 93/11/11 12:25:29 
  39. ;    VDISK header changes
  40. ;    BIOSINIT.A86 1.39 93/11/08 23:19:22 
  41. ;    SetupHMA does CALL5 initialisation
  42. ;    BIOSINIT.A86 1.38 93/10/29 20:03:48
  43. ;    BIOS relocation services restored for possible 3rd party memory manager use
  44. ;    BIOSINIT.A86 1.37 93/10/29 19:42:27
  45. ;    Change HIDOS default to off
  46. ;    BIOSINIT.A86 1.36 93/09/22 15:22:14
  47. ;    Change int21/4458 to les bx,cs:drdos_ptr (smaller, faster)
  48. ;    BIOSINIT.A86 1.35 93/09/03 20:10:55
  49. ;    Support intl YES/NO
  50. ;    BIOSINIT.A86 1.34 93/09/02 22:34:42
  51. ;    Add header to system allocations
  52. ;    BIOSINIT.A86 1.33 93/09/01 17:36:57
  53. ;    increase stack size for aspi4dos.sys
  54. ;    BIOSINIT.A86 1.31 93/08/06 20:55:16
  55. ;    re-arrange device init order for SCREATE.SYS on a VDISK.SYS
  56. ;    BIOSINIT.A86 1.28 93/08/02 14:45:43
  57. ;    hide preload drives from func_device
  58. ;    ENDLOG
  59. include i:msdos.equ ; DOS Function Equates
  60. include i:psp.def ; PSP Definition
  61. include i:f52data.def ; Internal DOS data area
  62. include i:doshndl.def ; Dummy DOS structures
  63. include config.equ
  64. include i:fdos.equ
  65. include i:modfunc.def
  66. TRUE     equ 0FFFFh       ; value of TRUE
  67. FALSE     equ 0       ; value of FALSE
  68. ;
  69. ; Equates for INIT_FLAGS which can be modified by the BIOS
  70. ; the default is a RAM based BDOS (Code and Data) with INIT_DRV
  71. ; specifing the default drive and the initial drive for COMSPEC
  72. ;
  73. INIT_ROMCODE equ 0001h ; Rom based DOS CODE
  74. INIT_COMSPEC equ 0002h ; COMSPEC_DRV specifies the default
  75. ; Command Processor Drive
  76. INIT_WINDOWS equ 0004h ; Disable windows support
  77. COMMAND_BASE equ 000E0h ; must cover FFFF:D0 for CALL5 fixup
  78. COMMAND_SIZE equ 015C0h
  79. CGROUP GROUP CODE, INITCODE, INITDATA, INITPSP, INITENV, DATAEND
  80. CODE CSEG
  81. eject
  82. ;
  83. ; The DOS Code Segment is formatted as follows.
  84. ;
  85. DOS_OFFSET equ word ptr  .0008h ; Offset of code in segment
  86. HISTORY_CODE equ word ptr  .000Ch ; Start of history code
  87. INIT_CODE equ word ptr  .000Eh ; Start of initialisation code
  88. DOS_FLAG equ word ptr  .001Ch ; Compressed Data Flag
  89. DOS_CODE equ word ptr  .001Eh ; DOS Code Length (Bytes)
  90. DOS_DATA equ word ptr  .0020h ; DOS Data Length (Bytes)
  91. NO_YES_CHARS equ word ptr  .0028h ; DOS Data No/Yes characters
  92. INT31_SEGMENT equ word ptr .00C6h ; DOS Data Segment pointer
  93. ; for ROM systems
  94. JMPF_OPCODE equ 0EAh ; 8086 JMPF instruction
  95. INITCODE CSEG PARA 'INITCODE'
  96. extrn cleanup:near ; BIOS Clean Up routine
  97. extrn config_init:near ; CONFIG Code Init
  98. extrn config_finish:near ; Update DOS with Device Info
  99. extrn config:near ; CONFIG.SYS Processor
  100. extrn crlf:near ; Output CR/LF to screen
  101. extrn resident_device_init:near ; Device Driver Init
  102. extrn read_dos:near ; load DOS file
  103. extrn setup_ldt:near
  104. extrn setup_stacks:near
  105. extrn dos_version_check:near
  106. db 'Copyright (c) 1983,1996 '
  107. db 'Caldera, Inc. All Rights Reserved '
  108. db 'XXXX-0000-987654321X'
  109. Public biosinit
  110. ;========
  111. biosinit:
  112. ;========
  113. ; entry: MEM_SIZE    = memory size in paragraphs
  114. ; DEVICE_ROOT = address of 1st resident device driver
  115. ; INIT_DRV    = boot drive (0 = A:, 1 = B:, etc.)
  116. ; INIT_BUF    = minimum # of disk buffers
  117. ; CURRENT_DOS = code segment of DOS (if loaded)
  118. ; INIT_FLAGS  = Control Flags
  119. ; COMSPEC_DRV = Drive for Command Processor
  120. ;
  121. ;
  122. ; we set up the following variables
  123. ; BIOS_SEG    = low memory BIOS code/data (static)
  124. ; DOS_DSEG    = low memory DOS data area (static)
  125. ; RCODE_SEG   = relocated BIOS code segment
  126. ; DOS_CSEG    = relocated DOS code segment
  127. ; INIT_DSEG   = segment based initialisation data
  128. ;
  129. cld
  130. cli
  131. mov ax,cs ; Initialise our stack and Data Segment
  132. mov ds,ax
  133. mov ss,ax
  134. mov sp,offset stack
  135. sti
  136. mov bios_seg,ax ; Save the BIOS Segment
  137. ; Now some code which allows Remote Program Loader to reserve some memory
  138. ; which will be safe from being trampled on by the system.
  139. ; The RPL takes over Int 2F and has a magic signature "RPL" at offset 3 from
  140. ; it's entry point. If this is detected an Int2f is issued
  141. ;
  142. ; On Entry:
  143. ; AX = 4A06, DX = Segment address of top of memory
  144. ; On Exit:
  145. ; DX = segment address of the RPL
  146. ;
  147. ; On return the system will build a DMD entry for the RPL, with an owner field
  148. ; of 8 (ie. System). The RPL can poke this entry to 0 when it wishes to free
  149. ; the memory.
  150. ;
  151. ; In addition we now look for "RPLOADER", and if found we remember the address
  152. ; of the entry point so we can call it with status information
  153. mov dx,mem_size ; get existing size
  154. dec dx ; one para less for upper mem DMD link
  155. xor ax,ax
  156. mov es,ax ; point to vectors
  157. mov bx,4*2fh ; we want Int 2F vector
  158. les bx,es:dword ptr [bx] ; pick up the contents
  159. lea di,3[bx] ; point to magic signature "RPL"
  160. mov si,offset rpl_name
  161. mov cx,3
  162. repe cmpsb ; does the signature match ?
  163.  jne biosinit20
  164. mov cx,5 ; look also for "RPLOADER"
  165. repe cmpsb
  166.  jne biosinit10
  167. mov rpl_off,bx ; save entry point for use later
  168. mov rpl_seg,es
  169. biosinit10:
  170. mov ax,4a06h ; magic number for RPL
  171. int 2fh ; does anyone want to steal memory ?
  172. inc dx
  173. cmp dx,mem_size ; is memory size unchanged ?
  174.  jnb biosinit20
  175. dec dx ; point back at start of memory
  176. dec dx ;  then one below for DMD start
  177. mov es,dx ; ES points to DMD
  178. mov DMD_ID,IDZ ; make it last in the chain
  179. mov DMD_PSP,8 ; owned by system
  180. lea di,DMD_NAME ; point to name field
  181. mov si,offset rpl_name
  182. mov cx,(length rpl_name)/2
  183. rep movsw ; initialise name field too
  184. inc dx ; skip the DMD for real top
  185. xchg dx,mem_size ; replace memory size with new value
  186. sub dx,mem_size ; whats the difference ?
  187. mov DMD_LEN,dx ; save it's this length
  188. biosinit20:
  189. ; End of RPL support
  190. mov ax,mem_size ; get top of memory
  191. sub ax,MOVE_DOWN
  192. mov mem_max,ax ; last available paragraph
  193. mov init_dseg,ax ; initialisation data lives here
  194. mov cl,4
  195. mov dx,offset DYNAMIC_DATA_END+15
  196. shr dx,cl ; we need this much dynamic data
  197. add ax,dx
  198. ; Now we try to relocate the BIOS
  199. mov dx,rcode_len ; we want to keep this much BIOS code
  200. add systemSize,dx ;  so add to reserved space in HMA
  201. mov dx,icode_len ; how much do we want to move ?
  202. shr dx,cl
  203.  jz biosinit30 ; if ROMed we have nothing to relocate
  204. mov rcode_seg,ax ; relocated BIOS lives here
  205. add ax,dx ; remember how much we allocated
  206. mov dx,rcode_offset
  207. mov si,dx
  208. mov di,dx
  209. shr dx,cl ; DX = para offset of data
  210. sub rcode_seg,dx ; adjust our segment value
  211. mov es,rcode_seg
  212. mov cx,icode_len
  213. rep movsb ; copy it up
  214. biosinit30:
  215. mov dos_cseg,ax ; a relocated DOS image will live here
  216. mov ax,offset biosinit_end+32
  217. mov cl,4 ; Leave the Last Paragraph Free for
  218.     shr ax,cl           ;  himem DMD 
  219. neg ax ; Calculate the destination
  220. add ax,mem_size ; Segment for the BIOS relocation
  221. mov cx,offset biosinit_end ; Relocate the BIOSINIT code to 
  222. mov si,offset biosinit ; the top of available memory
  223. mov di,si
  224. sub cx,si ; Size of BIOSINIT
  225. mov es,ax ; Initialize ES and copy CX words
  226. rep movsb
  227. push es ; fiddle RETF to relocated code
  228. mov ax,offset relocated_init
  229. push ax
  230. retf
  231. ;
  232. ; Generic BIOS INIT Patch area
  233. ;
  234. include i:patch.cod
  235. ;
  236. ; BIOSINIT CODE and DATA have now been relocated to high memory
  237. ;
  238. relocated_init:
  239. mov ax,cs
  240. cli
  241. mov ss,ax
  242. mov sp,offset stack
  243. sti
  244. mov ds,ax ; All Segment registers now point
  245. mov es,ax ; to the relocated BIOSINIT
  246. call config_init ; initialize setup module
  247. call dd_fixup ; fixup relocatable device drivers
  248. les di,device_root ; initialize all the resident
  249. call resident_device_init ;   device drivers
  250. push cs ! pop es
  251. mov dx,1 ; phase one of RPL initialisation
  252. call rploader ;  inform RPLoader if present
  253. call Verify386 ; CY set if not a 386
  254. mov ax,mem_current ; get ending address returned by BIOS
  255.  jc dont_align
  256. cmp ax,0100h
  257.  jae dont_align ; lets be 4 KByte aligned to benefit
  258. mov ax,0100h ;  the multi tasker (386 or above)
  259. dont_align:
  260. mov free_seg,ax ;  and save as first Free Segment
  261. cmp current_dos,0 ; does the OEM want us to read
  262.  jnz dos_reloc ;   the DOS file from disk?
  263. mov ax,dos_cseg
  264. mov current_dos,ax ; the file is held on the INIT_DRV with
  265. call read_dos ;   the name specified in DOS_NAME
  266. eject
  267. ;
  268. ; The following code will relocate the DOS code.
  269. ;
  270. dos_reloc:
  271. ;
  272. ; We now move the DOS data to low memory
  273. ;
  274. mov ax,current_dos
  275. mov dos_cseg,ax ; Update the DOS Code Segment
  276. mov ds,ax
  277. mov cl,4
  278. mov ax,ds:DOS_CODE ; get size of DOS code
  279. add cs:systemSize,ax ;  and add to the system size
  280. shr ax,cl ; convert to para's
  281. mov cs:dosCodeParaSize,ax ; save for EMM386.SYS
  282. mov ax,ds:DOS_OFFSET ; remember we have padding
  283. add cs:dos_coff,ax ;  and adjust DOS init offset
  284. shr ax,cl ; also adjust DOS segment
  285. sub cs:dos_cseg,ax ;  to account for padding
  286. xor ax,ax
  287. mov es,ax ; ES -> interrupt vectors
  288. mov ax,ds:DOS_DATA ; get # of bytes of DOS data
  289. shr ax,cl ; get para size of DOS data
  290. xchg ax,cs:free_seg ; get seg for DOS data
  291. add cs:free_seg,ax ; remember how much we used
  292. mov es:INT31_SEGMENT,ax ; update the segment value of INT31
  293. mov es,ax ;  so ROMMED systems can find PCM_DSEG
  294. mov cs:dos_dseg,ax ; we need to remember where too...
  295. mov si,ds:DOS_CODE ; offset of DOS Data
  296. xor di,di ; destination offset
  297. test DOS_FLAG,1 ; has the DOS Data been compressed
  298.  jnz dos_r20 ; yes so call the decompress routine
  299. mov cx,ds:DOS_DATA ;  otherwise just copy the data.
  300. rep movsb
  301. jmps dos_r40
  302. ;
  303. ; This routine will decompress the DOS data area which has 
  304. ; been compressed after linking using Andy Wightmans data 
  305. ; compression algorithm.
  306. ;
  307. dos_r20:
  308. lodsw ; get control word
  309. mov cx,ax ; as a count
  310.  jcxz dos_r40 ; all done
  311. test cx,8000h ; negative ?
  312.  jnz dos_r30 ; yes do zeros
  313. rep movsb ; else move in data bytes
  314. jmps dos_r20 ; and to the next
  315. dos_r30:
  316. and cx,7fffh ; remove sign
  317.  jcxz dos_r20 ; none to do
  318. xor ax,ax
  319. rep stosb ; fill with zeros
  320. jmps dos_r20
  321. dos_r40:
  322. push cs ! pop ds
  323. push cs ! pop es
  324. mov cl,4 ; reserve space for resident DDSC's
  325. mov ax,DDSC_LEN
  326. mul dev_count ; AX byte are required
  327. add ax,15
  328. shr ax,cl ; AX para are required
  329. xchg ax,free_seg
  330. add free_seg,ax ; we have allocated the space
  331. mov res_ddsc_seg,ax ; point res_ddsc_ptr at the space
  332. mov dx,dos_dseg
  333. sub ax,dx ; DOS resident DDSC_'s use DOS data seg
  334. cmp ax,1000h ; surely we must fit ?
  335.  jae dos_r50
  336. shl ax,cl ; offset within pcmode data segment
  337. mov res_ddsc_off,ax
  338. mov res_ddsc_seg,dx ; setup pointer to resident DDSC's
  339. dos_r50:
  340. ;
  341. ; Call the DOS INIT Code passing all the information setup
  342. ; by the BIOS.
  343. ;
  344. mov ax,mem_size ; pass the Memory Size, the first free
  345. mov bx,free_seg ;  segment and the initial 
  346. mov dl,init_drv ;  drive to the DOS init routine
  347. cli
  348. mov ds,dos_dseg ; DS -> DOS data segment
  349. callf cs:dos_init
  350. mov es,cs:dos_dseg
  351. mov bx,26h ; ES:BX -> list of lists
  352. mov ax,es:word ptr F52_FCBPTR[bx]
  353.     shr ax,1 ! shr ax,1     
  354.     shr ax,1 ! shr ax,1     
  355. and es:word ptr F52_FCBPTR[bx],15
  356. add es:word ptr F52_FCBPTR+2[bx],ax
  357. sti
  358. push cs ! pop ds
  359. mov es,current_dos ; internationalise the yes/no chars
  360. mov di,es:NO_YES_CHARS
  361. mov es,dos_dseg ; ES:DI -> internal table
  362. mov ax,word ptr no_char
  363. stosw ; replace default no chars
  364. mov ax,word ptr yes_char
  365. stosw ; replace default yes chars
  366. push cs ! pop es
  367. add dos_coff,3 ; next dos_init call just fixes up
  368. ;  segment relocations
  369. mov dx,2 ; phase two of RPL initialisation
  370. call rploader ;  inform RPLoader if present
  371. call config_start ; get free memory
  372. call config ; read and process CONFIG.SYS
  373. call config_end ; relocate DOS code and free memory
  374. mov ax,(MS_X_OPEN*256)+2 ; Open for Write
  375. mov dx,offset idle_dev ; Get the IDLE Device Name#
  376. int DOS_INT ; Open the device
  377.  jc dos_r70 ; Quit on Error
  378. push ax ; Save the Handle
  379. mov ax,4458h ; Get the address of the IDLE data
  380. int DOS_INT ; area in ES:AX
  381. pop bx ; Restore the Handle
  382. mov idle_off,ax ; Save the data area offset and 
  383. mov idle_seg,es ; segment
  384. mov ax,4403h
  385. mov dx,offset idle_off
  386. mov cx,DWORD
  387. int DOS_INT
  388. mov ah,MS_X_CLOSE
  389. int DOS_INT
  390. dos_r70:
  391. call mark_system_memory ; ensure any memory we have allocated
  392. ; is marked as system
  393. mov bios_offset,offset cleanup
  394. callf bios ; execute BIOS cleanup code
  395. mov ax,(MS_M_STRATEGY*256)+3
  396. xor bx,bx ; unlink in upper memory region
  397. int 21h
  398. mov dx,3 ; phase three of RPL initialisation
  399. call rploader ;  inform RPLoader if present
  400. mov ax,12ffh ; magic cleanup call to MemMAX
  401. mov bx,5 ;  to do any tidy ups it wishes
  402. xor cx,cx
  403. xor dx,dx
  404. int 2fh
  405. push cs ! pop es
  406. load_e10:
  407. mov ax,(MS_X_EXEC * 256)+0 ; Exec the Command Processor
  408. mov bx,offset exec_env ; Get the Parameter Block Address
  409. mov dx,offset shell ; and the Command Processor
  410. mov exec_clseg,ds
  411. mov exec_fcb1seg,ds
  412. mov exec_fcb2seg,ds
  413. int DOS_INT ; Go for it
  414. mov ah,MS_C_WRITESTR ; Print an error message and wait for
  415. mov dx,offset bad_exec ;  the user to enter new name
  416. int DOS_INT
  417. mov ah,MS_C_READSTR ; get user to input new COMMAND
  418. mov dx,offset shell_ask ;  location
  419. int DOS_INT
  420. call crlf ; tidy up with CR/LF
  421. xor bx,bx
  422. mov bl,shell_end
  423. mov shell[bx],bh ; replace CR with NULL
  424. jmps load_e10
  425. eject
  426. ;
  427. ; Initialise the PSP and inform DOS of the
  428. ; location of the BIOSINIT PSP. The MS_P_SETPSP *MUST* be the first 
  429. ; INT21 function call because the PSP Address is used during the
  430. ; entry code except when the INDOS flag is set and certain function 
  431. ; calls are made.
  432. ;
  433. ; Then open the Resident character devices so that the dynamically
  434. ; devices can output messages to the screen etc.
  435. config_start:
  436. mov cl,4
  437. mov bx,ds
  438. mov ax,offset psp ; Now force DOS Plus to use the 
  439. shr ax,cl ; internal PSP for all disk and
  440. add bx,ax ; character I/O
  441. mov xftbl_seg,bx ; Update the Handle Table Pointer
  442. mov parent_psp,bx ; and make this the root process
  443. mov ah,MS_P_SETPSP ; Set the current PSP
  444. int DOS_INT
  445. if DOS5
  446. mov ax,3306h
  447. int 21h ; get true version
  448. mov dosVersion,bx ; and plant in initial PSP
  449. endif
  450. call dos_version_check ; make sure we are on correct DOS
  451. mov ax,4458h
  452. int DOS_INT ; we need to access local data
  453. mov drdos_off,bx ; so save a pointer to it
  454. mov drdos_seg,es
  455. mov ax,ext_mem_size
  456. mov es:DRDOS_EXT_MEM[bx],ax ; save extended memory size in DOS
  457. mov ax,5200h
  458. int DOS_INT
  459. mov func52_off,bx
  460. mov func52_seg,es ; save pointer to internal data
  461. if DOS5
  462. mov ax,ext_mem_size
  463. mov es:F52_EXT_MEM[bx],ax ; save extended memory size in DOS
  464. endif
  465. mov ax,(offset TEMP_LDT)/16 ; use our temporary LDT's
  466. add ax,init_dseg ;  during system init
  467. mov es:F52_PATHOFF[bx],0 ; point at the LDT's
  468. mov es:F52_PATHSEG[bx],ax
  469. push cs ! pop es
  470. mov ah,MS_M_ALLOC ; Allocate all available memory
  471. mov bx,0FFFFh ; BX is returned with the maximum
  472. int DOS_INT ; available block size
  473. mov ah,MS_M_ALLOC
  474. int DOS_INT
  475. mov mem_first_base,ax ; Base of 1st allocated block
  476. mov mem_current_base,ax ; Base of allocated memory
  477. mov mem_current,ax ; Next available Segment
  478. call config_finish ; Update DOS with the information
  479. ; obtained from loading the resident
  480. ; drivers.
  481. mov ah,MS_DRV_SET ; Select the Default Drive
  482. mov dl,init_drv ; passed to us by the BIOS
  483. int DOS_INT
  484. mov ah,MS_F_DMAOFF ; Initialise the DMA address for 
  485. mov dx,offset search_state ; the Search First State data
  486. int DOS_INT
  487. mov al,init_drv ; get the boot drive then check
  488. test init_flags,INIT_COMSPEC ; flags to see if this is the
  489.  jz config_s05 ; default COMSPEC drive.
  490. mov al,comspec_drv
  491. config_s05:
  492. add shell,al ; update the drive letter of shell
  493. add shell_drv,al ;  and the reload path
  494. call open_stdaux ; Open STDAUX as internal handle #0
  495. call open_stdcon ; Open Standard CON Devices as #1
  496. mov ah,MS_X_CLOSE ; now close AUX again
  497. mov bx,STDAUX ; for CONFIG processing
  498. int DOS_INT
  499. ret
  500. ;
  501. ; Relocate the DOS CODE from high memory to immediately above
  502. ; the device drivers, buffers etc. Then call the DOS_CLEANUP code
  503. ; so that any self segment pointers maintained in the DOS DATA
  504. ; can be updated. Then free all the unused memory and reopen the
  505. ; standard devices.
  506. ;
  507. config_end:
  508. push es
  509. mov al,last_drv ; get lastdrive value
  510. les bx,func52_ptr
  511. cmp al,es:F52_PHYDRV[bx] ; less than the # of Physical drives ?
  512.  ja config_end10
  513. mov al,es:F52_PHYDRV[bx] ; ensure minimum of # physical drives
  514. config_end10:
  515. mov es:F52_LASTDRV[bx],al ; set # of drives installed
  516. mov cl,4 ; we will be converting byte-paras
  517. mov ah,LDT_LEN ; we need this many bytes per drive
  518. mul ah ; *lastdrive
  519. add ax,15 ; round LDT's size up to para
  520. shr ax,cl
  521. mov dl,'L' ; allocate LDT's
  522. call alloc_instseg ; Allocate memory AX is destination
  523. mov es:F52_PATHOFF[bx],0 ; point at the LDT's
  524. mov es:F52_PATHSEG[bx],ax ; save seg we just allocated
  525. pop es
  526. call setup_ldt ; initialise LDT structures
  527. call setup_stacks ; allocate stacks
  528. call relocate_system ; relocate system as requested
  529. push es ; Free all of the unused memory
  530. mov es,mem_current_base ; ES: Base Allocated Memory
  531. mov bx,mem_current ; Get the currently allocated memory
  532. sub bx,mem_current_base ; and subtract mem_current_base to
  533. mov ah,MS_M_SETBLOCK ; give the number of paragraphs used
  534. int DOS_INT ; and modify block accordingly
  535. ; Kludge - if the CONFIG file has had a line of the form INSTALL= to load a TSR
  536. ; then that TSR will have inherited the handles, so bumping the open count, but
  537. ; the func 31 exit leaves all these files open. As a result we will get the
  538. ; wrong internal file numbers unless we force complete closure. So we keep
  539. ; trying to close each internal handle until we get an error.
  540. mov ah,MS_P_GETPSP
  541. int DOS_INT ; get current PSP
  542. mov es,bx
  543. mov cx,PSP_XFNMAX ; Close all the standard handles
  544. les di,PSP_XFTPTR ; and then reopen them in case a
  545. mov bx,0 ; dynamicly loadable device has
  546. cfg_e10: ; replaced the BIOS driver
  547. mov dl,es:[di+bx] ; save old internal handle
  548. mov ah,MS_X_CLOSE
  549. int DOS_INT ; try and close this handle
  550. mov es:[di+bx],dl ; put the internal handle back 
  551.  jnc cfg_e10 ; and try and close it again
  552. mov es:byte ptr [di+bx],0ffh
  553. inc bx ; mark as closed and try next handle
  554. loop cfg_e10
  555. pop es
  556. ;; jmps open_std
  557. open_std:
  558. call open_stdaux ; open AUX device as STDAUX
  559. call open_stdcon ; now STDIN, STDOUT, STDERR
  560. ; jmp open_stdprn ; finally STDPRN
  561. open_stdprn:
  562. mov ax,(MS_X_OPEN * 256) + 1
  563. mov dx,offset printer ; Open the PRN device
  564. int DOS_INT
  565.  jc open_sp10 ; No PRN device
  566. cmp ax,STDPRN ; If all the previous Opens were
  567.  jz open_sp10 ; successful then this is STDPRN
  568. mov bx,ax ; otherwise force this to STDPRN
  569. mov cx,STDPRN
  570. mov ah,MS_X_DUP2
  571. int DOS_INT
  572. mov ah,MS_X_CLOSE
  573. int DOS_INT
  574. open_sp10:
  575. ret
  576. open_stdcon:
  577. mov ax,(MS_X_OPEN * 256) + 2
  578. mov dx,offset console ; Open the CON device
  579. int DOS_INT
  580.  jc open_sc10 ; No CON device
  581. mov bx,ax ; First Open should be STDIN
  582. mov cx,STDOUT ; Force Duplicate to STDOUT
  583. mov ah,MS_X_DUP2
  584. int DOS_INT
  585. mov cx,STDERR ; Then Force Duplicate to STDERR
  586. mov ah,MS_X_DUP2
  587. int DOS_INT
  588. open_sc10:
  589. ret
  590. open_stdaux:
  591. mov ax,(MS_X_OPEN * 256) + 2
  592. mov dx,offset auxilary ; Open the AUX device
  593. int DOS_INT ; to get internal handle 0
  594.  jc open_sa10 ; No AUX device
  595. mov bx,ax ; Force DUP to STDAUX
  596. mov cx,STDAUX
  597. mov ah,MS_X_DUP2
  598. int DOS_INT
  599. mov ah,MS_X_CLOSE
  600. int DOS_INT
  601. open_sa10:
  602. ret
  603. eject
  604. relocate_system:
  605. push ds ! push es
  606. cmp dos_target_seg,0FFFFh ; is the OS going high ?
  607.  jne relocate_system10
  608. call SetupHMA ; make sure HMA chain is established
  609. xor cx,cx
  610. xchg cx,systemHMA ; free up any space reserved for the OS
  611. call FreeHMA
  612. call ReserveCommandHMA ; reserve space for COMMAND.COM
  613. relocate_system10:
  614. call reloc_bios ; move down relocatable drivers
  615. call reloc_dos ; move DOS above drivers if RAM based
  616. xor cx,cx
  617. xchg cx,commandHMA
  618. call FreeHMA ; return command.com HMA space to pool
  619. cli
  620. mov ds,dos_dseg ; DS -> DOS data segment
  621. callf cs:dos_init ; (in case of CS relative fixups)
  622. sti
  623. pop es ! pop ds
  624. ret
  625. eject
  626. reloc_dos: ; move DOS down to just above drivers
  627. ;----------
  628. push ds
  629. push es
  630. test init_flags,INIT_ROMCODE ; Run the DOS code in ROM
  631.  jz $+5 ! jmp reloc_dos90 ; at CURRENT_DOS - No Code Reloc
  632. mov es,current_dos
  633. mov cx,es:DOS_CODE ; get DOS code size in bytes
  634. mov ax,dos_target_seg ; get DOS target
  635. cmp ax,0FFFFh ; it it seg FFFF ?
  636.  jne reloc_dos10
  637. mov es,current_dos
  638. mov dx,es:DOS_OFFSET
  639. call AllocHMA ; allocate CX bytes, offset < DX
  640.  jnc reloc_dos50 ;  if we can use high memory
  641. xor ax,ax ; can't, so try auto-allocation
  642. reloc_dos10:
  643. test ax,ax ; has a specific address been
  644.  jnz reloc_dos40 ;  specified ?
  645. push cx ; save DOS code size
  646. xchg ax,cx
  647. mov cl,4
  648. shr ax,cl ; convert to paragraphs
  649. pop cx
  650. cmp hidos,0 ; do we want to relocate DOS ?
  651.  je reloc_dos20 ;  no, allocate conventionally
  652. call alloc_upper ;  else allocate space for the DOS
  653.  jnc reloc_dos40 ;  in upper memory if possible
  654. reloc_dos20:
  655. mov es,current_dos ; if conventional memory we
  656. mov ax,es:INIT_CODE ;  can discard INIT code
  657. cmp history_flg,0 ; is history enabled ?
  658.  jne reloc_dos30
  659. mov ax,es:HISTORY_CODE ; no, discard history code as well
  660. reloc_dos30:
  661. push cx
  662. add ax,15
  663. mov cl,4 ; convert to paragraphs
  664. shr ax,cl
  665. pop cx
  666. call alloc_seg_with_padding ; allocate in conventional memory
  667. reloc_dos40:
  668. xchg ax,dx ; save segment address
  669. mov es,current_dos ; point at code
  670. mov ax,es:DOS_OFFSET ; get offset of code start
  671. xor di,di
  672. mov es,dx ; ES:DI -> destination address
  673. push cx ; save DOS size
  674. mov cl,4
  675. shr ax,cl ; AX = header size in para's
  676. sub dx,ax ; adjust DOS segment accordingly
  677. pop cx ; CX = DOS size in bytes
  678. reloc_dos50:
  679. ; At this point
  680. ; CX = # bytes to move
  681. ; ES:DI -> destination
  682. ; DX = segment to fixup
  683. ;
  684. mov dos_cseg,dx ; new code segment for DOS
  685. mov ds,current_dos ; DS -> DOS code
  686. xor si,si
  687. shr cx,1 ; CX = # of words in DOS
  688. rep movsw ; copy DOS down
  689. reloc_dos90: ; fixups performed
  690. pop es
  691. pop ds
  692. ret
  693. Public HookInt2F
  694. HookInt2F:
  695. ;---------
  696. ; Hook Int 2F during device driver initialisation so we can intercept
  697. ; some broadcasts
  698. ; On Entry:
  699. ; None (beware DS/ES can be anything)
  700. ; On Exit:
  701. ; None (All regs preserved)
  702. ;
  703. push es
  704. push ax
  705. push bx
  706. les bx,cs:drdos_ptr
  707. mov bx,es:DRDOS_INT2F[bx] ; ES:BX -> Int 2F hooks
  708. mov ax,offset Int2FHandler
  709. xchg ax,es:4[bx] ; get Int 2F offset
  710. mov cs:int2FOff,ax
  711. mov ax,cs
  712. xchg ax,es:6[bx] ; get Int 2F segment
  713. mov cs:int2FSeg,ax
  714. pop bx
  715. pop ax
  716. pop es
  717. ret
  718. Public UnhookInt2F
  719. UnhookInt2F:
  720. ;-----------
  721. ; Device driver initialisation has finished, so unhook from Int 2F
  722. ; On Entry:
  723. ; None (beware DS/ES can be anything)
  724. ; On Exit:
  725. ; None (All regs preserved)
  726. ;
  727. push es
  728. push ax
  729. push bx
  730. les bx,cs:drdos_ptr
  731. mov bx,es:DRDOS_INT2F[bx] ; ES:BX -> Int 2F hooks
  732. mov ax,cs:int2FOff
  733. mov es:4[bx],ax ; restore Int 2F offset
  734. mov ax,cs:int2FSeg
  735. mov es:6[bx],ax ; restore Int 2F segment
  736. pop bx
  737. pop ax
  738. pop es
  739. ret
  740. ; During device driver init we provide some services on Int 2F
  741. ; eg. 12FF for EMM386.SYS and 4A01/4A02 for Windows HIMEM.SYS
  742. Int2FHandler:
  743. ;------------
  744. ; On Entry:
  745. ; callers DS on stack
  746. ; On Exit:
  747. ; if not handled pass on to BIOS, callers DS on stack, all regs preserved
  748. ;
  749. pop ds ; pop DS from stack
  750. cmp ax,4A01h ; Query Free HMA Space ?
  751.  je HMAQueryFree
  752. cmp ax,4A02h ; Allocate HMA Space ?
  753.  je HMAAlloc
  754. cmp ax,12FFh ; is it a relocation service ?
  755.  jne OldInt2F
  756. sti ; if we RETF don't leave IF disabled
  757. cmp bx,9 ; register upper memory link
  758.  je DOSUpperMemoryRoot
  759. cmp bx,1 ; Relocate BDOS
  760.  jb DOSQuerySize ; what's the size of DOS
  761.  je DOSRelocate ; where to put it
  762. cmp bx,3 ; Relocate BIOS
  763.  jb BIOSQuerySize ; what's the size of BIOS
  764.  je BIOSRelocate ; where to put it
  765. OldInt2F:
  766. push ds ; DS on stack as expected
  767. db JMPF_OPCODE
  768. int2FOff dw 0
  769. int2FSeg dw 0
  770. ; Enquire DOS size
  771. DOSQuerySize:
  772. ;------------
  773. ; On Entry:
  774. ; None
  775. ; On Exit:
  776. ; AX = 0
  777. ; DX = DOS Size in para's
  778. ;
  779. mov dx,cs:dosCodeParaSize ; DX = para's required for DOS code
  780. jmps RelocExit
  781. ; Relocate DOS
  782. DOSRelocate:
  783. ;-----------
  784. ; On Entry:
  785. ; DX = para to reloacte to (FFFF=HMA)
  786. ; On Exit:
  787. ; AX = 0
  788. ;
  789. mov cs:dos_target_seg,dx ; save where
  790. jmps RelocExit
  791. ; Enquire BIOS size
  792. BIOSQuerySize:
  793. ;-------------
  794. ; On Entry:
  795. ; None
  796. ; On Exit:
  797. ; AX = 0
  798. ; DX = BIOS Size in para's
  799. ;
  800. mov dx,cs:rcode_len ; DX = bytes required for BIOS code
  801. add dx,15
  802. mov cl,4
  803. shr dx,cl ; DX para's required
  804. jmps RelocExit
  805. ; Relocate BIOS
  806. BIOSRelocate:
  807. ;------------
  808. ; On Entry:
  809. ; DX = para to reloacte to (FFFF=HMA)
  810. ; On Exit:
  811. ; AX = 0
  812. ;
  813. mov cs:bios_target_seg,dx ; save where
  814. ; jmps RelocExit
  815. RelocExit:
  816. xor ax,ax ; indicate success
  817. retf 2
  818. DOSUpperMemoryRoot:
  819. ;------------------
  820. les bx,cs:drdos_ptr
  821. mov es:DRDOS_DMD_UPPER[bx],dx ; remember upper memory link
  822. if DOS5
  823. les bx,cs:func52_ptr
  824. mov es:F52_DMD_UPPER[bx],dx ; remember upper memory link
  825. endif
  826. xor ax,ax
  827. retf 2
  828. HMAAlloc:
  829. ;--------
  830. ; On Entry:
  831. ; BX = # bytes to allocate
  832. ; On Exit:
  833. ; ES:DI -> start of allocated block
  834. ; BX trashed
  835. ;
  836. push ds
  837. push ax
  838. push cx
  839. push dx
  840. push si
  841. push bp
  842. push cs ! pop ds ; establish data seg
  843. mov cx,bx ; CX = bytes wanted
  844. mov dx,0FFFFh ; anywhere is OK
  845. call AllocHMA ; ES:DI -> allocated data
  846. pop bp
  847. pop si
  848. pop dx
  849. pop cx
  850. pop ax
  851. pop ds
  852. iret
  853. HMAQueryFree:
  854. ;------------
  855. ; On Entry:
  856. ; None
  857. ; On Exit:
  858. ; BX = Size of block remaining (0 if no HMA)
  859. ; ES:DI -> start of available HMA (FFFF:FFFF if no HMA)
  860. ;
  861. push ds
  862. push ax
  863. push cx
  864. push dx
  865. push si
  866. push bp
  867. push cs ! pop ds ; establish data seg
  868. call SetupHMA ; allocate the HMA for OS use
  869. les bx,cs:drdos_ptr
  870. mov di,es:DRDOS_HIMEM_ROOT[bx]
  871. mov ax,0FFFFh ; get offset of HMA entry
  872. mov es,ax
  873. test di,di ; do we have a himem root ?
  874.  jz HMAQueryFree10 ; no, return failure
  875. mov bx,es:2[di] ; BX = size of region
  876. mov ax,di ; para align the base
  877. add ax,15 ; because the allocation will
  878. and ax,not 15
  879. sub ax,di ; AX bytes left in the para
  880. add di,ax ; bias the starting location
  881. sub bx,ax ; that many less available
  882.  ja HMAQueryFree20 ; if non-zero, return it
  883. HMAQueryFree10:
  884. xor bx,bx ; BX = zero on failure
  885. mov di,0FFFFh ; ES:DI -> FFFF:FFFF
  886. HMAQueryFree20:
  887. pop bp
  888. pop si
  889. pop dx
  890. pop cx
  891. pop ax
  892. pop ds
  893. iret
  894. Public AllocHMA
  895. AllocHMA:
  896. ;--------
  897. ; On Entry:
  898. ; CX = bytes to allocate
  899. ; DX = offset of allocation
  900. ; On Exit:
  901. ; CY set if no can do and ES:DI = FFFF:FFFF
  902. ; else
  903. ; ES:DI -> memory allocated (para aligned)
  904. ; CX preserved
  905. ; DX = segment to fixup
  906. ;
  907. les bx,cs:drdos_ptr
  908. mov di,es:DRDOS_HIMEM_ROOT[bx]
  909. test di,di ; have we a HIMEM chain ?
  910.  jz AllocHMA20
  911. cmp di,dx ;  low enough for us
  912.  ja AllocHMA20
  913. mov ax,0FFFFh ; relocate to magic segment
  914. mov es,ax ; lets examine high memory
  915. mov ax,es:2[di] ; get size of himem entry
  916. mov si,es:[di] ;  and get himem link
  917. mov bx,di
  918. add bx,15
  919. and bx,not 15 ; BX is now para aligned
  920. sub bx,di ; BX is bytes left in para
  921. sub ax,bx ; so we only have this much
  922.  jc AllocHMA20 ;  less than a para ?
  923. add di,15 ; para align the base, dropping
  924. and di,not 15 ;  non-aligned bit on floor
  925. cmp ax,cx ; is himem entry big enough ?
  926.  jb AllocHMA20 ; no, allocate from 1st MByte
  927.  je AllocHMA10 ; just made it!
  928. sub ax,cx ; how much is left
  929. cmp ax,2*WORD ; is it to small to keep ?
  930.  jb AllocHMA10 ; no, discard the remainder
  931. mov bx,di ; point to new entry
  932. add bx,cx ;  this many byte up
  933. mov es:[bx],si ; fill in link field
  934. mov es:2[bx],ax ;  and length
  935. mov si,bx ; make this new root
  936. AllocHMA10:
  937. push cx ; save length of CODE
  938. push dx ;  and offset of CODE
  939. les bx,cs:drdos_ptr
  940. mov es:DRDOS_HIMEM_ROOT[bx],si
  941. pop ax ; AX = offset of CODE
  942. mov cl,4
  943. shr ax,cl ; make it paras
  944. mov dx,0ffffh
  945. mov es,dx ; ES:DI -> destination of CODE
  946. mov dx,di
  947. mov cl,4
  948. shr dx,cl ; DX = offset from FFFF in para's
  949. dec dx ; DX = offset from 10000
  950. sub dx,ax ; DX = fixup segment
  951. pop cx ; CX = bytes to move
  952. clc ; made it!
  953. ret
  954. AllocHMA20:
  955. mov di,0FFFFh ; set ES:DI = FFFF:FFFF
  956. mov es,di
  957. stc ; can't do it
  958. ret
  959. Public SetupHMA
  960. SetupHMA:
  961. ;--------
  962. ; We have a client for the high memory area at segment FFFF
  963. ; We should try and setup a high memory free chain
  964. ; XMS only supports allocation of the complete area, so try and grab
  965. ;  it all and do our own sub-allocations within it.
  966. ;
  967. push es
  968. les bx,cs:drdos_ptr
  969. cmp es:DRDOS_HIMEM_ROOT[bx],0; do we already have a chain ?
  970.  jnz SetupHMA10 ;  if so skip XMS allocation
  971. mov ax,4300h ; check for XMS installation
  972. int 2fh
  973. cmp al,80h
  974.  jne SetupHMA20
  975. mov ax,4310h ; get address of XMS driver
  976. int 2fh
  977. mov word ptr xms_driver,bx
  978. mov word ptr xms_driver+2,es
  979. mov ah,0 ; version number check
  980. callf xms_driver
  981. cmp dx,1 ; does HiMem exist ?
  982.  jne SetupHMA20
  983. mov ah,1 ; allocate whole HiMem
  984. mov dx,0ffffh
  985. callf xms_driver
  986. cmp ax,1 ; did we succeed ?
  987.  jne SetupHMA20
  988. mov ah,3 ; enable a20 gate
  989. callf xms_driver
  990. cmp ax,1 ; did we succeed ?
  991.  jne SetupHMA20
  992. les bx,cs:drdos_ptr
  993. mov es:DRDOS_HIMEM_ROOT[bx],COMMAND_BASE
  994. mov ax,0FFFFh ; one entry of FFF0 bytes covers
  995. mov es,ax ;  the complete HMA
  996. inc ax
  997. mov es:word ptr .COMMAND_BASE,ax
  998. mov es:word ptr .COMMAND_BASE+2,-COMMAND_BASE
  999. mov di,10h ; copy a dummy VDISK header
  1000. mov si,offset dummyVDISK
  1001. mov cx,10h
  1002. rep movsw ; copy up 0x20 bytes
  1003. push ds ; now fixup JMPF in hi-memory for CALL5
  1004. mov ds,ax ;  link for PC-NFS
  1005. mov si,4*30h ; DS:SI -> Int 30 vector
  1006. lea di,10h[si] ; ES:DI -> himem alias
  1007. movsw ! movsw ! movsb ; copy the JMPF
  1008. pop ds
  1009. SetupHMA10:
  1010. les bx,cs:drdos_ptr ; private data area in ES:BX
  1011. mov dx,COMMAND_BASE
  1012. cmp dx,es:DRDOS_HIMEM_ROOT[bx]
  1013.  jne SetupHMA20 ; should we be reserving space for OS?
  1014. mov cx,systemSize ; we should reserve this much
  1015. call ReserveHMA ;  for the OS in the HMA
  1016.  jc SetupHMA20
  1017. mov systemHMA,ax ; save for re-use
  1018. SetupHMA20:
  1019. pop es
  1020. ret
  1021. Public alloc_instseg
  1022. alloc_instseg:
  1023. ; allocate AX paragraphs for data that will have to be instanced during
  1024. ; multitasking. if Vladivar kernel available ask that, or else just
  1025. ; try for normal upper memory
  1026. push ax
  1027. push bx ; save registers
  1028. push cx
  1029. mov cx,F_Version ; is the multi-tasker loaded ?
  1030. mov ax,OS386_FUNC
  1031. int OS386_INT
  1032. int 2Fh ; check for Vladivar
  1033. test cx,cx ; CX=0 if it's there
  1034. pop cx
  1035. pop bx
  1036. pop ax
  1037.  jnz alloc_hiseg ; no, allocate normally
  1038. push ax
  1039. push bx
  1040. push cx
  1041. push dx
  1042. mov dx,ax ; DX = paragraphs required
  1043. mov cx,F_RealAllocI ; ask nicely for memory
  1044. mov ax,OS386_FUNC
  1045. int OS386_INT
  1046. pop dx
  1047. pop cx
  1048. pop bx
  1049.  jc alloc_intseg10 ; did we get any ?
  1050. add sp,WORD
  1051. clc ; we've done it !!
  1052. ret
  1053. alloc_intseg10:
  1054. pop ax ; we didn't manage it...
  1055. ; jmp alloc_hiseg
  1056. Public alloc_hiseg
  1057. alloc_hiseg:
  1058. ; allocate AX paragraphs in high memory if possible, otherwise allocate
  1059. ; it in conventional memory
  1060. cmp hidos,0 ; do we want to relocate DOS ?
  1061.  je alloc_seg ;  no, allocate conventionally
  1062. call alloc_upper ; try to allocate some upper memory
  1063.  jc alloc_seg ;  can't, so allocate conventional
  1064. ret ;  else return address of allocated mem
  1065. alloc_seg_with_padding:
  1066. ; On Entry:
  1067. ; AX = para's required
  1068. ; DX = minimum acceptable offset
  1069. ; On Exit:
  1070. ; AX = base para
  1071. ;
  1072. ; If gate A20 is enabled we can't use negative offset's for DOS/BIOS so
  1073. ; we pad conventional memory to avoid this. Avoid seg=0 while here.
  1074. push cx
  1075. push dx
  1076. add dx,15+16 ; DX is the offset we will be using
  1077. mov cl,4 ;  so make sure base is high enough
  1078. shr dx,cl ; convert "offset" to a segment value
  1079. cmp dx,mem_current ;  make sure we don't generate a
  1080.  jbe alloc_seg_nopad ;  negative segement value as this
  1081. mov mem_current,dx ;  will crash if a20 enabled
  1082. alloc_seg_nopad: ; pad if necessary
  1083. mov dl,'M' ; allocate for DOS
  1084. call alloc_seg ; now we can allocate OK
  1085. pop dx
  1086. pop cx
  1087. ret
  1088. Public alloc_seg
  1089. alloc_seg:
  1090. ;---------
  1091. ; On Entry:
  1092. ; AX = para's required
  1093. ; DL = subsegment type
  1094. ; On Exit:
  1095. ; AX = base para
  1096. ;
  1097. push ds
  1098. push cx
  1099. mov cx,ax ; remember how much was wanted
  1100. inc ax ; allow an extra para for a header
  1101. add ax,mem_current ; Return a pointer to AX paragraphs
  1102. cmp ax,mem_max ; of memory to the calling routine.
  1103.  jae alloc_s10
  1104. xchg ax,mem_current
  1105. mov ds,ax ; DS:0 -> header
  1106. inc ax ; AX:0 -> buffer
  1107. mov ds:DMD_ID,dl ; remember the type
  1108. mov ds:DMD_PSP,ax ; owner = itself
  1109. mov ds:DMD_LEN,cx ; size in para
  1110. xor cx,cx ; zero rest for cosmetic reasons
  1111. mov ds:word ptr DMD_NAME-3,cx
  1112. mov ds:word ptr DMD_NAME-2,cx
  1113. mov ds:word ptr DMD_NAME,'S'+256*'D'
  1114. mov ds:word ptr DMD_NAME+2,cx
  1115. mov ds:word ptr DMD_NAME+4,cx
  1116. mov ds:word ptr DMD_NAME+6,cx
  1117. pop cx
  1118. pop ds
  1119. ret
  1120. alloc_s10:
  1121. hlt ; ##jc##
  1122. jmps alloc_s10
  1123. alloc_upper:
  1124. ;-----------
  1125. ; On Entry:
  1126. ; AX = paragraphs required
  1127. ; On Exit:
  1128. ; CY clear:  AX = paragraphs address of allocated memory
  1129. ; CY set: cannot allocate memory (All regs preserved)
  1130. ;
  1131. push bx
  1132. push ax ; save para required
  1133. cmp himem_base,0 ; we have already allocated some ?
  1134.  je alloc_upper10 ; nothing to grow, allocate new block
  1135. mov bx,himem_size ; himem was this big
  1136. add bx,ax ; try and extend it
  1137. push es
  1138. mov es,himem_base ; point at existing himem
  1139. mov ah,MS_M_SETBLOCK ; and try and set to new size
  1140. int DOS_INT
  1141. pop es
  1142.  jc alloc_upper10 ; can't grow, so allocate new block
  1143. mov ax,himem_base
  1144. add ax,himem_size ; return seg above old alloc
  1145. pop bx ; recover para required
  1146. add himem_size,bx ; add into himem size
  1147. pop bx
  1148. clc ; success..
  1149. ret ; return AX = seg
  1150. alloc_upper10:
  1151. mov ax,(MS_M_STRATEGY*256)+1; set allocation strategy
  1152. mov bl,41h ;  to best fit, high only
  1153. int DOS_INT
  1154. pop bx ! push bx ; recover para required in BX
  1155. mov ah, MS_M_ALLOC ;  and try to allocate them
  1156. int DOS_INT
  1157. pushf ! push ax ; save CF and possible address
  1158. mov ax,(MS_M_STRATEGY*256)+1; set allocation strategy
  1159. mov bl,0 ;  to first fit
  1160. int DOS_INT
  1161. pop ax ! popf ; restore CF and possible address
  1162.  jc alloc_upper20 ; can't allocate, use conventional
  1163. cmp ax,mem_size ; is it from upper memory ?
  1164.  ja alloc_upper15 ; yes, we can use it
  1165. push es ; it's conventional, free it up
  1166. mov es,ax ;  seg address in ES
  1167. mov ah,MS_M_FREE
  1168. int DOS_INT ; free up this memory
  1169. pop es
  1170. jmps alloc_upper20 ; try again with XMS
  1171. alloc_upper15:
  1172. mov himem_base,ax ; save base value
  1173. pop himem_size ; save size
  1174. pop bx ; and return seg in AX
  1175. clc ; success..
  1176. ret
  1177. alloc_upper20:
  1178. pop ax
  1179. pop bx ; restore regs
  1180. push ds ! push es
  1181. push bx ! push cx ! push dx ! push si ! push di ! push bp
  1182. push ax ; save allocation size
  1183. mov ax,4300h ; check for XMS installation
  1184. int 2fh
  1185. cmp al,80h
  1186.  jne alloc_upper30
  1187. mov ax,4310h ; get address of XMS driver
  1188. int 2fh
  1189. mov word ptr xms_driver,bx
  1190. mov word ptr xms_driver+2,es
  1191. pop dx ! push dx ; DX = allocation size
  1192. mov ah,10h ; allocate upper memory block
  1193. callf xms_driver
  1194. cmp ax,1 ; did we succeed ?
  1195.  jne alloc_upper30
  1196. pop ax ; recover allocation size
  1197. mov ax,bx ; return para address of himem
  1198. pop bp ! pop di ! pop si ! pop dx ! pop cx ! pop bx
  1199. pop es ! pop ds
  1200. clc ; success
  1201. ret
  1202. alloc_upper30:
  1203. pop ax ; recover allocation size
  1204. pop bp ! pop di ! pop si ! pop dx ! pop cx ! pop bx
  1205. pop es ! pop ds
  1206. stc ; failure....
  1207. ret
  1208. mark_system_memory:
  1209. ;------------------
  1210. ; ensure any memory we have allocated is owned by PSP 0008, a magic value
  1211. ;  used to indicate system memory
  1212. push es
  1213. les bx,func52_ptr ; get internal data in ES:BX
  1214. mov es,es:F52_DMDROOT[bx] ; get 1st DMD entry
  1215. mov ah,MS_P_GETPSP
  1216. int DOS_INT ; get our PSP in BX
  1217. mark_sm10:
  1218. cmp es:DMD_ID,'M'
  1219.  je mark_sm20 ; check we have a valid DMD
  1220. cmp es:DMD_ID,'Z'
  1221.  jne mark_sm50 ; stop if we don't
  1222. mark_sm20:
  1223. cmp bx,es:DMD_PSP ; is it ours ??
  1224.  jne mark_sm30
  1225. mov es:DMD_PSP,0008 ; mark as system
  1226. mark_sm30:
  1227. cmp es:DMD_PSP,0008 ; if system mark as SC
  1228.  jne mark_sm40
  1229. xor ax,ax ; zero rest for cosmetic reasons
  1230. mov ds:word ptr DMD_NAME-3,ax
  1231. mov ds:word ptr DMD_NAME-2,ax
  1232. mov ds:word ptr DMD_NAME,'S'+256*'C'
  1233. mov ds:word ptr DMD_NAME+2,ax
  1234. mov ds:word ptr DMD_NAME+4,ax
  1235. mov ds:word ptr DMD_NAME+6,ax
  1236. mark_sm40:
  1237. cmp es:DMD_ID,'Z' ; is it the last DMD ?
  1238.  je mark_sm50 ;  then stop
  1239. mov ax,es
  1240. inc ax ; skip DMD header and add
  1241. add ax,DMD_LEN ;  length to find next DMD
  1242. mov es,ax
  1243. jmps mark_sm10 ; now go and look at that
  1244. mark_sm50:
  1245. pop es
  1246. ret
  1247. ; Relocate the BIOS code from top of memory
  1248. reloc_bios:
  1249. mov dx,rcode_offset
  1250. mov cx,rcode_len ; we need to relocate this much
  1251. test cx,cx ; do we need to move anything ?
  1252.  jnz reloc_bios10
  1253. ret
  1254. reloc_bios10:
  1255. add cx,15 ; round rcode size up to a para
  1256. and cx,not 15
  1257. mov ax,bios_target_seg ; where do we go
  1258. test ax,ax
  1259.  jz reloc_bios20 ; zero - do it ourselves
  1260. inc ax ; FFFF - unlikely as it's not
  1261.  jz reloc_bios25 ;  currently supported
  1262. dec ax ; else we've been given a seg
  1263. jmps reloc_bios40
  1264. reloc_bios20:
  1265. cmp dos_target_seg,0FFFFh ; if DOS goes up, so does BIOS
  1266.  jne reloc_bios30
  1267. reloc_bios25:
  1268. call AllocHMA ;  in HIGH memory
  1269.  jnc reloc_bios50
  1270. reloc_bios30:
  1271. mov ax,cx ; allocate conventionally
  1272. shr ax,1 ! shr ax,1 ;  in para's of course
  1273. shr ax,1 ! shr ax,1
  1274. cmp hidos,0 ; do we want to relocate DOS ?
  1275.  je reloc_bios35 ;  no, allocate conventionally
  1276. call alloc_upper ; try to allocate some upper memory
  1277.  jnc reloc_bios40 ;  can't, so allocate conventional
  1278. reloc_bios35: ;  padding out if required
  1279. call alloc_seg_with_padding
  1280. reloc_bios40:
  1281. mov es,ax
  1282. xor di,di ; ES:DI -> destination
  1283. shr dx,1 ! shr dx,1 ; convert offset to para's
  1284. shr dx,1 ! shr dx,1
  1285. sub ax,dx ; bias segment appropriately
  1286. xchg ax,dx ;  and have in DX
  1287. reloc_bios50:
  1288. push es
  1289. push cx
  1290. push di
  1291. push ds
  1292. mov si,rcode_offset
  1293. mov ds,rcode_seg
  1294. rep movsb
  1295. pop ds
  1296. mov rcode_seg,dx ; new RCODE location
  1297. call dd_fixup ; fixup any device drivers
  1298. pop di
  1299. pop cx
  1300. pop es
  1301. ret
  1302. ;
  1303. ; The following code performs the fixups necessary for RELOCATABLE executable
  1304. ; internal device drivers.
  1305. dd_fixup:
  1306. ; On Entry:
  1307. ; None
  1308. ; On Exit:
  1309. ; None
  1310. push es
  1311. mov di,rcode_seg ; fixup to this segment
  1312. mov si,rcode_fixups ; get fixup table
  1313. test si,si ; is there one ?
  1314.  jz dd_fixup20
  1315. mov es,bios_seg
  1316. dd_fixup10:
  1317. lodsw ; get a fixup offset
  1318. test ax,ax ; last of the fixups ?
  1319.  jz dd_fixup20
  1320. xchg ax,di ; point to the fixup
  1321. stosw ; do the fixup
  1322. xchg ax,di ; save segment again
  1323. jmps dd_fixup10
  1324. dd_fixup20:
  1325. pop es
  1326. ret
  1327. ReserveOSHMA:
  1328. ;------------
  1329. ; reserve space in HMA for OS
  1330. ; On Entry:
  1331. ; None
  1332. ; On Exit:
  1333. ; None
  1334. ;
  1335. ReserveCommandHMA:
  1336. ;----------------
  1337. ; reserve space in HMA for COMMAND.COM
  1338. ; On Entry:
  1339. ; None
  1340. ; On Exit:
  1341. ; None
  1342. ;
  1343. cmp commandHMA,0 ; been here already ??
  1344.  jne ReserveCommandHMA10
  1345. mov cx,COMMAND_SIZE
  1346. mov dx,COMMAND_BASE
  1347. call ReserveHMA ; reserve the space in HMA
  1348.  jc ReserveCommandHMA10 ;  if we can
  1349. mov commandHMA,ax ; save for re-use
  1350. ReserveCommandHMA10:
  1351. ret
  1352. ReserveHMA:
  1353. ;----------
  1354. ; reserve some space in the HMA
  1355. ; On Entry:
  1356. ; CX = size require
  1357. ; DX = maximum offset acceptable
  1358. ; On Exit:
  1359. ; AX = offset of reserved space
  1360. ;
  1361. push es
  1362. call AllocHMA ; allocate space in HIGH memory
  1363.  jc ReserveHMA10
  1364. mov es:word ptr [di],0 ; no link, it's this big
  1365. mov es:word ptr 2[di],cx
  1366. mov bx,es
  1367. mov ax,0FFFFh
  1368. sub ax,bx ; AX = para offset adjustment required
  1369. mov cl,4
  1370. shl ax,cl ; convert to byte offset
  1371. add ax,di ; AX = offset from FFFF:0
  1372. ReserveHMA10:
  1373. pop es
  1374. ret
  1375. FreeHMA:
  1376. ;-------
  1377. ; Return reserved HMA space to pool
  1378. ; On Entry:
  1379. ; CX = offset of HMA block to relink (0 = noblock)
  1380. ; On Exit:
  1381. ; None
  1382. ;
  1383.  jcxz free_himem10 ; no block, don't recycle
  1384. push es
  1385. push cx ; save offset
  1386. les bx,cs:drdos_ptr
  1387. pop ax ; recover offset
  1388. mov di,ax ; remember offset for later
  1389. xchg ax,es:DRDOS_HIMEM_ROOT[bx]; become new head of HMA
  1390. mov bx,0FFFFh
  1391. mov es,bx ; point ES:DI at our section
  1392. stosw ;  chain on rest of HMA
  1393. pop es
  1394. free_himem10:
  1395. ret
  1396. rploader:
  1397. ;--------
  1398. ; On Entry:
  1399. ; DX = phase code
  1400. ; On Exit:
  1401. ; None, All regs preserved
  1402. push es
  1403. push ax
  1404. push bx
  1405. push cx
  1406. push dx
  1407. mov ax,rpl_off ; do we have an RPL sitting on
  1408. or ax,rpl_seg ;  Int 13h
  1409.  jz rploader10
  1410. mov ax,12ffh ; magic cleanup call to RPL
  1411. mov bx,5 ;  to do any tidy ups it wishes
  1412. xor cx,cx ;  following resident BIOS
  1413. mov dx,1 ;  initialisation
  1414. pushf
  1415. cli
  1416. callf rpl_entry ; fake an INT
  1417. rploader10:
  1418. pop dx
  1419. pop cx
  1420. pop bx
  1421. pop ax
  1422. pop es
  1423. ret
  1424. Public Verify386
  1425. Verify386:
  1426. ;---------
  1427. ; On Entry:
  1428. ; None
  1429. ; On Exit:
  1430. ; CY clear if 386 or above
  1431. ;
  1432. push sp ; really old CPU's inc SP
  1433. pop ax ;  before pushing
  1434. cmp ax,sp ; newer ones push original SP
  1435.  jne Verify386fail
  1436. mov ax,3000h ; now try to set IOPL = 3
  1437.     push    ax
  1438. popf
  1439. pushf
  1440. pop bx
  1441. and ax,bx ; any IOPL bits set ?
  1442.  jz Verify386fail
  1443. ; clc ; it's at least a 386
  1444. ret
  1445. Verify386fail:
  1446. stc ; it's not a 386
  1447. ret
  1448. INITDATA dseg 'INITDATA'
  1449. include initmsgs.def ; Include TFT Header File
  1450. extrn history_flg:byte
  1451. extrn next_drv:byte
  1452. extrn dev_count:byte
  1453. ;
  1454. ; PUBLIC Variables which are initialised by the BIOS before the
  1455. ; BIOSINIT code has been executed. 
  1456. ;
  1457. data_start rb 0 ; used to para-align PSP & ENV
  1458. Public func52_ptr
  1459. func52_ptr rd 0 ; address of internal BDOS variables
  1460. func52_off dw 0 ; offset " " "
  1461. func52_seg dw 0 ; segment " " "
  1462. Public drdos_ptr
  1463. drdos_ptr rd 0 ; address of internal BDOS variables
  1464. drdos_off dw 0 ; offset " " "
  1465. drdos_seg dw 0 ; segment " " "
  1466. Public res_ddsc_ptr
  1467. res_ddsc_ptr rd 0
  1468. res_ddsc_off dw 0
  1469. res_ddsc_seg dw 0
  1470. Public rcode_offset, rcode_seg, icode_len, rcode_len, rcode_fixups
  1471. rcode_offset dw 0 ; current offset of relocated code
  1472. rcode_seg dw 0 ; current segment of relocated code
  1473. icode_len dw 0 ; initial size of relocated code
  1474. rcode_len dw 0 ; final size of relocated code
  1475. rcode_fixups dw 0 ; offset of rcode fixup table
  1476. Public current_dos
  1477. current_dos dw 0 ; Current Segment Address of DOS Code
  1478. Public dos_target_seg, bios_target_seg
  1479. dos_target_seg dw 0 ; target address for DOS relocation
  1480. bios_target_seg dw 0 ; 0000 - auto-relocate
  1481. ; FFFF - high memory (not allocated)
  1482. ; xxxx - driver allocated address
  1483. dosCodeParaSize dw 0 ; Size of DOS code in para's
  1484. systemSize dw COMMAND_SIZE ; BIOS+DOS code sizes are added to
  1485. ;  give total size to reserve in HMA
  1486. systemHMA dw 0 ; offset of area in HMA reserved 
  1487. ;  for SYSTEM (BIOS/DOS/COMMAND)
  1488. commandHMA dw 0 ; offset of area in HMA reserved 
  1489. ;  for COMMAND.COM
  1490. Public device_root
  1491. device_root rd 1 ; Root of Resident Device driver Chain
  1492. Public mem_size, ext_mem_size, comspec_drv
  1493. Public init_flags, init_drv
  1494. mem_size dw 0 ; Total Memory Size (in Paragraphs)
  1495. ext_mem_size dw 0 ; Total Extended Memory Size (in KB.)
  1496. init_flags dw 0 ; BIOS INIT Flags
  1497. init_drv db 0 ; Boot Drive (A is 0 .....)
  1498. comspec_drv db 0 ; Default COMSPEC Drive
  1499. Public num_stacks, stack_size
  1500. num_stacks dw DEF_NUM_STACKS
  1501. stack_size dw DEF_SIZE_STACK
  1502. Public num_files, num_fcbs, num_fopen
  1503. Public country_code, code_page
  1504. num_files dw DEF_NUM_FILES ; # of file handles
  1505. num_fcbs dw DEF_NUM_FCBS ; # of fcb file handles
  1506. num_fopen dw -1 ; "unset" value for fast open
  1507. country_code dw DEF_COUNTRY ; Country Code 
  1508. code_page dw DEF_CODEPAGE ; Code Page
  1509. Public dos_name
  1510. IF DRDOS35
  1511. dos_name db 'DRBDOS  SYS',0 
  1512. ELSE
  1513. dos_name db 'IBMDOS  COM',0 ; default DOS filename
  1514. ENDIF
  1515. rpl_name db 'RPLOADER'
  1516. rpl_entry rd 0 ; remember RPL entry point for
  1517. rpl_off dw 0 ;  startup broadcasts
  1518. rpl_seg dw 0
  1519. eject
  1520. ;
  1521. ; Internal variables used by the BIOSINIT code
  1522. ;
  1523. Public bios_seg
  1524. bios rd 0 ; Far pointer to the BIOS Cleanup
  1525. bios_offset rw 1 ; routines.
  1526. bios_seg rw 1
  1527. Public init_dseg
  1528. init_dseg dw 0 ; Init data segment
  1529. Public dos_dseg
  1530. dos_dseg dw 0 ; DOS Data Segment Address
  1531. Public mem_current_base, mem_current, mem_max
  1532. mem_first_base rw 1 ; Base of First Allocated Memory
  1533. mem_current_base rw 1 ; Base of Current Allocated Memory
  1534. mem_current rw 1 ; Next Free Paragraph
  1535. mem_max rw 1 ; Last available Paragraph
  1536. dos_init rd 0 ; DOS Initialization Code
  1537. dos_coff dw 0 ; DOS Init Code Offset
  1538. dos_cseg rw 1 ; DOS Init Code Segment
  1539. free_seg rw 1 ; First available paragraph.
  1540. xms_driver rd 1 ; address of himem driver
  1541. Public hidos
  1542. hidos db 0 ; set true if HIDOS requested
  1543. himem_base dw 0 ; base of HIMEM seg allocations
  1544. himem_size dw 0 ; length of HIMEM seg allocations
  1545. Public last_drv
  1546. last_drv db 5 ; default is "E:"
  1547. console db 'CON',0 ; Default Console Device
  1548. printer db 'PRN',0 ; Default Printer Device
  1549. auxilary db 'AUX',0 ; Default Auxilary Device
  1550. idle_dev db '$IDLE$',0 ; Idle Device Name
  1551. idle_off rw 1 ; Idle Data Area Offset
  1552. idle_seg rw 1 ; Idle Data Area Segment
  1553. dummy_fcb db 0,'           '
  1554. exec_env dw 0 ; Environment Segment
  1555. exec_cloff dw shell_cline ; Command Line Offset
  1556. exec_clseg dw 0 ; Command Line Segment
  1557. dw dummy_fcb
  1558. exec_fcb1seg dw 0 ; FCB 1 Offset and Segment
  1559. dw dummy_fcb
  1560. exec_fcb2seg dw 0 ; FCB 2 Offset and Segment
  1561. rd 1 ; SS:SP
  1562. rd 1 ; CS:IP
  1563. Public shell_cline
  1564. shell_cline db length shell_drv; Initial Command Line
  1565. shell_drv db 'A: /P'
  1566. db 0Dh
  1567. rb 126 - length shell_drv
  1568. dummyVDISK db 0, 0, 0 ; jump instruction
  1569. db 'VDISK3.3' ; OEM name
  1570. dw 128 ; bytes per sector
  1571. db 1 ; sectors per allocation unit
  1572. dw 1 ; number of reserved sectors
  1573. db 1 ; number of FATs
  1574. dw 40 ; number of root directory entries
  1575. dw 512 ; total number of sectors
  1576. db 0FEh ; media descriptor byte
  1577. dw 6 ; sectors per FAT
  1578. dw 8 ; sectors per track
  1579. dw 1 ; number of heads
  1580. dw 0 ; number of hidden sectors
  1581. dw 1024+64 ; KB of extended memory used
  1582. search_state rb 43 ; Search First/Next State
  1583. rw 384 ; big stack for ASPI4DOS.SYS driver
  1584. stack rw 0
  1585. INITPSP DSEG PARA 'INITDATA'
  1586. db 'Z' ; dummy DMD header
  1587. dw 0008h ; owner is system
  1588. dw 0010h ; length of PSP
  1589. rb 3 ; pad to 8 bytes
  1590. db 'DOS',0,0,0,0,0 ; name field (must be 8 bytes)
  1591. psp rb 16h ; Zero Fill PSP Header
  1592. parent_psp dw 0 ; parent, patched to itself
  1593. db 0FFh, 0FFh, 0FFh ; STDIN, STDOUT, STDERR
  1594. db 0FFh, 0FFh ; STDAUX, STDPRN
  1595. db 0FFh, 0FFh, 0FFh ; Remainder CLOSED
  1596. db 0FFh, 0FFh, 0FFh
  1597. db 0FFh, 0FFh, 0FFh
  1598. db 0FFh, 0FFh, 0FFh
  1599. db 0FFh, 0FFh, 0FFh
  1600. dw 0000   ; PSP Environment Pointer
  1601. dw 0000, 0000   ; DOS User SS:SP
  1602. dw 20   ; Maximum of 20 Handles
  1603. dw offset PSP_XFT   ; Handle Table Offset
  1604. xftbl_seg dw 0   ; Handle Table Segment
  1605. rb offset PSP_VERSION - offset PSP_RES1
  1606. Public dosVersion
  1607. dosVersion dw 7   ; DOS version is 7.0
  1608. rb PSPILEN - offset PSP_VERSION - 2
  1609.   ; PAD to Partial PSP Size
  1610. INITENV DSEG PARA 'INITDATA'
  1611. shell_ask db 79 ; max len
  1612. shell_end db 0 ; end of the line
  1613. Public shell
  1614. shell db 'A:COMMAND.COM', 0
  1615. rb 80-length shell
  1616. DATAEND DSEG PARA 'INITDATA'
  1617. Public biosinit_end
  1618. biosinit_end rb 0
  1619. end