title 'Concurrent CP/M Loader Program' ;******************************************************* ; ; The Loader Program opens the file 'CCPM.SYS' ; using the LBDOS and LBIOS and then reads it into ; memory. The DS register is set to the start of ; the Concurrent CP/M DATA area, and a JMPF to the first ; byte of the Concurrent CP/M code is executed. ; ; The first 128 byte record of the CCPM.SYS file is ; a header with the following format: ; ; +----+----+----+----+----+----+----+----+----+ ; |TYPE| LEN | ABS | MIN | MAX | ; +----+----+----+----+----+----+----+----+----+ ; ; type rb 1 ;seg type ; len rw 1 ;length ; abs dw 1 ;absolute segment address for LOADER ; min rw 1 ;minimum mem ; max rw 1 ;max mem needed ; ; The code is expected first and then the data ; within the CCPM.SYS File. This header record ; is constructed automatically by the system ; generation utility GENCCPM. See the variables ; declared at 'SEC1:' where the first sector of ; the CCPM.SYS will be read. ; ; The following commands are used to generate CPMLDR.SYS ; RASM86 LBIOS ; RASM86 LPROG ; LINK86 LBIOS3.SYS = LBIOS,LPROG [DATA[ORIGIN[0180]]] ; GENLDR [nnnn] ; ; The following commands are used to generate the ; boot tracks image BOOTTRKS ; SID86 ; #RDSKBOOT.SYS ;strips header and ; #WBOOT,180,37F ;default base page ; PIP BOOTTRKS = BOOT[O],CPMLDR.SYS[O] ; ;******************************************************* CR equ 13 LF equ 10 CTYPE equ byte ptr 00h CLEN equ word ptr 01h CLDSEG equ word ptr 03h DTYPE equ byte ptr 09h DLEN equ word ptr 0Ah DLDSEG equ word ptr 0Ch CODETYPE equ 1 ;code type CMD header DATATYPE equ 2 ;data type CMD header ; bdos function numbers DRV_SET equ 14 F_OPEN equ 15 F_READ equ 20 F_DMASET equ 26 F_USERNUM equ 32 F_MULTISEC equ 44 F_DMA equ 51 ;******************************************************* ; ; LOADER starts here ; ;******************************************************* CSEG org 0000h public ?start extrn ?conout:near, ?pmsg:near ?start: ; loader entry from BDOS init ;------ mov si,offset signon ;print signon message call ?pmsg mov dl,0 mov cl,DRV_SET ! int 224 ;select boot drive mov dl,0 mov cl,F_USERNUM ! int 224 ;set user number mov dx,offset ccpm_fcb mov cl,F_OPEN ! int 224 ;open CCPM.SYS file cmp al,255 ! jne perr ;insure no error on open mov si,offset nofile error: call ?pmsg ;print no SYSTEM file message halt: sti hlt ;then halt the machine jmps halt perr: mov dx,offset sec1 mov cl,F_DMASET ! int 224 ;set DMA offset address mov dl,1 ;set Multi-sector count to 1 mov si,ds ;SI = DMA segment address call read_rec ;read first record mov bx,offset sec1 cmp CTYPE[bx],CODETYPE ;code type must = 1 je chk_data badhdr: mov si,offset hdrerr jmp error chk_data: cmp DTYPE[bx],DATATYPE ;data type must = 2 jne badhdr mov ax,CLDSEG[bx] ;code abs + code length add ax,CLEN[bx] ;should be = to data abs cmp ax,DLDSEG[bx] ! jne badhdr add ax,DLEN[bx] cmp ax,CLDSEG[bx] ;check for wrap around jbe badhdr mov ccpm_init,0000h ;set O.S. entry offset to 0000h mov ax,CLDSEG[bx] mov ccpm_init+2,ax ;set O.S. entry segment hdrok: mov si,offset csegmsg ;print out starting code and data call ?pmsg ; on console mov ax,word ptr sec1+CLDSEG call phex ;print base code segment mov si,offset dsegmsg call ?pmsg ;print base data segment mov ax,word ptr sec1+DLDSEG call phex mov dx,0 mov cl,F_DMASET ! int 224 ;set DMA offset to 0 ;set multi_sector count to 127 mov dl,127 ;to align reads with physical sectors mov si,word ptr sec1+CLDSEG ;initial DMA segment call read_rec ;read next 127 sectors jz done ;Z flag set -> EOF add si,8*127 ;increment dma segment mov dl,128 ;set multi-sector count to 128 call read_rec ;read next 128 sectors jz done ;Z flag set -> EOF readit1: add si,8*128 ;increment dma segment call read_data ;read next 128 sectors jnz readit1 ;Z flag set -> EOF done: mov si,offset crlf ;print carriage return, line feed call ?pmsg mov ds,word ptr sec1+DLDSEG ;CCP/M data segment jmpf cs:dword ptr ccpm_init ;leap to CCP/M initialization ;------------------------------------------------------- ; subroutines ;------------------------------------------------------- read_rec: ;-------- ; Entry: DL = multisector count ; SI = dma segment mov cl,F_MULTISEC ! int 224 ;set multi-sector count to 128 read_data: ;--------- ; Entry: SI = dma segment ; Exit: Z flag set if EOF ; Z flag reset if no error mov dx,si mov cl,F_DMA ! int 224 ;set DMA segment for disk IO mov dx,offset ccpm_fcb mov cl,F_READ ! int 224 ;next 128 sector read cmp al,1! jnbe read_error ret read_error: mov si,offset rerr ;print READ ERROR message jmp error phex: ;print 4 hex characters from ax ;---- ; Entry: AX = hex value to print mov cx,0404h ;4 in both CH and CL lhex: rol ax,cl ;rotate left 4 push cx ! push ax ;save crucial registers call pnib ;print hex nibble pop ax ! pop cx ;restore registers dec ch ! jnz lhex ;and loop four times ret pnib: ;print low nibble in AL as hex char ;---- ; Entry: AL = hex character to print and al,0fh cmp al,9 ! ja p10 ;above 9 ? add al,'0' ;digit jmps prn p10: add al,'A'-10 ;hex digit A-F prn: mov dl,al putchar: ;------- ; Entry: DL = character to send to console mov cl,dl jmp ?conout ; code segment variable ccpm_init rw 2 ;double word entry to Concurrent CP/M ;******************************************************* ; ; DATA AREA ; ;******************************************************* DSEG signon db 'Concurrent CP/M System Loader V1.0 (02/16/84)',0 nofile db CR,LF,'CCPM.SYS Not Found On Boot Disk',0 rerr db CR,LF,'Error Reading CCPM.SYS',0 hdrerr db CR,LF,'Bad Header Record in CCPM.SYS',0 csegmsg db CR,LF,'Code Paragraph Address = ',0 dsegmsg db CR,LF,'Data Paragraph Address = ',0 crlf db CR,LF,0 ccpm_fcb db 0,'CCPM ','SYS',0,0,0,0 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 db 0 ;------------------------------------------------------- sec1 rb 128 ;read first sector of CCPM.SYS ;here (header record) ;******************************************************* END