Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ***** CUT HERE ***** BEGIN FILE build.sh
- #!/bin/bash
- nasm -f bin -o dsbios.com dsbios.asm
- upx --brute --8086 dsbios.com #optional
- ***** CUT HERE ***** BEGIN FILE cga.asm
- ;Halfassed handling of a true hardware CGA card
- CGA:
- .Init:
- ;Input: CS=BIOS_SEG
- ;Destroys ax, dx, si, di
- mov si,CGA.profile25x80
- call CRTC_LoadProfile.CGA
- xor si,si
- call CRTC_SetDisplayAddress
- mov al,0x2d
- mov dl,0xd8 ;dh already = 0x3
- out dx,al ;set mode
- inc dx
- xor al,al ;set another mode
- out dx,al
- ret
- .modeTable:
- ;CRTC mode parameters for CGA
- db 0x38,0x28,0x2D,0x0A,0x1F,6,0x19 ; Mode 0,1: 40x25
- db 0x1C,2,7,6,7
- db 0,0,0,0
- .profile25x80:
- db 0x71,0x50,0x5A,0x0A,0x1F,6,0x19 ; Mode 2,3: 80x25
- db 0x1C,2,7,6,7
- db 0,0,0,0
- db 0x38,0x28,0x2D,0x0A,0x7F,6,0x64 ; Mode 4-6: Graphics
- db 0x70,2,1,6,7
- db 0,0,0,0
- ;the fourth mode string is only for MDA, not CGA
- times 16 db 0 ;...so dsBIOS leaves it zero
- ;video memory page size for those crtc init values
- .vidMem:
- dw 0x0800 ; Regen len, 40 x 25
- dw 0x1000 ; 80 x 25
- dw 0x4000 ; GRAPHIX
- dw 0x4000
- ;max columns for each mode
- .maxCols:
- db 0x28,0x28,0x50,0x50,0x28,0x28,0x50,0x50 ; Maximum columns
- .modeBytes:
- db 2Ch,28h,2Dh,29h,2Ah,2Eh,1Eh,00h ; Table of mode sets
- ;TABMUL db 00h,00h,10h,10h,20h,20h,20h,30h
- ***** CUT HERE ***** BEGIN FILE crtc.asm
- ;FIXME: Assumes BIOS_CODE_SEG = BIOS_DATA_SEG!
- CRTC_LoadProfile:
- .CGA:
- ; Input: DS:SI = address of config buffer
- ;(12 bytes) - Config data for CRTC
- ;geometry info is automatically extracted and set up
- ; Output: SI is incremented by 12
- ;Trashed: AX, DX, DI
- mov dx,0x3d4 ;CGA address
- mov di,0x3d5 ;CGA data
- mov al,[si+6] ;get rows
- jmp short CRTC_LoadProfile.SetupRowsCols
- .Sanyo:
- ; Input: DS:SI = address of config buffer
- ;(10 bytes) - Config data for CRTC
- ;geometry info is automatically extracted and set up
- ; Output: SI is incremented by 12
- ;Trashed: AX, DX, DI
- mov dx,0x30 ;CRTC address port
- mov di,0x32 ;CRTC data port
- mov al,[si+6] ;get # rows*2
- shr ax,1 ;divide by 2 (reg 6 has 4 scanline rows, chars are 8)
- ;Routines are chained, DO NOT insert any code here
- .SetupRowsCols:
- dec ax ;subtract 1 (it's zero based)
- mov [BV.ScreenRows],al
- ;Routines are chained, DO NOT insert any code here
- .SetupCols:
- ; Input: DS:SI = address of config buffer
- ;(12 or 10 bytes depending if CGA) - Config data for CRTC
- ;geometry info is automatically extracted and set up
- ; DX = CRTC Address port
- ; DI = CRTC Data port
- ; Output: SI is incremented by 12
- ;Trashed: AX
- mov al,[si+1] ;get # columns
- cbw
- cs mov [BV.ScreenCols],ax
- NoSetup:
- push bx
- cld
- mov al,0
- .lp out dx,al ;write config byte number
- xchg ax,bx
- xchg dx,di
- lodsb
- out dx,al ;write config byte
- xchg dx,di
- xchg ax,bx
- inc ax
- cmp al,12 ;written 12 bytes?
- jb .lp
- pop bx
- ret
- CRTC_SetDisplayAddress:
- ; Input: SI = Display offset
- ; DX = CRTC Address port
- ; DI = CRTC Data port
- ;Trashed: AL
- mov al,13
- .do2nd:
- out dx,al
- xchg dx,di
- xchg ax,si
- out dx,al
- xchg ah,al
- xchg ax,si
- xchg dx,di
- dec ax
- jp .do2nd ;going to hell for this one
- ret
- CRTC_GetDisplayAddress:
- ; Input: DX = CRTC Address port
- ; DI = CRTC Data port
- ; Output: SI = Display offset
- ;Trashed: AL
- mov al,13
- .do2nd:
- out dx,al
- xchg dx,di
- xchg ax,si
- in al,dx
- xchg ah,al
- xchg ax,si
- xchg dx,di
- dec ax
- jp .do2nd ;window seat please
- ret
- ;Register Index/Register Name
- ; 0 Horizontal Total
- ; 1 Horizontal Displayed
- ; 2 Horizontal Sync Position
- ; 3 Horizontal and Vertical Sync Widths
- ; (Hitachi 46505 does not allow setting vertical sync width)
- ; 4 Vertical Total
- ; 5 Vertical Total Adjust
- ; 6 Vertical Displayed
- ; 7 Vertical Sync position
- ; 8 Interlace and Skew
- ; (Hitachi 46505 does not implement skew)
- ; 9 Maximum Raster Address
- ; 10 Cursor Start Raster
- ; 11 Cursor End Raster
- ; 12 Display Start Address (High)
- ; 13 Display Start Address (Low)
- ; 14 Cursor Address (High)
- ; 15 Cursor Address (Low)
- ; 16 Light Pen Address (High)
- ; 17 Light Pen Address (Low)
- CRTC:
- ;.profile25x72
- ; db 112 ;0 Horizontal Total
- ; db 72 ;1 Horizontal Displayed
- ; db 85 ;2 Horizontal Sync Position
- ; db 0x4a ;3 Horizontal and Vertical Sync Widths
- ; db 65 ;4 Vertical Total
- ; db 0 ;5 Vertical Total Adjust
- ; db 50 ;6 Vertical Displayed
- ; db 56 ;7 Vertical Sync position
- ; db 0 ;8 Interlace and Skew
- ; db 3 ;9 Maximum Raster Address
- .profile25x80:
- db 112 ;0 Horizontal Total
- db 80 ;1 Horizontal Displayed
- db 88 ;2 Horizontal Sync Position
- db 0x4a ;3 Horizontal and Vertical Sync Widths
- db 65 ;4 Vertical Total
- db 0 ;5 Vertical Total Adjust
- db 50 ;6 Vertical Displayed
- db 56 ;7 Vertical Sync position
- db 0 ;8 Interlace and Skew
- db 3 ;9 Maximum Raster Address
- .profile6x34: ;Possibly for future use in breakout menu
- db 112 ;0 Horizontal Total
- db 34 ;1 Horizontal Displayed
- db 66 ;2 Horizontal Sync Position
- db 0x4a ;3 Horizontal and Vertical Sync Widths
- db 65 ;4 Vertical Total
- db 0 ;5 Vertical Total Adjust
- db 12 ;6 Vertical Displayed
- db 37 ;7 Vertical Sync position
- db 0 ;8 Interlace and Skew
- db 3 ;9 Maximum Raster Address
- ;These are the modes that the ROM bootstrap can set
- ;SW 2 ON
- ;65505348690264640003000000000000
- ;65=101 0 Horizontal Total
- ;50=80 1 Horizontal Displayed
- ;53=83 2 Horizontal Sync Position
- ;48 3 Horizontal and Vertical Sync Widths
- ;69=105 4 Vertical Total
- ;02 5 Vertical Total Adjust
- ;64=100 6 Vertical Displayed
- ;64=100 7 Vertical Sync position
- ;00 8 Interlace and Skew
- ;03 9 Maximum Raster Address
- ;00 10 Cursor Start Raster
- ;00 11 Cursor End Raster
- ;00 12 Display Start Address (High)
- ;00 13 Display Start Address (Low)
- ;00 14 Cursor Address (High)
- ;00 15 Cursor Address (Low)
- ;SW 2 OFF
- ;7048554A410032380003000000000000
- ;70=112 0 Horizontal Total
- ;48=72 1 Horizontal Displayed
- ;55=85 2 Horizontal Sync Position
- ;4a 3 Horizontal and Vertical Sync Widths
- ;41=65 4 Vertical Total
- ;00 5 Vertical Total Adjust
- ;32=50 6 Vertical Displayed
- ;38=56 7 Vertical Sync position
- ;00 8 Interlace and Skew
- ;03 9 Maximum Raster Address
- ;00 10 Cursor Start Raster
- ;00 11 Cursor End Raster
- ;00 12 Display Start Address (High)
- ;00 13 Display Start Address (Low)
- ;00 14 Cursor Address (High)
- ;00 15 Cursor Address (High)
- ***** CUT HERE ***** BEGIN FILE crypto.asm
- ;cryptographic functions - key entry/generation, block chaining
- Generate_Subkeys:
- ;DL = drive number
- ;Returns: BX=Subkey address
- ;Destroys: AX, CX
- mov bx,BV.DSubkeys
- test dl,1
- jnz .drive1
- add bx,240
- .drive1:
- push dx
- push bx ;subkeys
- mov ax,BV.EncKey
- push ax ;key
- call rijndael_keygen
- pop ax
- pop bx
- pop dx
- ret
- Enter_Key:
- ;input: ds:di = key to be entered
- ; es=ds
- ;output: carry set if canceled (null entry)
- ;trashed: ax, bx, cx, si
- .beginEntry:
- ;first, clear buffer
- push di ;save buffer location
- mov cx,16 ;16 words
- xor ax,ax
- cld
- rep stosw
- pop di
- mov cl,4
- .loopover:
- xor bx,bx ;bx = pointer within the input buffer (32 bytes)
- xor ax,ax
- int 0x16 ;get keypress
- cmp al,13
- je .cancelExit
- jmp short .noread
- .charlp:
- xor ax,ax
- int 0x16 ;get keypress
- .noread:
- ;check for backspace
- cmp al,8 ;backspace
- je .beginEntry
- cmp al,13 ;enter key
- je .normalExit ;carry will be clear if taken
- xor al,[di+bx]
- rol al,cl
- mov [di+bx],al
- inc bx
- cmp bl,32
- jne .charlp
- jmp short .loopover
- .cancelExit:
- stc
- .normalExit:
- ret
- Do_IV:
- ;CH = low eight bits of cylinder number
- ;CL = sector number 1-63 (bits 0-5)
- ; high two bits of cylinder (bits 6-7, hard disk only)
- ;DH = head number
- ;SI = subkeys
- ;Direction: cleared
- ;Destroyed: AX
- push bx
- push di
- push si ;subkey location for encrypt call
- ; generate IV
- mov di,BV.EncIV
- push di ;IV location for encrypt call
- mov ax,cx
- stosw
- mov al,dh
- stosb
- xor ax,ax
- times 6 stosw
- stosb
- ; encrypt IV
- ;arguments are already pushed
- call rijndael_encrypt
- ; xor IV into first block
- pop si ;IV location
- lea bx,[si+16]
- call mixkey_nosetup ;; Destroys AX, SI, and DI.
- pop si ;subkeys
- pop di
- pop bx
- ret
- Encrypt_Sector:
- ;CH = low eight bits of cylinder number
- ;CL = sector number 1-63 (bits 0-5)
- ; high two bits of cylinder (bits 6-7, hard disk only)
- ;DH = head number
- ;DL = drive number (bit 7 set for hard disk)
- ;DS = BIOS_DATA_SEG
- push es
- push cs
- pop es
- push si
- cmp dl,1
- sbb si,si ;si=0xffff if drive=1, else 0
- and si,240 ;si=240 if drive=1, else 0
- add si,BV.DSubkeys
- push bx
- push cx
- push dx
- call Do_IV ;Apply IV
- push si
- mov si,BV.SectorBuffer
- .nextscr:
- lea bx,[si+16]
- call mixkey_nosetup
- cmp si,BV.SectorBuffer+512-16
- jne .nextscr
- mov si,BV.SectorBuffer
- .nextblock:
- push si
- call rijndael_decrypt ;encrypt block (using decryption...)
- pop si
- ;xor block into next block
- ;si has current [source] position in sector
- lea bx,[si+16] ;xor to 16 bytes later
- call mixkey_nosetup ;adds 16 to SI (mix ciphertext)
- cmp si,BV.SectorBuffer+512-16
- jne .nextblock
- push si
- call rijndael_decrypt ;final block
- pop si
- pop si
- pop dx
- pop cx
- pop bx
- pop si
- pop es
- ret
- Decrypt_Sector:
- ;CH = low eight bits of cylinder number
- ;CL = sector number 1-63 (bits 0-5)
- ; high two bits of cylinder (bits 6-7, hard disk only)
- ;DH = head number
- ;DL = drive number
- ;DS = BIOS_DATA_SEG
- push es
- push cs
- pop es
- push si
- cmp dl,1
- sbb si,si
- and si,240 ;see Encrypt_Sector for this trick
- add si,BV.DSubkeys
- push bx
- push cx
- push dx
- push si
- mov si,BV.SectorBuffer+512-16
- push si
- call rijndael_encrypt
- pop si
- .nextblock:
- mov bx,si
- sub si,16
- push si
- call mixkey_nosetup
- call rijndael_encrypt ;decrypt block (using encryption...)
- pop si
- cmp si,BV.SectorBuffer
- jne .nextblock
- mov si,BV.SectorBuffer+512-32
- .nextscr:
- lea bx,[si+16]
- call mixkey_nosetup
- sub si,32
- cmp si,BV.SectorBuffer-16
- jne .nextscr
- pop si
- pop dx
- pop cx
- push cx
- push dx
- call Do_IV ;Apply IV
- pop dx
- pop cx
- pop bx
- pop si
- pop es
- ret
- ;Plan:
- ;Encryption:
- ; generate IV
- ; encrypt IV
- ; xor IV into first block
- ; encrypt first block
- ; xor first block into 2nd block
- ; encrypt 2nd block...
- ;
- ;Decryption:
- ; decrypt last block
- ; xor 2nd to last block into last block
- ; decrypt 2nd to last block
- ; ...
- ; decrypt first block
- ; generate IV
- ; encrypt IV
- ; xor IV into first block
- ***** CUT HERE ***** BEGIN FILE disk.asm
- ;This file needs a rewrite, but mostly works
- ;(some problems switching between disk geometries in freedos)
- Readsector:
- ;pushing done in function selector
- ;INPUT
- ;AH = 02h
- ;AL = number of sectors to read (must be nonzero)
- ;CH = low eight bits of cylinder number
- ;CL = sector number 1-63 (bits 0-5)
- ; high two bits of cylinder (bits 6-7, hard disk only)
- ;DH = head number
- ;DL = drive number (bit 7 set for hard disk)
- ;ES:BX -> data buffer
- ;-----
- ;during operation:
- ;BH = total sectors
- ;BL = sectors read
- ;ES:BP = data buffer
- .rslp call FDC.SpinSeek
- cli
- .rsnsl:
- ;inc bl
- ;cmp bl,bh
- ;je .doOpDoneNE
- push cx
- mov di,BV.SectorBuffer
- mov ax,512
- xchg ax,cx ;sector size
- out 0xc,al ;sector number
- mov al,0x80 ;read sector
- call FDC.CmdDelay ;command
- ;retrieve it from the FDC
- jmp short .bytelp
- .erchk test al,3
- jz .doOpError
- .bytelp:
- in al,8
- test al,2
- jz .erchk
- in al,0xe
- mov [di],al ;store byte from FDC
- inc di
- loop .bytelp
- in al,8
- test al,0x9e
- jnz .doOpError
- ;do decryption
- mov di,dx
- and di,1
- test byte [BV.DFlags+di],1
- jz .nodec
- pop cx
- call Decrypt_Sector
- push cx
- .nodec:
- ;store
- mov di,bp
- mov si,BV.SectorBuffer
- mov cx,256
- rep movsw
- mov bp,di
- pop cx
- mov si,dx
- and si,byte 1
- cmp cx,byte 1
- jne .noReadSectorCount
- or dh,dh
- jnz .noReadSectorCount
- mov al,[BV.SectorBuffer+0x18]
- inc al
- mov [BV.SectorsPerTrack+si],al
- .noReadSectorCount:
- inc bl
- cmp bl,bh
- je .doOpDoneNE
- inc cx ;find next sector
- cmp cl,[BV.SectorsPerTrack+si]
- jb .rsnsl
- mov cl,1
- xor dh,1
- jnz .rslp
- inc ch
- jmp short .rslp
- .doOpDoneNE:
- jmp INT13.OpDoneNE
- .doOpError:
- jmp INT13.OpError
- Writesector:
- ;pushing done in function selector
- ;INPUT
- ;AH = 03h
- ;AL = number of sectors to write (must be nonzero)
- ;CH = low eight bits of cylinder number
- ;CL = sector number 1-63 (bits 0-5)
- ; high two bits of cylinder (bits 6-7, hard disk only)
- ;DH = head number
- ;DL = drive number (bit 7 set for hard disk)
- ;ES:BX -> data buffer
- ;-----
- ;during operation:
- ;BH = total sectors
- ;BL = sectors read
- ;ES:BP = data buffer
- .rslp call FDC.SpinSeek
- cli
- .rsnsl:
- ;inc bl
- ;cmp bl,bh
- ;je Readsector.doOpDoneNE
- push cx
- xchg ax,cx
- out 0xc,al ;sector number
- ;load from memory to buffer
- push es
- mov ax,es
- mov ds,ax ;ds=source
- mov ax,cs
- mov es,ax ;es=buffer
- mov si,bp
- mov di,BV.SectorBuffer
- mov cx,256
- rep movsw
- mov bp,si
- mov ax,cs
- mov ds,ax ;restore ds
- pop es
- ;do encryption
- mov si,dx
- and si,byte 1
- test byte [BV.DFlags+si],1
- jz .nodec
- pop cx
- call Encrypt_Sector
- push cx
- .nodec:
- mov si,BV.SectorBuffer
- ;mov cx,512 ;byte counting isn't important when writing
- ;mov al,0xa0 ;write sector
- ;call FDC.CmdDelay ;command
- push bp
- push dx
- mov bp,.bytelp
- mov dx,8
- mov ah,0;2
- lodsb
- mov di,ax
- mov al,0xa0 ;write sector
- push bx
- mov bx,0xf602
- call FDC.CmdDelay ;command
- mov ah,0;xf6
- ;write it to the FDC
- .startlp:
- in al,dx
- shr al,1
- jnc .wdone ;not busy -> error
- jnz .startlp ;waiting for busy only
- .waitdata:
- in al,dx
- test al,bh ;ah=f6 ;ignore CRC error?!?
- jz .waitdata ;wait for data request
- ;jmp short .writeagain
- xchg ax,di
- out 0xe,al
- jmp short .loadnext
- .bytelp:
- in al,dx
- dec ax
- jz .bytelp
- cmp al,bl
- jne .wdone
- .writeagain:
- xchg ax,di
- out 0xe,al
- .loadnext:
- lodsb ;get next byte
- xchg di,ax
- in al,dx
- and al,bl ;bl=2
- jnz .writeagain
- jmp bp
- .wdone:
- pop bx
- in al,dx
- or al,al
- ;cmp al,0xff;0x9e
- pop dx
- pop bp
- jnz INT13.OpError
- pop cx
- inc bl
- cmp bl,bh
- je Readsector.doOpDoneNE
- mov si,dx
- and si,1
- inc cx ;find next sector
- cmp cl,[BV.SectorsPerTrack+si]
- jb .rsnsl
- mov cl,1
- xor dh,1
- jnz .rslp
- inc ch
- jmp .rslp
- INT13:
- .OpError:
- ; error exit
- ;xor ah,ah
- ;xor bx,bx
- ;call DisplayNAX
- ;xor ax,ax
- ;int 0x29
- ;xchg ax,cx
- ;call DisplayNAX
- ;.self jmp short .self
- pop cx
- mov ah,4
- ;jmp short INT13.OpDone
- db 0xbb ;ignore next 2 bytes (mov bx,xxxx)
- .OpDoneNE:
- mov ah,0
- .OpDone:
- mov al,0xd0 ;immediate interrupt
- out 8,al
- mov al,0xd2 ;capture not-ready
- out 8,al
- pop bp
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- or ah,ah ;cmp ah,0
- ;jz .noerr
- jnz .errex
- .noerr mov ds,bx
- mov bx,sp
- ss and byte [bx+6],0xfe ;turn carry off
- mov bx,ds
- .ex cs and byte [BV.LFlags],0xfb ;unlock
- cs mov [BV.DiskLastStatus],ah
- cs test byte [BV.LFlags],0x20 ;need to run keyclick?
- jz .nokc
- cs and byte [BV.LFlags],0xdf ; no more keyclick
- push ax
- push bx
- call ProcessKeys
- pop bx
- pop ax
- .nokc:
- pop ds
- iret
- .entry:
- push ds
- push cs
- pop ds
- cld
- or byte [BV.LFlags],4 ;lock
- cmp dl,1
- ja .unsupported ;invalid drive
- cmp ah,5
- je .format
- ja .gr5
- cmp ah,1
- jb .noerr ;0 .reset
- je .getstatus ;1
- cmp ah,3
- ja .unsupported; .verify
- push bx
- push cx
- push dx
- push si
- push di
- push bp
- mov bp,bx
- mov bh,al
- mov bl,0
- je Writesector; 3
- jmp Readsector ;2
- .gr5:
- cmp ah,8
- je .getparam ;8
- cmp ah,0x15 ;get disk type
- je .disktype
- cmp ah,0x16
- je .diskchg
- ;6, 7 are fixed disk format
- .verify:
- .format:
- .unsupported:
- mov ah,1 ;unsupported
- .errex mov ds,bx
- mov bx,sp
- ss or byte [bx+6],1 ;turn carry on
- mov bx,ds
- jmp short .ex
- .getparam:
- ;mov ah,7 ;drive param error
- ;test dl,1
- ;ja .errex ;drive out of range
- mov bl,1 ;360KB
- mov cx,40*0x100+9
- mov dx,0x101 ;2 heads, 1 drive
- ;check if we really have 2 drives
- mov ah,[BV.Equipment]
- rcl ah,1
- rcl ah,1
- adc dl,0 ;increment drive count if there are two
- xor ah,ah
- ;FIXME need to set drive param table
- jmp .noerr
- ;.reset
- ; jmp short .noerr
- .getstatus:
- cs mov ah,[BV.DiskLastStatus]
- or ah,ah
- jz .noerr
- jmp short .errex
- .diskchg:
- mov ah,al
- in al,0x1c
- and al,0x3
- sub al,dl
- xchg al,ah ;al becomes unchanged, ah=0 if same drive
- jz .noerr
- mov ah,6
- jmp .errex
- .disktype:
- mov ah,2; 1 ;floppy, changeline support
- jmp .noerr
- FDC:
- .SpinSeek:
- ;in: dl=drive number, ch=track, dh=head number
- ; ds=0x40 (BIOS_DATA_SEG)
- ;push ax
- push bx
- mov al,0xd0 ;force interrupt
- out 8,al
- xor bx,bx
- ;figure out if the right drive/side was set
- in al,0x1c
- mov ah,al
- and al,7 ;mask off all but the drive/side
- xor al,dl ;dl is desired drive number
- times 2 ror al,1
- xor al,dh ;dh is desired head number
- ;al now has different bits set from drive/side
- jz .ssSameDS
- inc bx ;make sure we exit at an index pulse
- ;inc bx ;and a little more for 10spt
- .ssSameDS:
- times 2 rol al,1
- xor al,ah ;this is so fucking genius, it amazes me
- out 0x1c,al ;set desired drive/side
- ;is the drive still ready?
- in al,8
- shl al,1
- jnc .ssNoSpinDelay
- mov bl,4 ;the drive wasn't spinning - let's go 3-4 revolutions
- .ssNoSpinDelay:
- mov [BV.FloppyIntCount],bl
- or bx,bx ;if bx is non-zero, we must have changed sides/tracks
- mov bl,dl
- lea bx,[bx+BV.DTrack] ;don't touch flags
- ;load track from memory
- mov al,[bx]
- jnz .doSeek
- cmp al,ch ;is the drive on the same track?
- jz .noSeek
- .doSeek: ;do seek to track
- out 0xa,al ;set current track
- mov al,ch
- out 0xe,al ;set track number
- mov [bx],al ;update track number
- mov al,0x18 ;seek track, load head
- call .CmdDelay ;command
- .ccWait in al,8
- test al,1
- jnz .ccWait
- mov al,0xd4 ;capture index pulse
- ;mov bl,[BV.FloppyIntCount]
- sti ;process interrupts
- out 8,al
- .ssWait cmp byte [BV.FloppyIntCount],0
- jg .ssWait
- ;cmp bl,4
- ;jb .countSectors
- .noSeek pop bx
- ;pop ax
- ret
- .CmdDelay:
- out 8,al
- .Delay:
- times 4 aam
- ret
- .WaitFinished:
- in al,8
- test al,1
- jnz .WaitFinished
- ret
- FloppyDetect:
- ;Strategy: Step down up to 45 times until TR00 is detected, else give up
- ; Step up 1 time, verify TR00=0
- ; Step down 1 time, verify TR00=1
- ;Returns with zero flag set if only one drive is found
- mov cx,45 ; max tracks
- .tryAgain:
- mov al,0x68 ;step down, 6ms delay
- call .CWT
- loopz .tryAgain ;loop if no TR00
- jz .done
- mov al,0x4a ;step up, 20ms delay
- call .CWT
- mov al,0x6a ;step down, 20ms delay (0x6a AND 4 is zero for error exit)
- jnz .errdone
- .CWT:
- call FDC.CmdDelay
- call FDC.WaitFinished
- .errdone:
- test al,4
- .done:
- ret
- FloppyInt:
- ;purpose is to decrement event count if in disk code
- ;otherwise select drive 3 and unload head if no longer ready
- cli
- push ax
- in al,8 ;clear interrupt
- cs test byte [BV.LFlags],4 ;are we in BIOS disk code?
- jz .notdisk
- cs dec byte [BV.FloppyIntCount] ;in disk code
- pop ax
- iret
- .notdisk:
- in al,0x1c
- mov ah,al
- or al,7 ;select drive 3 side 1
- xor ah,al
- jz .done ;drive 3 side 1 was already selected
- out 0x1c,al
- ;turn off the drive motor
- in al,0xa ;get track
- out 0xe,al ;seek to current track
- mov al,0x10 ;seek and unload head
- out 8,al ;floppy command
- .done pop ax
- iret
- ***** CUT HERE ***** BEGIN FILE dsbios.asm
- CPU 186
- BIOS_DATA_SEG equ 0x40
- BIOS_CODE_SEG equ 0x40
- VIDEO_SEG equ 0x400
- Section Loader
- LoaderStart:
- call InitCode+LoaderEnd-LoaderStart
- LoaderEnd:
- section BIOS align=1 vstart=0
- BV:
- .Serial dw 0
- dw 0
- dw 0
- dw 0
- .Parallel dw 0x1a
- dw 0
- dw 0
- dw 0
- .Equipment dw 0x4021 ;4061 for 2 floppies; autodetected
- db 0
- .TotalRAM dw 768
- db 0
- db 0
- .KeyStatus dw 0 ;shift flags (int16/ah=2) are here (high byte is extended)
- db 0
- .NextKey dw .KeyBuffer
- .FirstFreeKey dw .KeyBuffer
- .KeyBuffer times 16 dw 0
- .EndKeyBuffer db 0
- db 0
- db 0
- .DiskLastStatus db 0
- db 0
- db 0
- db 0
- db 0
- .XFCount db 0
- db 0
- db 0
- ;Start mode change clear range
- .CurMode db 0x2
- .ScreenCols dw 0;80
- .PageSize dw 0x1000 ;4000
- .PageStart dw 0
- .CursorPos times 8 dw 0
- .CEndLine db 8
- .CStartLine db 7
- .CurPage db 0
- .CRTCBase dw 0x3d4
- .CurModeSelect db 0x2d
- .CurCGAPalette db 0
- ;End mode change clear range
- dd 0
- db 0
- .TimerTicksL dw 0
- .TimerTicksH dw 0
- .DaysPassed db 0
- .CtrlBrk db 0
- dw 0
- db 0
- db 0
- db 0
- db 0
- times 4 db 0
- times 4 db 0
- .KeyBufferStart dw .KeyBuffer
- .KeyBufferEnd dw .EndKeyBuffer
- times 0x84-($-$$) db 0
- .ScreenRows db 0;24
- times 0x200-($-$$) db 0
- .XFlags db 2 ;bit 0=V20 present, 1=CGA present (turned off if not found)
- .LFlags db 0 ;bit 0=OnboardVid 1=CGA 2=Disk 3=BIOSMenus
- ; 4=RunTimerTick 5=RunKeyClick 6=RunBIOSMenu
- .FloppyIntCount db 0
- .SectorsPerTrack db 10,10 ;actually SPT+1
- .AuxTickCount dw 0
- .EncKey times 32 db 0
- ;DriveData
- .DTrack db 0,0
- .DFlags db 0,0 ;bit 0: disk encryption active
- .DSubkeys times 240*2 db 0 ;240 bytes each
- .CRTC_Profile:
- dw 0
- .CRTC_DisplayAddress:
- dw 0
- .LStackStart dw 0x0200 ;bit to be moved for coprocessor detection
- times 47 dw 0
- .LocalStack:
- .EncIV times 4 dd 0
- .SectorBuffer times 128 dd 0
- startCode:
- startOnboardv:
- %include "onboardv.asm" ;Onboard Video
- endOnboardv:
- startCga:
- %include "cga.asm" ;CGA Video
- endCga:
- startDisk:
- %include "disk.asm" ;Disk Functions
- endDisk:
- startKeyboard:
- %include "keyboard.asm" ;Keyboard API & Interrupt handler
- endKeyboard:
- startMisc:
- %include "misc.asm" ;Minor interrupt handlers, BIOS display routines
- endMisc:
- startTimer:
- %include "timer.asm" ;Timer chip support
- endTimer:
- startMenu:
- %include "menu.asm" ;Breakout menu
- endMenu:
- startCrtc:
- %include "crtc.asm" ;CRTC configuration routines and screen profiles
- endCrtc:
- startCrypto:
- %include "crypto.asm" ;Encryption support routines
- endCrypto:
- %define rijndael_empty_data ;tables are generated at boot, saving disk space
- startRijndael:
- %include "rijndael.asm" ;Main Rijndael encryption routines
- endRijndael:
- EndOfResident:
- startInit:
- %include "init.asm" ;HW Init and 3rd stage bootloader code
- endInit:
- InitCode: ;relocate to 40:0
- cli
- push cs
- pop ds
- mov cx,(InitCode - BV) / 2
- mov ax,BIOS_CODE_SEG
- mov es,ax
- xor di,di
- pop si ;first byte after call
- cld
- rep movsw ;for great justice
- jmp BIOS_CODE_SEG:BIOSEntry
- %ifdef SizeSummary
- dw endInit - startInit
- db "<INIT"
- dw endOnboardv - startOnboardv
- db "<ONBOARDV"
- dw endCga - startCga
- db "<CGA"
- dw endDisk - startDisk
- db "<DISK"
- dw endKeyboard - startKeyboard
- db "<KEYBOARD"
- dw endMisc - startMisc
- db "<MISC"
- dw endTimer - startTimer
- db "<TIMER"
- dw endMenu - startMenu
- db "<MENU"
- dw endCrtc - startCrtc
- db "<CRTC"
- dw endCrypto - startCrypto
- db "<CRYPTO"
- dw endRijndael - startRijndael
- db "<RIJNDAEL"
- dw endRijInit - startRijInit
- db "<RIJINIT"
- dw startCode - BV
- db "<VARS"
- %endif
- ***** CUT HERE ***** BEGIN FILE init.asm
- InitList:
- ;Init interrupt table
- db 0x8
- dw NoInterrupt
- db 0x10
- dw OnBoardVideo
- db 0x11
- dw INT11
- db 0x12
- dw INT12
- db 0x13
- dw INT13.entry
- db 0x15
- dw INT15
- db 0x16
- dw INT16.entry
- db 0x18
- dw Reboot
- db 0x19
- dw Reboot
- db 0x1a
- dw INT1A ;system time api
- db 0x1d
- dw CGA.modeTable
- db 0x29
- dw INT29
- db 0xf8 ;Timer0
- dw Timer0
- ;db 0xf9 ;Timer1
- ;dw Timer1
- ;db 0xfa
- ;dw
- db 0xfb ;Keyboard UART
- dw KeyUART
- ;db 0xfc
- ;dw
- db 0xfd ;Floppy Interrupt
- dw FloppyInt
- db 0xfe ;FPU Exception
- dw FPUInterrupt
- db 0xff ;Expansion IRQ
- dw NoInterrupt
- db 0 ;end list
- ;#############
- ;Hardware init list
- ;Video page
- dw 0x1000 ;Video @ 16-32K (VIDEO_SEG)
- ;Floppy seek track 0
- dw 0x0808 ;no verify
- ;keyboard controller:
- dw 0x3a00, 0x3a00, 0x3aff, 0x3aff, 0x3a37
- ; \force state/ \reset/ \mode/ \set command
- ;8259A interrupt controller
- dw 0x0013, 0x02f8, 0x020f, 0x0296
- ; \ICW1/ \ICW2/ \ICW4/ \mask/
- ;Timer init data
- dw 0x2634, 0x20bf, 0x2021 ;channel 0 (clock)
- dw 0x2674, 0x2200, 0x2200 ;channel 1 (2nd stage clock)
- dw 0x26b6, 0x245d, 0x2400 ;channel 2 (add-in serial rate)
- ;End hardware init
- dw 0 ;end list
- Msg: ;IMPORTANT: DO NOT REORDER FIRST 2 MESSAGES
- .title:
- db "[dsBIOS] V1.02 - (C)2006 Brad Normand",0xd,0xa
- db 0xa,0xa
- db " Memory: KB",0xd,0xa
- db " CPU Type:",0xd,0xa
- db " Coprocessor:",0xd,0xa
- db " CGA Video:",0xd,0xa
- ;db " Aux Comm:",0xd,0xa
- db "Floppy Drives:",0
- .i8088:
- db "i8088",0
- .V20:
- db "NEC V20",0
- .none:
- db "None",0
- .detected:
- db "Detected",0
- .text:
- db ", text mode initialized",0
- .keyBoot:
- db 13,10,10,"Booting FreeDOS...",13,10,10,0
- ;MsgReg: db "LAST AX-DX CS-IP ",0
- ;MsgMCE db "Memory corruption detected at: 40:",0
- BIOSEntry:
- ;switch to our local stack
- ;ax=0x40 at entry (BIOS_CODE_SEG)
- ;cl=0x00 at entry
- ;direction flag must be clear
- mov ss,ax
- mov sp,BV.LocalStack-26 ;extra zeros to pop
- mov ds,ax
- ;start the math coprocessor initializing if present
- fninit ;finit can't be used because it will lock if no coprocessor
- ;prepare interrupt table - each vector points to InterruptCatcher
- ; but with low byte of CS = int#
- pop di ;zero from stack
- pop es ;zero from stack
- ;generate int0 offset
- mov ax,InterruptCatcher-BV & 0xf + ((((InterruptCatcher-BV >> 4) + BIOS_CODE_SEG) & 0xff) << 4)
- ;generate int0 segment
- mov dx,((InterruptCatcher-BV >> 4) + BIOS_CODE_SEG) & 0xff00
- ;cx and direction were cleared in first stage init
- inc ch
- .nextint:
- stosw
- sub ax,0x10 ;update offset
- jnb .noborrow
- sub ax,0x1000 ;this adjustment is necessary to ensure the handler is in the segment window
- add dx,0x100-0x1000 ;0x100 offsets the adjustment, 0x1000 for the wrapover
- .noborrow:
- xchg ax,dx
- stosw
- inc ax ;update segment
- xchg ax,dx
- loop .nextint
- ;direction was also cleared
- rep stosw
- fild dword [BV.LStackStart+1] ;load test bit into FPU if present
- ;set up 25x80
- mov si,CRTC.profile25x80
- call CRTC_LoadProfile.Sanyo
- pop si ;zero from empty stack
- call CRTC_SetDisplayAddress
- ;CGA Detection and Initialization
- call CGA.Init
- mov dl,0xd4
- mov si,0x15ea
- .fixCGA:
- xor byte [BV.XFlags],2
- call CRTC_SetDisplayAddress
- call CRTC_GetDisplayAddress
- sub si,0x15ea
- jz .fixCGA ;if detected
- fist dword [BV.LStackStart] ;write test bit back from FPU if present
- ;next, step through the interrupt list and set them
- mov si,InitList
- .intlp lodsb
- and ax,0xff
- jz .intdone
- shl ax,1
- shl ax,1
- xchg ax,di
- movsw
- mov ax,BIOS_DATA_SEG
- stosw
- jmp short .intlp
- .intdone:
- ;now process hardware init
- .portloop:
- xor dx,dx
- lodsw
- test ax,ax
- jz .portdone
- xchg ah,dl
- out dx,al
- jmp short .portloop
- .portdone:
- ;do the title
- pop ax ;zero from empty stack
- int 0x10 ;clear screen
- ;mov bx,1
- ;mov si,Msg.title ;SI is already set
- call DisplayString
- ;initialize the FDC (track 0 seek already in progress)
- ;mov byte [BV.DTrack],0 ;already zero!
- ;determine CPU type
- mov ax,sp
- pusha
- nop
- cmp ax,sp
- je .nov20
- xchg ax,sp
- or byte [BV.XFlags],1
- .nov20:
- ;update equipment with coprocessor status
- mov al,[BV.LStackStart]
- or [BV.Equipment],al
- ;count RAM - start at 64KB, test 1KB blocks up to 768KB
- ;Note: this checks for presence only - not correct operation!
- mov ax,0x1000-64
- mov cx,705 ;test up to 704 additional KB
- mov di,0x2fd ;test pattern and address - should catch any missing chip
- .ramclp add ax,64
- mov es,ax
- es mov [di],di
- es cmp [di],di
- loope .ramclp ;cx is decremented an extra time
- ;subtract the nonexistant memory from our total
- sub word [BV.TotalRAM],cx
- ;display some info
- ;mov si,Msg.HW ;SI is already set
- ;mov bx,3
- ;mov word [BV.CursorPos],0x300
- ;call DisplayString
- mov word [BV.CursorPos],0x30f
- int 0x12
- call DisplayNAX
- mov word [BV.CursorPos],0x40f
- test byte [BV.XFlags],1
- ;mov si,Msg.i8088 ;SI is already set
- jz .i8088
- mov si,Msg.V20
- .i8088 call DisplayString
- mov word [BV.CursorPos],0x50f
- test byte [BV.Equipment],2
- mov si,Msg.none
- jz .no8087
- mov si,Msg.detected
- .no8087 call DisplayString
- mov word [BV.CursorPos],0x60f
- mov si,Msg.none
- test byte [BV.XFlags],2
- jz .noCGA
- mov si,Msg.detected
- call DisplayString
- .noCGA call DisplayString
- ;generate rijndael tables
- startRijInit:
- %ifdef rijndael_empty_data
- push cs
- pop es
- mov di,isbox ;xtime ;first, put log in sbox and pwr in isbox ;xtime
- pop bx ;zero from empty stack
- ; push di
- push di
- mov al,1
- mov cx,0xff00
- .tablp mov bl,al
- mov [bx+sbox],cl
- stosb
- ;call .xtime
- shl al,1
- jnc .nxor
- xor al,0x1b
- .nxor xor al,bl
- inc cx
- jnz .tablp
- ;now, create the sbox
- pop bx
- xor ax,ax
- mov di,sbox
- push di
- .sboxl mov ah,al
- mov ch,4
- .makes1 rol ah,1
- xor al,ah
- dec ch
- jnz .makes1
- xor al,0x63
- stosb
- mov al,[di]
- not al
- xlat
- loop .sboxl
- ;now, the inverse sbox
- xor bx,bx
- xor ax,ax ;clear al
- pop si ;xtime
- .islp mov bl,[si]
- inc si
- mov [bx+isbox],al
- inc al
- jnz .islp
- %endif
- endRijInit:
- ;wait for track seek to complete
- call FDC.WaitFinished
- mov al,1 ;2nd drive, side 0
- out 0x1c,al
- call FloppyDetect
- mov al,'1'
- jz .oneFD
- or byte [BV.Equipment],0x40 ;turn on 2 drives
- inc ax ;2
- .oneFD:
- mov [BV.CursorPos],word 0x70f
- int 0x29 ;display # drives
- mov al,0xd2 ;capture ready->not ready
- out 8,al
- in al,0x22
- in al,0x22
- mov [BV.AuxTickCount],word 0
- sti ;ready to handle interrupts
- ;mov word [BV.CursorPos],0x0800
- mov si,Msg.keyBoot
- ;pop bx ;zero from stack
- call DisplayString
- ; pop ax ;zero from stack
- .bootMenu:
- ; int 0x16
- .bootFD:
- mov ax,0x201 ;floppy read one sector
- mov cx,1 ;track 0 sector 1
- xor dx,dx ;head 0 disk 0
- pop es ;load seg from empty stack
- mov bx,0x3ce0 ;load ofs
- int 0x13 ;read sector
- ;es mov ax,[0x7dfe]
- ;xor bx,bx
- ;call DisplayNAX
- ;cmp ax,0xaa55
- ;.noboot jne .noboot
- ; pop ax ;zero from stack
- ; int 0x10
- ;pop es ;zero from stack
- mov di,0x3d00
- push di ;boot offset
- cld
- mov ch,1 ;actually copies 2 extra bytes
- mov si,FreeDOSBoot
- rep movsw
- mov ds,cx
- mov si,0x3ceb
- mov di,0x3d0b
- mov cl,0xa ;copy disk info
- rep movsw ;es prefix may require interrupts disabled
- mov dl,0
- retf ;cs from empty stack
- FreeDOSBoot:
- incbin "freedos.bs"
- ***** CUT HERE ***** BEGIN FILE keyboard.asm
- INT16: ;keyboard API
- .getfun:
- ;jmp short .nofun
- .eshift:
- ;jmp short .nofun
- .entry: ;call IntPrint
- ;call CheckIt
- push bp
- push bx
- mov bp,sp
- xchg ah,al
- cmp al,1
- je .checkkey ;check for keystroke
- jb .getkey ;get keystroke
- cmp al,3
- je .shift ;get shift flags
- cmp al,5
- je .store ;store keystroke
- cmp al,9
- je .getfun ;get keyboard functionality
- cmp al,0x10
- je .getkey ;get enhanced keystroke
- jb .nofun
- cmp al,0x12
- ;je .eshift ;get extended shift states
- jb .checkkey ;check for enhanched
- .nofun xchg ah,al
- .noex pop bx
- pop bp
- iret
- .getkeyptr:
- cli ;clear interrupts for this operation
- cs mov bx,[BV.NextKey]
- cs cmp [BV.FirstFreeKey],bx
- ret
- .checkkey:
- sti ;make sure interrupts were enabled at least for a moment
- or byte [bp+8],0x40 ;was +4 ;set zero to on ;SS
- call .getkeyptr
- je .nocheck
- cs mov ax,[bx]
- xchg ah,al
- xor byte [bp+8],0x40 ;was +4 ;toggle zero ;SS
- .nocheck:
- jmp short .nofun
- .getkeywaitlp:
- sti ;interrupts still disabled
- hlt ;interrupts disabled until halted
- .getkey:
- call .getkeyptr
- je .getkeywaitlp ;loop until we have a keypress
- cs mov ax,[bx]
- inc bx
- inc bx
- cs cmp [BV.KeyBufferEnd],bx ;do we need to loop over?
- jne .gnoloop
- cs mov bx,[BV.KeyBufferStart]
- .gnoloop:
- cs mov [BV.NextKey],bx
- jmp short .noex
- .shift:
- cs mov al,[0] ;FIXME
- jmp short .noex
- .store:
- push ax
- push ds
- push cs
- pop ds
- cli ;don't want two things updating the buffer at once!
- mov bx,[BV.FirstFreeKey]
- mov [bx],cx
- lea ax,[bx+2]
- cmp [BV.KeyBufferEnd],ax ;do we need to loop over?
- jne .noloop
- mov ax,[BV.KeyBufferStart]
- .noloop: ;if it was full, we'll pretend it never happened
- cmp [BV.NextKey],ax
- je .dropkey
- mov [BV.FirstFreeKey],ax
- .dropkey:
- pushf
- call ProcessKeys ;just in case they sent a special key
- popf
- pop ds
- pop ax
- mov ah,0 ;can't use xor here
- jne .bufnotfull
- inc ah
- .bufnotfull:
- jmp short .nocheck;.nofun
- KeyUART: ;stack usage: 4+1 words
- cli
- push ax
- push bx
- push ds
- in al,0x3a
- test al,2
- jz .jiret
- ;ok, we know we have a key
- push cs
- pop ds
- ;let's get the character and write it to the buffer
- or al,0xf7 ;turn on all the bits besides parity in the status
- mov ah,al
- in al,0x38 ;get data byte
- mov bx,[BV.FirstFreeKey]
- mov [bx],ax
- lea ax,[2+bx]
- cmp [BV.KeyBufferEnd],ax ;do we need to loop over?
- jne .noloop
- mov ax,[BV.KeyBufferStart]
- .noloop: ;if it was full, we'll pretend it never happened
- cmp [BV.NextKey],ax
- je .dropkey
- mov [BV.FirstFreeKey],ax
- .dropkey:
- mov al,0x37
- out 0x3a,al
- call ProcessKeys
- .jiret pop ds
- pop bx
- pop ax
- iret
- ProcessKeys:
- ;destroys ax,bx,ds
- mov ax,0xfe00
- mov ds,ax
- ;do locking checks
- test byte [BV.LFlags+0x2400],0xe ;is something else in progress?
- jz .doit
- or byte [BV.LFlags+0x2400],0x20 ;yes, do it later
- ret
- .doit: ;start with the first used key
- mov bx,[BV.NextKey+0x2400]
- .pkloop: ;retrieve the key to ax
- cs mov ax,[bx]
- ror ah,1
- ror ah,1
- ror ah,1
- xor ah,0xfe ;ah is 0 for no ctrl, 1 for ctrl
- test ah,0xfe
- jnz .noproc ;key was already processed
- ;process 'special' keys here, zero ax to clear them from the buffer
- cmp ax,0x103 ;ctrl break
- jne .nobreakout
- xor ax,ax
- cs mov [bx],ax ;store key
- jmp Menu_Breakout
- .nobreakout:
- shl ax,1
- xchg ax,bx
- mov bx,[bx] ;do ROM lookup
- xchg ax,bx
- cs mov [bx],ax ;store key
- .noproc: ;gotta check if we're to the free keys
- cmp [BV.FirstFreeKey+0x2400],bx
- je DisplayString.jret ;yep, get out
- inc bx
- inc bx
- ;do we need to wrap over?
- cmp [BV.KeyBufferEnd+0x2400],bx
- jne .pkloop
- mov bx,[BV.KeyBufferStart+0x2400]
- jmp short .pkloop
- ***** CUT HERE ***** BEGIN FILE menu.asm
- Menu_Breakout:
- cld
- push ax
- push dx
- push ds
- push es
- mov ax,cs
- mov ds,ax
- mov es,ax
- .clearKey:
- xor ax,ax
- int 0x16
- mov ah,1
- int 0x16
- jnz .clearKey
- ;test [BV.LFlags],byte 1
- ;jz .noVideo
- ;or [BV.LFlags],byte 0x40 ;request breakout callback upon video completion mov al,'#'
- ;int 0x29
- ;pop es
- ;pop ds
- ;pop dx
- ;pop ax
- ;ret
- .noVideo:
- ;or byte [BV.LFlags],8
- ;mov al,[BV.LFlags]
- ;and [BV.LFlags],byte 0xbf
- ;and al,0x40
- ;int 0x29
- .lp0:
- call TickBuzzer
- .keyloop:
- xor ax,ax
- int 0x16
- cmp al,'r'
- jne .noReboot
- jmp Reboot
- .noReboot:
- cmp al,'0'
- jne .no0
- mov dl,0
- jmp short .setkey
- .no0:
- cmp al,'1'
- jne .no1
- mov dl,1
- jmp short .setkey
- .no1:
- cmp al,'c'
- jne .noc
- push si
- push di
- call CGA.Init
- pop di
- pop si
- .noc:
- call TickBuzzer
- ;and byte [BV.LFlags],0xf7
- pop es
- pop ds
- pop dx
- pop ax
- ret
- .setkey:
- push bx
- push cx
- push si
- push di
- mov di,BV.EncKey
- call Enter_Key
- pushf
- mov bx,dx
- and bx,1
- add bx,BV.DFlags
- ror byte [bx],1
- popf
- cmc
- rcl byte [bx],1
- call Generate_Subkeys
- pop di
- pop si
- pop cx
- pop bx
- jmp short .lp0
- Menu_SaveVideo:
- ;save cursor position
- ;save line 1
- ;configure for single line video
- ;ret
- Menu_RestoreVideo:
- ;restore video settings
- ;restore line 1
- ;restore cursor position
- ;ret
- ***** CUT HERE ***** BEGIN FILE misc.asm
- ;FIXME: Assumes BIOS_CS=BIOS_DS and BIOS_CS && 0xFF00=0
- INT8:
- ;to be done
- INT11:
- cs mov ax,[BV.Equipment]
- iret
- INT12:
- cs mov ax,[BV.TotalRAM]
- NoInterrupt:
- iret
- Reboot:
- mov al,0xff
- out 0x3a,al ;reset keyboard UART for buggy OSes *cough*SANYO*cough*
- jmp 0xffff:0
- INT15:
- push bp
- mov bp,sp
- or byte [bp+6],1 ;set carry - helps with freedos memory detection
- pop bp
- iret
- ;call IntPrint
- ; cmp ah,0xc0
- ; jne NoInterrupt
- ; push cs
- ; pop es
- ; mov bx,.table
- ; xor ah,ah
- ; popf ;fixme, this is invalid
- ; clc
- ; retf
- ;.table dw .endtable-.starttable
- ;.starttable
- ; db 0xf7 ;model
- ; db 0 ;submodel
- ; db 0 ;BIOS Revision
- ; db 0
- ; db 0x84 ;int16/ah=9 supported & non-8042 keyboard
- ; db 2 ;IML System
- ; db 8 ;ABIOS not supported
- ; db 0
- ; db "dsBIOS",0
- ;.endtable
- INT29: ;fast console output
- ;push ax
- push bx
- mov bl,7
- cs mov bh,[BV.CurPage]
- push si
- call OnBoardVideo.WrTT
- pop si
- pop bx
- ;pop ax
- iret
- FPUInterrupt:
- int 0x75
- int 0x2
- iret
- DisplayString:
- ;ds:si=string, si is incremented to character after null
- ;bl=attribute
- ;direction flag must be set as desired, this clears carry
- push ax
- push bx
- .lp lodsb
- or al,al
- jz .done
- int 0x29
- jmp short .lp
- .done:
- pop bx
- pop ax
- .jret:
- ret
- DisplayNAX:
- push ax
- push dx
- push cs ;high byte is zero
- .clp xor dx,dx
- cs div word [.base]
- xchg ax,dx
- add ax,0xe30
- push ax
- xchg ax,dx
- or ax,ax
- jnz .clp
- .dlp pop ax
- or ah,ah
- jz .done
- int 0x29
- jmp short .dlp
- .done pop dx
- pop ax
- ret
- .base dw 10
- TickBuzzer:
- .lp:
- in al,0x3a
- test al,1
- jz .lp
- mov al,0x18
- out 0x38,al
- ret
- InterruptCatcher:
- ;On entry: low byte of CS=Interrupt number
- push cs
- jmp BIOS_CODE_SEG:InterruptCatcher.main
- .main:
- push bp
- mov bp,sp
- push ax
- push si
- push ds
- push cs
- pop ds
- cld
- mov si,.msg
- call DisplayString
- mov al,[bp+2]
- xor ah,ah
- call DisplayNAX
- mov al,'/'
- int 0x29
- mov ax,[bp-2]
- call DisplayNAX
- call DisplayString
- pop ds
- pop si
- pop ax
- pop bp
- inc sp ;pop saved cs
- inc sp
- iret
- .msg:
- db "[dsBIOS: Unhandled Interrupt: ",0,"]",0
- %ifdef PigsFly
- DrawBox: ;this code is unfinished
- ; Input: AH=upper left row, AL=upper left col
- ; BH=#rows (outside dimension, zero is width 1) BL=#cols
- ;Trashed: CX, DX
- ;Internal: DX=current cursor pos
- ;Draw top line
- mov dx,al
- mov al,2 ;set cursor
- int 0x10
- mov al,201 ;upper left
- int 0x29
- mov cx,bx
- mov al,205 ;top mid
- .topmid
- dec cl
- jz .notopmid
- int 0x29
- dec cl
- jmp short .topmid
- .notopmid
- mov al,topright
- int 0x29
- ;now the middle portion
- inc
- ret
- DisplayNAXH: ;Displays AX in hexadecimal
- push ax
- push dx
- push cs ;high byte is zero
- xor dx,dx
- cs div word [.base]
- add dx,0xe30
- push dx
- xor dx,dx
- cs div word [.base]
- add dx,0xe30
- push dx
- xor dx,dx
- cs div word [.base]
- add dx,0xe30
- push dx
- xor dx,dx
- cs div word [.base]
- add dx,0xe30
- push dx
- .dlp pop ax
- or ah,ah
- jz .done
- cmp al,0x3a
- jb .dit
- add al,7
- .dit int 0x29
- jmp short .dlp
- .done pop dx
- pop ax
- ret
- .base dw 16
- IntPrint: ;meant to be called as first instruction of an interrupt handler
- ;(prints out registers and waits for a key)
- push ds
- push ax
- push si
- push cs
- pop ds
- push word [BV.CursorPos]
- mov [BV.CursorPos],word 0x1400
- mov si,MsgReg
- call DisplayString
- mov si,sp
- ss mov ax,[si+12];10]
- mov ds,ax
- ss mov si,[si+10];8]
- mov ax,[si-2]
- cs mov [BV.CursorPos],byte 4
- call DisplayNAXH
- cs mov [BV.CursorPos],byte 14
- mov si,sp
- ss mov ax,[si+4]
- call DisplayNAXH
- mov ax,bx
- call DisplayNAXH
- mov ax,cx
- call DisplayNAXH
- mov ax,dx
- call DisplayNAXH
- cs mov [BV.CursorPos],byte 36
- ss mov ax,[si+12];10]
- call DisplayNAXH
- ss mov ax,[si+6]
- call DisplayNAXH
- mov ax,es
- call DisplayNAXH
- mov ax,ss
- call DisplayNAXH
- ss mov ax,[si+10];8]
- call DisplayNAXH
- cs pop word [BV.CursorPos]
- pushf
- push cs
- mov ax,.gkret
- push ax
- push bp
- push bx
- jmp INT16.getkey
- .gkret pop si
- pop ax
- pop ds
- ret
- %endif
- ***** CUT HERE ***** BEGIN FILE onboardv.asm
- ;BIOS INT10 Driver for the Sanyo MBC-55x Onboard Video
- OnBoardVideo: ;interrupt handler
- push si
- cld
- mov si,ax
- mov al,ah
- test al,0xf0
- cbw ;clear ah
- xchg ax,si
- jnz .OutOfRange
- shl si,1
- ;cs or [BV.LFlags],byte 1
- cli ;reentrant? hah!
- cs call [si+.jmptable]
- .OutOfRange:
- pop si
- ;cs and [BV.LFlags],byte 0xfe
- ;cs test [BV.LFlags],byte 0x40
- ;jnz .DoBIOSMenu
- iret
- ;.DoBIOSMenu
- ; push ax
- ; mov al,'#'
- ; int 0x29
- ; pop ax
- ; call Menu_Breakout
- ; iret
- .SetGetCursor:
- ;push bx
- ;mov bl,bh
- ;and bx,byte 7 ;pages not implemented in built-in video; always set page 0
- ;shl bx,1
- ;lea si,[byte BV.CursorPos+bx]
- ;pop bx
- sahf
- jnc .SetOnly
- cs mov dx,[BV.CursorPos] ;si
- cs mov cx,[BV.CEndLine]
- ret
- .SetOnly:
- ;hide cursor if drawn!! FIXME
- ;validate cursor position!! FIXME
- cs mov [BV.CursorPos],dx ;si for addr
- ;ret
- .SetPage:
- ;unimplimented for built-in video
- ;push di
- ;push dx
- ;push ax
- ;call InitCGA
- ;pop ax
- ;pop dx
- ;pop di
- ret
- .SetMode:
- ;hmm... not really sure about this one... let's clear the
- ;screen and reset the cursor? The CGA will care more.
- push es
- push di
- push cx
- ;call InitCGA
- xor di,di
- cld
- mov ax,VIDEO_SEG
- mov es,ax
- mov ax,di
- mov cx,0x2000 ;FIXME for hardware scrolling
- rep stosw
- cs mov word [BV.CursorPos],0
- pop cx
- pop di
- pop es
- mov ax,0030
- ret
- .RdAttChr:
- mov ax,0x0320 ;unimplimented for built-in video
- .NoFunction:
- ;ret
- .SetCursorShape:
- ;ret
- .ScrollDn:
- ret
- .ScrollUp:
- push bx
- push cx
- jmp .doscroll ;HACK HACK FIXME FIXME
- ;ret
- .WrAttChr:
- push ax
- push ds
- push es
- push di
- push cx
- push dx
- xchg ax,si ;put ax in si (clears ah unless function > 127)
- cwd ;clear dx
- ;calculate dest. location
- ;xchg bh,bl
- ;mov di,bx
- ;xchg bh,bl
- ;and di,byte 7 ;max 8 pages
- ;shl di,1
- ;get the cursor data into ax and di (low=col high=row)
- cs mov ax,[BV.CursorPos];+di]
- ;take care of the row offset and swap it into di
- mov di,ax
- cs mov al,[BV.ScreenCols]
- mov dl,al
- shl dx,1
- shl dx,1
- mul ah
- shl ax,1
- xchg ax,di
- ;mask off the row
- cbw ;xor ah,ah (as long as rows < 128, this is safe)
- ;each col adds 4 to the offset
- ;add the col. offset on
- add di,ax
- times 2 shl di,1
- and si,0xff
- mov ax,VIDEO_SEG
- mov es,ax
- mov ah,0xff
- mov ds,ax
- times 3 shl si,1
- .repchr movsw
- movsw
- add di,dx ;(columns-1) * 4
- sub di,4
- movsw
- lodsw
- cmp bl,1
- jne .noul
- mov ah,0xff
- .noul stosw
- sub di,dx ;columns * 4
- sub si,8
- loop .repchr
- pop dx
- pop cx
- pop di
- pop es
- pop ds
- pop ax
- ret
- .WrChr:
- ;FIXME ideally, we read the old character and preserve the attribute?
- push bx
- mov bl,3
- call .WrAttChr
- pop bx
- ;ret
- .WrPixel:
- ;ret
- .RdPixel:
- ret
- ;WrTT starts here
- .doscroll:
- ;cs mov [BV.CursorPos+si],word 0
- ;xchg ax,si
- ;mov ax,1
- ;mov bh,bl
- ;xor cx,cx
- ;cs mov dl,[BV.ScreenCols]
- ;dec dx
- ;mov dh,24
- ;xchg ax,si
- ;.doscrollnocursor
- ;for now, just scroll up one line and blank last line
- push ax
- push ds
- push es
- ;bx, cx, and si are already preserved
- push di
- ;cld direction already cleared
- mov ax,VIDEO_SEG
- mov es,ax
- mov ds,ax
- mov al,8
- cs mov cl,[BV.ScreenCols]
- mul cl
- mov si,ax ;cols*8
- xor di,di
- cs mov al,[BV.ScreenRows]
- mul cl
- shl ax,1
- shl ax,1
- xchg ax,cx;cols*(rows-1)*4
- rep movsw
- xchg ax,cx
- xor ch,ch
- shl cx,1
- shl cx,1 ;cols*4
- ;xor ax,ax ;cleared from last rep movsw
- rep stosw
- pop di
- pop es
- pop ds
- pop ax
- jmp short .done
- .do13 cs mov byte [BV.CursorPos],0 ;+si for cursor pages
- pop bx
- ret
- .offS cs mov byte [BV.CursorPos],0 ;+si
- .do10 cs cmp byte [BV.CursorPos+1],24 ;+si
- je .doscroll
- cs inc byte [BV.CursorPos+1] ;+si
- pop cx
- pop bx
- ret
- .doFF:
- pop bx
- jmp .SetMode
- .WrTT:
- push bx
- ;hide cursor if drawn!! FIXME
- xchg bh,bl
- mov si,bx
- xchg bh,bl
- and si,7
- shl si,1
- cmp al,13 ;cr
- ja .doNormalCX
- je .do13
- cmp al,8 ;backspace
- je .do8
- cmp al,12
- je .doFF
- push cx ;we need to keep cx at this point
- cmp al,9
- je .do9
- cmp al,10 ;lf
- je .do10
- cmp al,7 ;beep
- jne .doNormal
- .do7 xchg ax,si
- mov cx,3
- .lp7 call TickBuzzer
- loop .lp7
- xchg ax,si
- jmp short .done
- .doNormalCX:
- push cx
- .doNormal:
- mov cx,1
- push ax
- .doD push si
- mov bl,3
- call .WrAttChr
- pop si
- pop ax
- cs add cx,[BV.CursorPos] ;+si
- ;check if past end of line
- cs cmp cl,[BV.ScreenCols]
- jae .offS
- cs mov [BV.CursorPos],cl ;normal increment +si
- .done pop cx
- pop bx
- ret
- .do9 xor cx,cx
- cs mov cl,[BV.CursorPos] ;+si
- add cl,8
- and cl,0xf8
- cs sub cl,[BV.CursorPos] ;+si
- push ax
- mov al," "
- jmp short .doD
- .do8 mov bl,0xff
- cs add bl,[BV.CursorPos] ;+si
- jnc .nobs
- cs mov [BV.CursorPos],bl ;+si
- .nobs pop bx
- ret
- .GetState:
- cs mov ax,[BV.CurMode]
- cs mov bh,[BV.CurPage]
- ret
- .jmptable:
- dw .SetMode
- dw .SetCursorShape
- dw .SetGetCursor ;set
- dw .SetGetCursor ;get
- dw .NoFunction
- dw .NoFunction ;.SetPage
- dw .ScrollUp
- dw .ScrollDn
- dw .RdAttChr
- dw .WrAttChr
- dw .WrChr
- dw .NoFunction
- dw .WrPixel
- dw .RdPixel
- dw .WrTT
- dw .GetState
- ***** CUT HERE ***** BEGIN FILE rijndael.asm
- ;; Rijndael Encryption Algorithm, in 80186/286 assembler, version 1.2b
- ;; Copyright (C) 2000 Rafael R. Sevilla
- ;; (Modified 2005 by Brad Normand for optimization and use in dsBIOS)
- ;;
- ;; This library of encryption routines is free software; you can
- ;; redistribute it and/or modify it under the terms of the GNU Lesser
- ;; General Public License as published by the Free Software Foundation;
- ;; either version 2 of the License, or (at your option) any later
- ;; version.
- ;;
- ;; This Rijndael Encryption code is distributed in the hope it will
- ;; be useful, but WITHOUT ANY WARRANTY; without even the implied
- ;; warranty of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE.
- ;; See the GNU Lesser General Public License for more details.
- ;;
- ;; You should have received a copy of the GNU Lesser General Public
- ;; License along with this Rijndael Encryption code; see the file
- ;; COPYING.LIB. If not, write to the Free Software Foundation, Inc.,
- ;; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- ;;
- ;; Note that the only 80186 instructions here are shr/shl instructions
- ;; with multibit counts, and these only appear in the key expansion
- ;; function. (These instructions have been changed to 8086 compatible
- ;; equivalents -Brad)
- ;;
- ;; Heavy restructuring and optimization has been done to increase speed
- ;; on 8086 type machines - Brad
- ;;
- ;; The modification here has incorporated a few changes suggested by
- ;; Robert G. Durnal (afn21533@afn.org), and a major bugfix in the
- ;; key generation code.
- ;;
- ;; Rijndael was developed by Joan Daemen and Vincent Rijmen
- ;;
- CPU 186 ;actually 8086, but dsBIOS needs this
- ;SECTION .data ;(For the dsBIOS project, CS=DS -Brad)
- ;; S-box for Rijndael
- sbox:
- %ifdef rijndael_empty_data ;dsBIOS generates these at boot
- times 256 db 0
- %else
- db 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43
- db 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240
- db 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38
- db 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21
- db 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226
- db 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160
- db 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237
- db 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207
- db 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127
- db 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245
- db 188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236
- db 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115
- db 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20
- db 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92
- db 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109
- db 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8
- db 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31
- db 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14
- db 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17
- db 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223
- db 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15
- db 176, 84, 187, 22
- %endif
- ;; Inverse S-box for Rijndael
- isbox:
- %ifdef rijndael_empty_data
- times 256 db 0
- %else
- db 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158
- db 129, 243, 215, 251, 124, 227, 57, 130, 155, 47, 255, 135
- db 52, 142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50
- db 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78
- db 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73
- db 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22
- db 212, 164, 92, 204, 93, 101, 182, 146, 108, 112, 72, 80
- db 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132
- db 144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5
- db 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2
- db 193, 175, 189, 3, 1, 19, 138, 107, 58, 145, 17, 65
- db 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115
- db 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232
- db 28, 117, 223, 110, 71, 241, 26, 113, 29, 41, 197, 137
- db 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75
- db 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244
- db 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89
- db 39, 128, 236, 95, 96, 81, 127, 169, 25, 181, 74, 13
- db 45, 229, 122, 159, 147, 201, 156, 239, 160, 224, 59, 77
- db 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97
- db 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99
- db 85, 33, 12, 125
- %endif
- ;SECTION .text ;(see note above -Brad)
- ;; small procedure to mix keys. CX must point to round key offset.
- ;; Destroys AX, SI (nosetup adds 16 to SI), and DI. Clears direction.
- mixkey:
- cld
- mov si,[bp+6] ; base address of round keys
- add si,cx ; make si address of current round key
- mov bx,[bp+4] ; load cipher state address
- mixkey_nosetup:
- lodsw ; load first word BEFORE finding offset
- sub bx,si ; bx is the offset between the round key and state
- %rep 7
- xor [si+bx],ax
- lodsw
- %endrep
- xor [si+bx],ax
- ret
- xlat_rotate:
- ;bx must point to translation table (sbox or isbox)
- ;if carry=1, rotate to right. if carry=0, rotate left.
- ;destroys ax, dx, si, and di
- mov si,[bp+4] ; load cipher state address
- mov di,si
- ;translate row 0 right away
- %rep 4
- lodsb
- xlatb
- stosb
- %endrep
- jc .forward
- std ;process backward
- add si,10 ;position at end of block
- mov di,si
- .forward:
- ;; Rotate (cyclically shift) row 1 by one, row 2 by two and row 3
- ;; by three.
- ;load row 1 (or 3 backwards)
- lodsw
- xchg ax,dx
- lodsw
- ;translate and rotate right by 1
- xlatb ;byte 1
- xchg ah,al
- xlatb ;byte 0
- xchg dl,al
- xlatb ;byte 3
- xchg dh,al
- xlatb ;byte 2
- ;store row 1 back (the loading order has shifted it by 2)
- stosw
- xchg ax,dx
- stosw
- ;load row 2
- lodsw
- xlatb ;byte 1
- xchg ah,al
- xlatb ;byte 0
- xchg ah,al
- xchg ax,dx
- lodsw
- xlatb ;byte 3
- xchg ah,al
- xlatb ;byte 2
- xchg ah,al
- ;store row 2 back (the loading order has shifted it by 2)
- stosw
- xchg ax,dx
- stosw
- ;load row 3 (or 1 backwards) into ax:dx
- lodsw ; first half of row
- xchg ax,dx ; lives in DX
- lodsw ; second half of row lives in AX
- ;translate and rotate row 1 left by 1 (right by 3)
- xlatb ;byte 1
- xchg dh,al
- xlatb ;byte 2
- xchg dl,al
- xlatb ;byte 3
- xchg ah,al
- xlatb ;byte 0
- ;store row 3 back
- stosw ; store first half of row
- xchg ax,dx ; make ax the second
- stosw ; store second half of row
- ;cld ;mixkey clears direction flag
- ret
- ; global _rijndael_encrypt ;(don't need globals for dsBIOS -Brad)
- rijndael_encrypt:
- push bp
- mov bp,sp
- push si
- push di
- xor cx,cx
- call mixkey
- mov cl,16 ; round key offset (16*round_number)
- .round_top:
- mov bx,sbox ; translate using sbox
- stc ; rotate right
- call xlat_rotate ; translate and rotate
- cmp cl,224 ;was cx ; are we at round 14 (16*14)?
- je .finalize ; yes, jmp
- ;; Do the MixColumn transformation.
- mov di,4 ; column loop counter
- mov si,[bp+di];di=4 ; load the address of the state
- ;push bp
- push cx ; save cx
- .do_mixcolumn:
- mov cl,[si] ; zeroth byte of column
- mov dl,[si+4] ; first byte of column
- mov ch,[si+8] ; second byte of column
- mov dh,[si+12] ; third byte of column
- mov bp,cx ; save a[j] and a[j+8] to xor with
- mov ax,cx ; let ax = tmp,tmp
- xor ax,dx
- xor ah,al
- mov al,ah ; tmp is set up
- xor cx,dx ; xor with a[j+4], a[j+12]
- shl cl,1 ; xtime a[j] and a[j+8]
- sbb bl,bl
- shl ch,1
- sbb bh,bh
- and bx,0x1b1b
- xor cx,bx ; xtime done
- xor cx,ax ; xor with tmp
- xchg dh,dl ; byteswap a[j+4], a[j+12] to line up for xor
- xor dx,bp ; xor with saved a[j+8], a[j]
- shl dl,1 ; xtime these two bytes
- sbb bl,bl
- shl dh,1
- sbb bh,bh
- and bx,0x1b1b
- xor dx,bx ; xtime done
- xor dx,ax ; xor with tmp
- xor [si],cl ; store back to state by xoring with orig
- xor [si+4],dh
- xor [si+8],ch
- xor [si+12],dl
- inc si ; point to next column
- dec di
- jnz .do_mixcolumn
- pop cx ; restore cx
- ;pop bp
- mov bp,sp
- add bp,4
- call mixkey ; mix the key
- add cx,16 ; increment the loop counter
- jmp short .round_top
- .finalize:
- ;; Perform a final key mixing before finishing up
- call mixkey
- pop di
- pop si
- pop bp
- ret
- ; global _rijndael_decrypt
- rijndael_decrypt:
- push bp
- mov bp,sp
- push si
- push di
- mov cx,224 ; round key offset (14*16)
- ;; Perform the initial key mixing operation
- call mixkey
- ;; The first round doesn't perform the inverse column mixing.
- jmp .start_isbox
- .round_top:
- call mixkey
- ;; The inverse column mixing is much more ticklish than the straight
- ;; mix...
- mov si,[bp+4] ; load the address of the state
- mov ch,4 ; column loop counter
- ;push bp
- mov bp,0x1b1b ; values for *2 operation
- .do_invmixcolumn:
- push cx
- mov cl,[si] ; zeroth byte of column
- mov ch,[si+4] ; first byte of column
- mov dl,[si+8] ; second byte of column
- mov dh,[si+12] ; third byte of column
- ;; Multiply by 0x0e in GF(2^8) (`*' denotes multiplication in GF(2^8))
- .invmix_onecolumn:
- ;output bytes (low,high):
- ;ax=x,y di=z,w
- mov ax,cx ;ax(x,y)=w,x
- xor ax,dx ;ax(x,y)=w^y,x^z
- mov di,ax ;di(z,w)=w^y,x^z
- xor ah,cl ;ah(y)=w^x^z
- xor al,dh ;al(x)=w^y^z
- xchg ax,di ;ax=z,w di=x,y
- xor ah,dl ;ah(w)=x^y^z
- xor al,ch ;al(z)=w^x^y
- ;now do *2 to each source byte
- shl cl,1
- sbb bl,bl
- shl ch,1
- sbb bh,bh
- and bx,bp;0x1b1b
- xor cx,bx ;first 2 done
- shl dl,1
- sbb bl,bl
- shl dh,1
- sbb bh,bh
- and bx,bp;0x1b1b
- xor dx,bx ;all *2'd
- ;for this part, w:w,x x:x,y y:y,z z:z,w
- ;ax=z,w di=x,y
- xor ax,cx ;ax(z,w)=w,x
- xor al,dh ;al(z)=w^z
- xor ah,cl ;ah(w)=w^x
- xchg ah,al
- xchg ax,di ;ax=x,y di=w,z
- xor ax,dx ;ax(x,y)=y,z
- xor al,ch ;al(x)=x^y
- xor ah,dl ;ah(y)=y^z
- xchg ah,al ;ax=y,x di=w,z
- ;now do *2 to each source byte
- shl cl,1
- sbb bl,bl
- shl ch,1
- sbb bh,bh
- and bx,bp;0x1b1b
- xor cx,bx ;first 2 done
- shl dl,1
- sbb bl,bl
- shl dh,1
- sbb bh,bh
- and bx,bp;0x1b1b
- xor dx,bx ;all *2'd
- ;for this part, w:w,y x:x,z y:w,y z:x,z
- ;ax=y,x di=w,z
- xor ax,cx
- xor ax,dx
- xor di,cx
- xor di,dx
- ;now do *2 to each source byte
- shl cl,1
- sbb bl,bl
- shl ch,1
- sbb bh,bh
- and bx,bp;0x1b1b
- xor cx,bx ;first 2 done
- shl dl,1
- sbb bl,bl
- shl dh,1
- sbb bh,bh
- and bx,bp;0x1b1b
- xor dx,bx ;all *2'd
- xor cx,dx ;don't care about preserving source bytes anymore
- xor cl,ch
- mov ch,cl
- xor ax,cx
- xor cx,di ;(moved to cx)
- ;ax=y,x cx=w,z
- mov [si],cl ;save bytes
- mov [si+4],ah
- mov [si+8],al
- mov [si+12],ch
- ;.end_col_invmix:
- inc si ; point to next column
- pop cx
- dec ch ;column loop counter (clears carry)
- ;jnz .do_invmixcolumn
- jz .start_isbox
- jmp .do_invmixcolumn
- ;pop bp ; restore saved registers
- .start_isbox:
- mov bp,sp
- add bp,4
- mov bx,isbox ; translate using isbox
- ;clc ; rotate to the left (carry was cleared above)
- call xlat_rotate
- sub cx,16
- jz .do_mixkey
- jmp .round_top
- .do_mixkey:
- call mixkey
- pop di
- pop si
- pop bp
- ret
- ; global _rijndael_keygen
- rijndael_keygen:
- cld
- push bp
- mov bp,sp
- push si
- push di
- ;; Copy the original key data into the W[] array. This generates
- ;; the keys used in the first two rounds.
- mov si,[bp+4]
- mov di,[bp+6]
- lea bx,[si+32]
- .copy_again:
- mov cx,4
- .copy_key:
- lodsw ; get two bytes of key information
- mov [di],al
- mov [di+4],ah
- lodsw ; get another two bytes of key info
- mov [di+8],al
- mov [di+12],ah
- inc di ; point to next column
- loop .copy_key ; (changed this to a loop -Brad)
- add di,12 ; point di to next block
- cmp si,bx
- jne .copy_again
- mov cl,7 ; key number minus 1 (ch was zeroed above)
- mov di,1 ; round constant
- ;mov bx,[bp+6] ; base address of generated keys
- mov bx,cx
- mov si,bx
- and bl,0xfc ; clear low four bits(only clears 2 bits? -Brad)
- shl bx,1 ; (granted these 'clear' the other two... -Brad)
- shl bx,1
- and si,3 ; mask low four bits (again, only 2 bits? -Brad)
- add bx,si
- add bx,[bp+6] ; SI points to column to get
- .keygen_loop:
- mov dl,[bx]
- mov dh,[bx+4]
- mov al,[bx+8]
- mov ah,[bx+12]
- inc cx
- ;; Now dl = first byte, dh = second, al = third, ah=fourth
- test cl,00000011b ; is round # div. by 4 or 8?
- jnz .not_div4 ; no...
- ;; Apply the S-boxes if round # is divisible by 4 or 8
- mov bx,sbox ; load address of S-box for xlat
- xlatb ; al = sbox[#3]
- xchg ah,al ; ah = sbox[#3], al=#4
- xlatb ; ah=sbox[#3], al=sbox[#4]
- xchg ax,dx ; ah=#2, al=#1, dh=sbox[#3], dl=sbox[#4]
- xlatb ; ah=#2, al=sbox[#1]
- xchg ah,al ; ah=sbox[#1], al=#2, dh=sbox[#3], dl=sbox[#4]
- xlatb ; al=sbox[#2]
- ;; Now, ah=sbox[#1], al=sbox[#2], dh=sbox[#3], dl=sbox[#4].
- ;; Test whether round is divisible by 8. If so, further transforms
- ;; are needed.
- test cl,00000111b ; is round # div by 8?
- jnz .not_div8 ; no...we're done
- ;; What we want is to rotate the data so that ah=sbox[#2], al=sbox[#3],
- ;; dh=sbox[#4], and dl=sbox[#1]. This is the cycle (0 1 2 3) which
- ;; can be turned into the product of transpositions (you by XCHG
- ;; instructions) (0 3)(0 2)(0 1)
- xchg ah,dl ; (0 3)
- xchg ah,dh ; (0 2)
- xchg ah,al ; (0,1)
- xchg bx,di ;get round constant from di
- xor ah,bl ;xor with round constant
- shl bl,1 ;update round constant
- sbb bh,bh
- and bh,0x1b
- xor bl,bh
- xchg bx,di ;store next round constant back
- .not_div8:
- ;; Now we have to rearrange the order of the registers again so that
- ;; from ah=#1, al=#2, dh=#3, dl=#4 => dl=#1, dh=#2, al=#3, ah=#4, so
- ;; that the following code gets the registers where they are expected.
- xchg ah,dl
- xchg al,dh
- .not_div4:
- ;; When we enter here, dl=first byte, dh=second, al=third, ah=fourth
- ;; Perform indexing on the address of the previous key again.
- mov bx,cx
- mov si,bx
- and bl,0xfc
- shl bx,1
- shl bx,1
- and si,3
- add bx,si ; offset into keys for first byte of old key
- add bx,[bp+6] ; add base address of subkeys
- xor dl,[bx-32] ; xor with current
- xor dh,[bx-28]
- xor al,[bx-24]
- xor ah,[bx-20]
- mov [bx],dl
- mov [bx+4],dh
- mov [bx+8],al
- mov [bx+12],ah
- cmp cx,59 ; last key?
- jne .keygen_loop
- .done: pop di
- pop si
- pop bp
- ret
- ***** CUT HERE ***** BEGIN FILE timer.asm
- ;ASSUMES BIOS_CODE_SEG = BIOS_DATA_SEG!! FIXME
- Timer0:
- cli
- push ax
- push dx
- push ds
- push cs
- pop ds
- mov dx,[BV.AuxTickCount]
- ;read timer 1
- in al,0x22
- mov ah,al
- in al,0x22
- xchg ah,al
- mov [BV.AuxTickCount],ax
- sub dx,ax
- shl dx,1 ;multiply dx by two because sanyo ticks are half as fast as normal IBM
- ;dx now has the amount of ticks elapsed since last time
- ;carry has an overflow bit
- adc word [BV.TimerTicksH],0
- add word [BV.TimerTicksL],dx
- adc word [BV.TimerTicksH],0
- cmp word [BV.TimerTicksH],24 ;check for 24 hours
- jb .carry2
- sub word [BV.TimerTicksH],24 ;24 hours
- inc byte [BV.DaysPassed]
- .carry2:
- sti
- ;int 0x1c
- int 0x8 ;emulate hardware timer interrupt
- .exit:
- pop ds
- pop dx
- pop ax
- iret
- ;And some time/date API:
- INT1A:
- cli ;don't want the time changing while we access it!!
- cmp ah,0x1
- je .set
- jnb .exit
- .get: ;Get system time
- cs mov al,[0x70]
- cs mov cx,[BV.TimerTicksH];[0x6e]
- cs mov dx,[BV.TimerTicksL];[0x6c]
- .set: ;Set system time
- cs mov byte [0x70],0x0 ;clear day counter
- cs mov [BV.TimerTicksH],cx
- cs mov [BV.TimerTicksL],dx
- .exit:
- iret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement