mirror of
https://github.com/xcat2/xNBA.git
synced 2024-11-22 17:41:55 +00:00
498 lines
12 KiB
NASM
498 lines
12 KiB
NASM
|
; Copyright (C) 1997 Markus Gutschke <gutschk@uni-muenster.de>
|
|||
|
;
|
|||
|
; This program is free software; you can redistribute it and/or modify
|
|||
|
; it under the terms of the GNU General Public License as published by
|
|||
|
; the Free Software Foundation; either version 2 of the License, or
|
|||
|
; any later version.
|
|||
|
;
|
|||
|
; This program is distributed in the hope that it will be useful,
|
|||
|
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|||
|
; GNU General Public License for more details.
|
|||
|
;
|
|||
|
; You should have received a copy of the GNU General Public License
|
|||
|
; along with this program; if not, write to the Free Software
|
|||
|
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|||
|
|
|||
|
; Prepend this image file to an arbitrary ROM image. The resulting binary
|
|||
|
; can be loaded from any BOOT-Prom that supports the "nbi" file format.
|
|||
|
; When started, the image will reprogram the flash EPROM on the FlashCard
|
|||
|
; ISA card. The flash EPROM has to be an AMD 29F010, and the programming
|
|||
|
; algorithm is the same as that suggested by AMD in the appropriate data
|
|||
|
; sheets.
|
|||
|
|
|||
|
|
|||
|
#define SEGLOW 0xC800 /* lower range for EPROM segment */
|
|||
|
#define SEGHIGH 0xE800 /* upper range for EPROM segment */
|
|||
|
#define AMD_ID 0x2001 /* flash EPROM ID, only support AMD */
|
|||
|
#define ERASE1_CMD 0x80 /* first cmd for erasing full chip */
|
|||
|
#define ERASE2_CMD 0x10 /* second cmd for erasing full chip */
|
|||
|
#define READID_CMD 0x90 /* cmd to read chip ID */
|
|||
|
#define PROG_CMD 0xA0 /* cmd to program a byte */
|
|||
|
#define RESET_CMD 0xF0 /* cmd to reset chip state machine */
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
|
|||
|
.text
|
|||
|
.org 0
|
|||
|
|
|||
|
; .globl _main
|
|||
|
_main: mov ax,#0x0FE0
|
|||
|
mov ds,ax
|
|||
|
mov ax,magic ; verify that we have been loaded by
|
|||
|
cmp ax,#0xE4E4 ; boot prom
|
|||
|
jnz lderr
|
|||
|
jmpi 0x200,0x0FE0 ; adjust code segment
|
|||
|
lderr: mov si,#loaderr
|
|||
|
cld
|
|||
|
lderrlp:seg cs
|
|||
|
lodsb ; loop over all characters of
|
|||
|
or al,al ; string
|
|||
|
jnz lderrnx
|
|||
|
xor ah,ah
|
|||
|
int 0x16 ; wait for keypress
|
|||
|
jmpi 0x0000,0xFFFF ; reboot!
|
|||
|
lderrnx:mov ah,#0x0E ; print it
|
|||
|
mov bl,#0x07
|
|||
|
xor bh,bh
|
|||
|
int 0x10
|
|||
|
jmp lderrlp
|
|||
|
|
|||
|
loaderr:.ascii "The flash EPROM utility has to be loaded from a BOOT-Prom"
|
|||
|
.byte 0xa,0xd
|
|||
|
.ascii "that knows about the 'nbi' file format!"
|
|||
|
.byte 0xa,0xd
|
|||
|
.ascii "Reboot to proceed..."
|
|||
|
.byte 0
|
|||
|
|
|||
|
.org 510
|
|||
|
.byte 0x55,0xAA
|
|||
|
|
|||
|
!----------------------------------------------------------------------------
|
|||
|
|
|||
|
start: mov ax,cs
|
|||
|
mov ds,ax
|
|||
|
mov ax,romdata ; verify that there is an Prom image
|
|||
|
cmp ax,#0xAA55 ; attached to the utility
|
|||
|
jnz resmag
|
|||
|
mov al,romdata+2
|
|||
|
or al,al ; non-zero size is required
|
|||
|
jnz magicok
|
|||
|
resmag: mov si,#badmagic ; print error message
|
|||
|
reset: call prnstr
|
|||
|
xor ah,ah
|
|||
|
int 0x16 ; wait for keypress
|
|||
|
jmpi 0x0000,0xFFFF ; reboot!
|
|||
|
magicok:mov di,#clrline1
|
|||
|
mov si,#welcome ; print welcome message
|
|||
|
inpnew: call prnstr
|
|||
|
inprest:xor bx,bx
|
|||
|
mov cl,#0xC ; expect 4 nibbles input data
|
|||
|
inploop:xor ah,ah
|
|||
|
int 0x16
|
|||
|
cmp al,#0x8 ; <Backspace>
|
|||
|
jnz inpnobs
|
|||
|
or bx,bx ; there has to be at least one input ch
|
|||
|
jz inperr
|
|||
|
mov si,#delchar ; wipe out char from screen
|
|||
|
call prnstr
|
|||
|
add cl,#4 ; compute bitmask for removing input
|
|||
|
mov ch,cl
|
|||
|
mov cl,#0xC
|
|||
|
sub cl,ch
|
|||
|
mov ax,#0xFFFF
|
|||
|
shr ax,cl
|
|||
|
not ax
|
|||
|
and bx,ax
|
|||
|
mov cl,ch
|
|||
|
inploop1:jmp inploop
|
|||
|
inpnobs:cmp al,#0x0D ; <Return>
|
|||
|
jnz inpnocr
|
|||
|
or bx,bx ; zero input -> autoprobing
|
|||
|
jz inpdone
|
|||
|
cmp cl,#-4 ; otherwise there have to be 4 nibbles
|
|||
|
jz inpdone
|
|||
|
inperr: mov al,#7 ; ring the console bell
|
|||
|
jmp inpecho
|
|||
|
inpnocr:cmp al,#0x15 ; <CTRL-U>
|
|||
|
jnz inpnokl
|
|||
|
mov si,di
|
|||
|
call prnstr ; clear entire input and restart
|
|||
|
jmp inprest
|
|||
|
inpnokl:cmp cl,#-4 ; cannot input more than 4 nibbles
|
|||
|
jz inperr
|
|||
|
cmp al,#0x30 ; '0'
|
|||
|
jb inperr
|
|||
|
ja inpdig
|
|||
|
or bx,bx ; leading '0' is not allowed
|
|||
|
jz inperr
|
|||
|
inpdig: cmp al,#0x39 ; '9'
|
|||
|
ja inpnodg
|
|||
|
mov ch,al
|
|||
|
sub al,#0x30
|
|||
|
inpnum: xor ah,ah ; compute new input value
|
|||
|
shl ax,cl
|
|||
|
add ax,bx
|
|||
|
test ax,#0x1FF ; test for 8kB boundary
|
|||
|
jnz inperr
|
|||
|
cmp ax,#SEGHIGH ; input has to be below E800
|
|||
|
jae inperr
|
|||
|
cmp ax,#SEGLOW ; and above/equal C800
|
|||
|
jae inpok
|
|||
|
cmp cl,#0xC ; if there is just one nibble, yet,
|
|||
|
jnz inperr ; then the lower limit ix C000
|
|||
|
cmp ax,#0xC000
|
|||
|
jb inperr
|
|||
|
inpok: mov bx,ax ; adjust bitmask
|
|||
|
sub cl,#4
|
|||
|
mov al,ch
|
|||
|
inpecho:call prnchr ; output new character
|
|||
|
jmp inploop1
|
|||
|
inpnodg:and al,#0xDF ; lower case -> upper case
|
|||
|
cmp al,#0x41 ; 'A'
|
|||
|
jb inperr
|
|||
|
cmp al,#0x46 ; 'F'
|
|||
|
ja inperr
|
|||
|
mov ch,al
|
|||
|
sub al,#0x37
|
|||
|
jmp inpnum
|
|||
|
inpdone:or bx,bx ; zero -> autoprobing
|
|||
|
jnz probe
|
|||
|
mov si,#automsg
|
|||
|
call prnstr
|
|||
|
mov cx,#0x10
|
|||
|
mov bx,#SEGHIGH ; scan from E800 to C800
|
|||
|
autoprb:sub bx,#0x0200 ; stepping down in 8kB increments
|
|||
|
mov di,bx
|
|||
|
call readid
|
|||
|
cmp ax,#AMD_ID
|
|||
|
jz prbfnd
|
|||
|
loop autoprb
|
|||
|
mov si,#failmsg
|
|||
|
nofnd: mov di,#clrline2
|
|||
|
jmp near inpnew ; failure -> ask user for new input
|
|||
|
probe: mov di,bx
|
|||
|
test bx,#0x07FF ; EPROM might have to be aligned to
|
|||
|
jz noalign ; 32kB boundary
|
|||
|
call readid
|
|||
|
cmp ax,#AMD_ID ; check for AMDs id
|
|||
|
jz prbfnd
|
|||
|
mov si,#alignmsg
|
|||
|
call prnstr
|
|||
|
and bx,#0xF800 ; enforce alignment of hardware addr
|
|||
|
noalign:call readid ; check for AMDs id
|
|||
|
cmp ax,#AMD_ID
|
|||
|
jz prbfnd
|
|||
|
mov si,#nofndmsg ; could not find any EPROM at speci-
|
|||
|
call prnstr ; fied location --- even tried
|
|||
|
mov si,#basemsg ; aligning to 32kB boundary
|
|||
|
jmp nofnd ; failure -> ask user for new input
|
|||
|
prbfnd: mov si,#fndmsg
|
|||
|
call prnstr ; we found a flash EPROM
|
|||
|
mov ax,bx
|
|||
|
call prnwrd
|
|||
|
mov si,#ersmsg
|
|||
|
call prnstr
|
|||
|
call erase ; erase old contents
|
|||
|
jnc ersdone
|
|||
|
mov si,#failresmsg ; failure -> reboot machine
|
|||
|
jmp near reset
|
|||
|
ersdone:mov si,#prg1msg ; tell user that we are about
|
|||
|
call prnstr ; to program the new data into
|
|||
|
mov ax,di ; the specified range
|
|||
|
call prnwrd
|
|||
|
mov si,#prg2msg
|
|||
|
call prnstr
|
|||
|
xor dh,dh
|
|||
|
mov dl,romdata+2
|
|||
|
shl dx,#1
|
|||
|
mov ah,dh
|
|||
|
mov cl,#4
|
|||
|
shl ah,cl
|
|||
|
xor al,al
|
|||
|
add ax,di
|
|||
|
call prnwrd
|
|||
|
mov al,#0x3A ; ':'
|
|||
|
call prnchr
|
|||
|
mov ah,dl
|
|||
|
xor al,al
|
|||
|
dec ax
|
|||
|
call prnwrd
|
|||
|
mov al,#0x20
|
|||
|
call prnchr
|
|||
|
mov dh,romdata+2 ; number of 512 byte blocks
|
|||
|
push ds
|
|||
|
mov ax,ds
|
|||
|
add ax,#romdata>>4 ; adjust segment descriptor, so that
|
|||
|
mov ds,ax ; we can handle images which are
|
|||
|
prgloop:mov cx,#0x200 ; larger than 64kB
|
|||
|
xor si,si
|
|||
|
xor bp,bp
|
|||
|
call program ; program 512 data bytes
|
|||
|
jc prgerr ; check error condition
|
|||
|
mov ax,ds
|
|||
|
add ax,#0x20 ; increment segment descriptors
|
|||
|
mov ds,ax
|
|||
|
add di,#0x20
|
|||
|
dec dh ; decrement counter
|
|||
|
jnz prgloop
|
|||
|
pop ds
|
|||
|
mov si,#donemsg ; success -> reboot
|
|||
|
prgdone:call prnstr
|
|||
|
mov si,#resetmsg
|
|||
|
jmp near reset
|
|||
|
prgerr: pop ds ; failure -> reboot
|
|||
|
mov si,#failresmsg
|
|||
|
jmp prgdone
|
|||
|
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
; READID -- read EPROM id number, base address is passed in BX
|
|||
|
; ======
|
|||
|
;
|
|||
|
; changes: AX, DL, ES
|
|||
|
|
|||
|
readid: mov dl,#RESET_CMD ; reset chip
|
|||
|
call sendop
|
|||
|
mov dl,#READID_CMD
|
|||
|
call sendop ; send READID command
|
|||
|
mov es,bx
|
|||
|
seg es
|
|||
|
mov ax,0x00 ; read manufacturer ID
|
|||
|
mov dl,#RESET_CMD
|
|||
|
jmp sendop ; reset chip
|
|||
|
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
; ERASE -- erase entire EPROM, base address is passed in BX
|
|||
|
; =====
|
|||
|
;
|
|||
|
; changes: AL, CX, DL, ES, CF
|
|||
|
|
|||
|
erase: mov dl,#ERASE1_CMD
|
|||
|
call sendop ; send ERASE1 command
|
|||
|
mov dl,#ERASE2_CMD
|
|||
|
call sendop ; send ERASE2 command
|
|||
|
xor bp,bp
|
|||
|
mov al,#0xFF
|
|||
|
push di
|
|||
|
mov di,bx
|
|||
|
call waitop ; wait until operation finished
|
|||
|
pop di
|
|||
|
jnc erfail
|
|||
|
mov dl,#RESET_CMD
|
|||
|
call sendop ; reset chip
|
|||
|
stc
|
|||
|
erfail: ret
|
|||
|
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
; PROGRAM -- write data block at DS:SI of length CX into EPROM at DI:BP
|
|||
|
; =======
|
|||
|
;
|
|||
|
; changes: AX, CX, DL, BP, ES, CF
|
|||
|
|
|||
|
program:mov dl,#PROG_CMD
|
|||
|
call sendop ; send programming command
|
|||
|
lodsb ; get next byte from buffer
|
|||
|
mov es,di
|
|||
|
seg es
|
|||
|
mov byte ptr [bp],al ; write next byte into flash EPROM
|
|||
|
call waitop ; wait until programming operation is
|
|||
|
jc progdn ; completed
|
|||
|
inc bp
|
|||
|
loop program ; continue with next byte
|
|||
|
clc ; return without error
|
|||
|
progdn: ret
|
|||
|
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
; SENDOP -- send command in DL to EPROM, base address is passed in BX
|
|||
|
; ======
|
|||
|
;
|
|||
|
; changes: ES
|
|||
|
|
|||
|
sendop: mov es,bx
|
|||
|
seg es
|
|||
|
mov byte ptr 0x5555,#0xAA ; write magic data bytes into
|
|||
|
jcxz so1 ; magic locations. This unlocks
|
|||
|
so1: jcxz so2 ; the flash EPROM. N.B. that the
|
|||
|
so2: seg es ; magic locations are mirrored
|
|||
|
mov byte ptr 0x2AAA,#0x55 ; every 32kB; the hardware address
|
|||
|
jcxz so3 ; might have to be adjusted to a
|
|||
|
so3: jcxz so4 ; 32kB boundary
|
|||
|
so4: seg es
|
|||
|
mov byte ptr 0x5555,dl
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
; WAITOP -- wait for command to complete, address is passed in DI:BP
|
|||
|
; ======
|
|||
|
;
|
|||
|
; for details on the programming algorithm, c.f. http://www.amd.com
|
|||
|
;
|
|||
|
; changes: AX, DL, ES, CF
|
|||
|
|
|||
|
waitop: and al,#0x80 ; monitor bit 7
|
|||
|
mov es,di
|
|||
|
wait1: seg es ; read contents of EPROM cell that is
|
|||
|
mov ah,byte ptr [bp] ; being programmed
|
|||
|
mov dl,ah
|
|||
|
and ah,#0x80
|
|||
|
cmp al,ah ; bit 7 indicates sucess
|
|||
|
je waitok
|
|||
|
test dl,#0x20 ; bit 5 indicates timeout/error
|
|||
|
jz wait1 ; otherwise wait for cmd to complete
|
|||
|
seg es
|
|||
|
mov ah,byte ptr [bp] ; check error condition once again,
|
|||
|
and ah,#0x80 ; because bits 7 and 5 can change
|
|||
|
cmp al,ah ; simultaneously
|
|||
|
je waitok
|
|||
|
stc
|
|||
|
ret
|
|||
|
waitok: clc
|
|||
|
ret
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
; PRNSTR -- prints a string in DS:SI onto the console
|
|||
|
; ======
|
|||
|
;
|
|||
|
; changes: AL
|
|||
|
|
|||
|
prnstr: push si
|
|||
|
cld
|
|||
|
prns1: lodsb ; loop over all characters of
|
|||
|
or al,al ; string
|
|||
|
jz prns2
|
|||
|
call prnchr ; print character
|
|||
|
jmp prns1
|
|||
|
prns2: pop si
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
; PRNWRD, PRNBYT, PRNNIB, PRNCHR -- prints hexadezimal values, or ASCII chars
|
|||
|
; ====== ====== ====== ======
|
|||
|
;
|
|||
|
; changes: AX
|
|||
|
|
|||
|
prnwrd: push ax
|
|||
|
mov al,ah
|
|||
|
call prnbyt ; print the upper byte
|
|||
|
pop ax
|
|||
|
prnbyt: push ax
|
|||
|
shr al,1 ; prepare upper nibble
|
|||
|
shr al,1
|
|||
|
shr al,1
|
|||
|
shr al,1
|
|||
|
call prnnib ; print it
|
|||
|
pop ax
|
|||
|
prnnib: and al,#0x0F ; prepare lower nibble
|
|||
|
add al,#0x30
|
|||
|
cmp al,#0x39 ; convert it into hex
|
|||
|
jle prnchr
|
|||
|
add al,#7
|
|||
|
prnchr: push bx
|
|||
|
mov ah,#0x0E ; print it
|
|||
|
mov bl,#0x07
|
|||
|
xor bh,bh
|
|||
|
int 0x10
|
|||
|
pop bx
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
magic: .byte 0xE4,0xE4
|
|||
|
|
|||
|
badmagic:.byte 0xa,0xd
|
|||
|
.ascii "There does not appear to be a ROM image attached to the"
|
|||
|
.ascii "flash EPROM utility;"
|
|||
|
.byte 0xa,0xd
|
|||
|
resetmsg:.ascii "Reboot to proceed..."
|
|||
|
.byte 0
|
|||
|
|
|||
|
welcome:.byte 0xa,0xd
|
|||
|
.ascii "Flash EPROM programming utility V1.0"
|
|||
|
.byte 0xa,0xd
|
|||
|
.ascii "Copyright (c) 1997 by M. Gutschke <gutschk@uni-muenster.de>"
|
|||
|
.byte 0xa,0xd
|
|||
|
.ascii "==========================================================="
|
|||
|
.byte 0xa,0xd
|
|||
|
prompt: .byte 0xa,0xd
|
|||
|
.ascii "Enter base address for AMD29F010 flash EPROM on FlashCard or"
|
|||
|
.byte 0xa,0xd
|
|||
|
.ascii "press <RETURN> to start autoprobing; the base address has"
|
|||
|
.byte 0xa
|
|||
|
clrline1:.byte 0xd
|
|||
|
.ascii "to be in the range C800..E600: "
|
|||
|
.ascii " "
|
|||
|
.byte 0x8,0x8,0x8,0x8
|
|||
|
.byte 0
|
|||
|
|
|||
|
delchar:.byte 0x8,0x20,0x8
|
|||
|
.byte 0
|
|||
|
|
|||
|
automsg:.ascii "autoprobing... "
|
|||
|
.byte 0
|
|||
|
|
|||
|
failmsg:.ascii "failed!"
|
|||
|
basemsg:.byte 0xa
|
|||
|
clrline2:.byte 0xd
|
|||
|
.ascii "Enter base address: "
|
|||
|
.ascii " "
|
|||
|
.byte 0x8,0x8,0x8,0x8
|
|||
|
.byte 0
|
|||
|
|
|||
|
fndmsg: .byte 0xa,0xd
|
|||
|
.ascii "Found flash EPROM at: "
|
|||
|
.byte 0
|
|||
|
|
|||
|
alignmsg:.byte 0xa,0xd
|
|||
|
.ascii "FlashCard requires the hardware address to be aligned to a"
|
|||
|
.byte 0xa,0xd
|
|||
|
.ascii "32kB boundary; automatically adjusting..."
|
|||
|
.byte 0
|
|||
|
|
|||
|
nofndmsg:.byte 0xa,0xd
|
|||
|
.ascii "No AMD29F010 flash EPROM found"
|
|||
|
.byte 0
|
|||
|
|
|||
|
ersmsg: .byte 0xa,0xd
|
|||
|
.ascii "Erasing old contents... "
|
|||
|
.byte 0
|
|||
|
|
|||
|
prg1msg:.ascii "done"
|
|||
|
.byte 0xa,0xd
|
|||
|
.ascii "Programming from "
|
|||
|
.byte 0
|
|||
|
|
|||
|
prg2msg:.ascii ":0000 to "
|
|||
|
.byte 0
|
|||
|
|
|||
|
donemsg:.ascii "done!"
|
|||
|
.byte 0xa,0xd
|
|||
|
.byte 0
|
|||
|
|
|||
|
failresmsg:
|
|||
|
.ascii "failed!"
|
|||
|
.byte 0xa,0xd
|
|||
|
.byte 0
|
|||
|
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
.align 16
|
|||
|
.org *-1
|
|||
|
.byte 0x00
|
|||
|
romdata:
|