mirror of
https://github.com/ipxe/ipxe
synced 2026-02-14 02:31:26 +03:00
Initial revision
This commit is contained in:
497
contrib/flashimg/flashimg.asm
Normal file
497
contrib/flashimg/flashimg.asm
Normal file
@@ -0,0 +1,497 @@
|
||||
; 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:
|
||||
Reference in New Issue
Block a user