david/ipxe
david
/
ipxe
Archived
1
0
Fork 0
This repository has been archived on 2020-12-06. You can view files and clone it, but cannot push or open issues or pull requests.
ipxe/contrib/flashimg/flashimg.asm

498 lines
12 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; 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: