[sundance] Add reset completion check
[gpxe.git] / contrib / flashimg / flashimg.asm
blob7a37ed5409b0e3cab927ebc62cf0f6b7257f6a1c
1 ; Copyright (C) 1997 Markus Gutschke <gutschk@uni-muenster.de>
3 ; This program is free software; you can redistribute it and/or modify
4 ; it under the terms of the GNU General Public License as published by
5 ; the Free Software Foundation; either version 2 of the License, or
6 ; any later version.
8 ; This program is distributed in the hope that it will be useful,
9 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 ; GNU General Public License for more details.
13 ; You should have received a copy of the GNU General Public License
14 ; along with this program; if not, write to the Free Software
15 ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 ; Prepend this image file to an arbitrary ROM image. The resulting binary
18 ; can be loaded from any BOOT-Prom that supports the "nbi" file format.
19 ; When started, the image will reprogram the flash EPROM on the FlashCard
20 ; ISA card. The flash EPROM has to be an AMD 29F010, and the programming
21 ; algorithm is the same as that suggested by AMD in the appropriate data
22 ; sheets.
25 #define SEGLOW 0xC800 /* lower range for EPROM segment */
26 #define SEGHIGH 0xE800 /* upper range for EPROM segment */
27 #define AMD_ID 0x2001 /* flash EPROM ID, only support AMD */
28 #define ERASE1_CMD 0x80 /* first cmd for erasing full chip */
29 #define ERASE2_CMD 0x10 /* second cmd for erasing full chip */
30 #define READID_CMD 0x90 /* cmd to read chip ID */
31 #define PROG_CMD 0xA0 /* cmd to program a byte */
32 #define RESET_CMD 0xF0 /* cmd to reset chip state machine */
34 ;----------------------------------------------------------------------------\f
37 .text
38 .org 0
40 ; .globl _main
41 _main: mov ax,#0x0FE0
42 mov ds,ax
43 mov ax,magic ; verify that we have been loaded by
44 cmp ax,#0xE4E4 ; boot prom
45 jnz lderr
46 jmpi 0x200,0x0FE0 ; adjust code segment
47 lderr: mov si,#loaderr
48 cld
49 lderrlp:seg cs
50 lodsb ; loop over all characters of
51 or al,al ; string
52 jnz lderrnx
53 xor ah,ah
54 int 0x16 ; wait for keypress
55 jmpi 0x0000,0xFFFF ; reboot!
56 lderrnx:mov ah,#0x0E ; print it
57 mov bl,#0x07
58 xor bh,bh
59 int 0x10
60 jmp lderrlp
62 loaderr:.ascii "The flash EPROM utility has to be loaded from a BOOT-Prom"
63 .byte 0xa,0xd
64 .ascii "that knows about the 'nbi' file format!"
65 .byte 0xa,0xd
66 .ascii "Reboot to proceed..."
67 .byte 0
69 .org 510
70 .byte 0x55,0xAA
72 !----------------------------------------------------------------------------\f
74 start: mov ax,cs
75 mov ds,ax
76 mov ax,romdata ; verify that there is an Prom image
77 cmp ax,#0xAA55 ; attached to the utility
78 jnz resmag
79 mov al,romdata+2
80 or al,al ; non-zero size is required
81 jnz magicok
82 resmag: mov si,#badmagic ; print error message
83 reset: call prnstr
84 xor ah,ah
85 int 0x16 ; wait for keypress
86 jmpi 0x0000,0xFFFF ; reboot!
87 magicok:mov di,#clrline1
88 mov si,#welcome ; print welcome message
89 inpnew: call prnstr
90 inprest:xor bx,bx
91 mov cl,#0xC ; expect 4 nibbles input data
92 inploop:xor ah,ah
93 int 0x16
94 cmp al,#0x8 ; <Backspace>
95 jnz inpnobs
96 or bx,bx ; there has to be at least one input ch
97 jz inperr
98 mov si,#delchar ; wipe out char from screen
99 call prnstr
100 add cl,#4 ; compute bitmask for removing input
101 mov ch,cl
102 mov cl,#0xC
103 sub cl,ch
104 mov ax,#0xFFFF
105 shr ax,cl
106 not ax
107 and bx,ax
108 mov cl,ch
109 inploop1:jmp inploop
110 inpnobs:cmp al,#0x0D ; <Return>
111 jnz inpnocr
112 or bx,bx ; zero input -> autoprobing
113 jz inpdone
114 cmp cl,#-4 ; otherwise there have to be 4 nibbles
115 jz inpdone
116 inperr: mov al,#7 ; ring the console bell
117 jmp inpecho
118 inpnocr:cmp al,#0x15 ; <CTRL-U>
119 jnz inpnokl
120 mov si,di
121 call prnstr ; clear entire input and restart
122 jmp inprest
123 inpnokl:cmp cl,#-4 ; cannot input more than 4 nibbles
124 jz inperr
125 cmp al,#0x30 ; '0'
126 jb inperr
127 ja inpdig
128 or bx,bx ; leading '0' is not allowed
129 jz inperr
130 inpdig: cmp al,#0x39 ; '9'
131 ja inpnodg
132 mov ch,al
133 sub al,#0x30
134 inpnum: xor ah,ah ; compute new input value
135 shl ax,cl
136 add ax,bx
137 test ax,#0x1FF ; test for 8kB boundary
138 jnz inperr
139 cmp ax,#SEGHIGH ; input has to be below E800
140 jae inperr
141 cmp ax,#SEGLOW ; and above/equal C800
142 jae inpok
143 cmp cl,#0xC ; if there is just one nibble, yet,
144 jnz inperr ; then the lower limit ix C000
145 cmp ax,#0xC000
146 jb inperr
147 inpok: mov bx,ax ; adjust bitmask
148 sub cl,#4
149 mov al,ch
150 inpecho:call prnchr ; output new character
151 jmp inploop1
152 inpnodg:and al,#0xDF ; lower case -> upper case
153 cmp al,#0x41 ; 'A'
154 jb inperr
155 cmp al,#0x46 ; 'F'
156 ja inperr
157 mov ch,al
158 sub al,#0x37
159 jmp inpnum
160 inpdone:or bx,bx ; zero -> autoprobing
161 jnz probe
162 mov si,#automsg
163 call prnstr
164 mov cx,#0x10
165 mov bx,#SEGHIGH ; scan from E800 to C800
166 autoprb:sub bx,#0x0200 ; stepping down in 8kB increments
167 mov di,bx
168 call readid
169 cmp ax,#AMD_ID
170 jz prbfnd
171 loop autoprb
172 mov si,#failmsg
173 nofnd: mov di,#clrline2
174 jmp near inpnew ; failure -> ask user for new input
175 probe: mov di,bx
176 test bx,#0x07FF ; EPROM might have to be aligned to
177 jz noalign ; 32kB boundary
178 call readid
179 cmp ax,#AMD_ID ; check for AMDs id
180 jz prbfnd
181 mov si,#alignmsg
182 call prnstr
183 and bx,#0xF800 ; enforce alignment of hardware addr
184 noalign:call readid ; check for AMDs id
185 cmp ax,#AMD_ID
186 jz prbfnd
187 mov si,#nofndmsg ; could not find any EPROM at speci-
188 call prnstr ; fied location --- even tried
189 mov si,#basemsg ; aligning to 32kB boundary
190 jmp nofnd ; failure -> ask user for new input
191 prbfnd: mov si,#fndmsg
192 call prnstr ; we found a flash EPROM
193 mov ax,bx
194 call prnwrd
195 mov si,#ersmsg
196 call prnstr
197 call erase ; erase old contents
198 jnc ersdone
199 mov si,#failresmsg ; failure -> reboot machine
200 jmp near reset
201 ersdone:mov si,#prg1msg ; tell user that we are about
202 call prnstr ; to program the new data into
203 mov ax,di ; the specified range
204 call prnwrd
205 mov si,#prg2msg
206 call prnstr
207 xor dh,dh
208 mov dl,romdata+2
209 shl dx,#1
210 mov ah,dh
211 mov cl,#4
212 shl ah,cl
213 xor al,al
214 add ax,di
215 call prnwrd
216 mov al,#0x3A ; ':'
217 call prnchr
218 mov ah,dl
219 xor al,al
220 dec ax
221 call prnwrd
222 mov al,#0x20
223 call prnchr
224 mov dh,romdata+2 ; number of 512 byte blocks
225 push ds
226 mov ax,ds
227 add ax,#romdata>>4 ; adjust segment descriptor, so that
228 mov ds,ax ; we can handle images which are
229 prgloop:mov cx,#0x200 ; larger than 64kB
230 xor si,si
231 xor bp,bp
232 call program ; program 512 data bytes
233 jc prgerr ; check error condition
234 mov ax,ds
235 add ax,#0x20 ; increment segment descriptors
236 mov ds,ax
237 add di,#0x20
238 dec dh ; decrement counter
239 jnz prgloop
240 pop ds
241 mov si,#donemsg ; success -> reboot
242 prgdone:call prnstr
243 mov si,#resetmsg
244 jmp near reset
245 prgerr: pop ds ; failure -> reboot
246 mov si,#failresmsg
247 jmp prgdone
250 ;----------------------------------------------------------------------------\f
252 ; READID -- read EPROM id number, base address is passed in BX
253 ; ======
255 ; changes: AX, DL, ES
257 readid: mov dl,#RESET_CMD ; reset chip
258 call sendop
259 mov dl,#READID_CMD
260 call sendop ; send READID command
261 mov es,bx
262 seg es
263 mov ax,0x00 ; read manufacturer ID
264 mov dl,#RESET_CMD
265 jmp sendop ; reset chip
268 ;----------------------------------------------------------------------------\f
270 ; ERASE -- erase entire EPROM, base address is passed in BX
271 ; =====
273 ; changes: AL, CX, DL, ES, CF
275 erase: mov dl,#ERASE1_CMD
276 call sendop ; send ERASE1 command
277 mov dl,#ERASE2_CMD
278 call sendop ; send ERASE2 command
279 xor bp,bp
280 mov al,#0xFF
281 push di
282 mov di,bx
283 call waitop ; wait until operation finished
284 pop di
285 jnc erfail
286 mov dl,#RESET_CMD
287 call sendop ; reset chip
289 erfail: ret
292 ;----------------------------------------------------------------------------\f
294 ; PROGRAM -- write data block at DS:SI of length CX into EPROM at DI:BP
295 ; =======
297 ; changes: AX, CX, DL, BP, ES, CF
299 program:mov dl,#PROG_CMD
300 call sendop ; send programming command
301 lodsb ; get next byte from buffer
302 mov es,di
303 seg es
304 mov byte ptr [bp],al ; write next byte into flash EPROM
305 call waitop ; wait until programming operation is
306 jc progdn ; completed
307 inc bp
308 loop program ; continue with next byte
309 clc ; return without error
310 progdn: ret
313 ;----------------------------------------------------------------------------\f
315 ; SENDOP -- send command in DL to EPROM, base address is passed in BX
316 ; ======
318 ; changes: ES
320 sendop: mov es,bx
321 seg es
322 mov byte ptr 0x5555,#0xAA ; write magic data bytes into
323 jcxz so1 ; magic locations. This unlocks
324 so1: jcxz so2 ; the flash EPROM. N.B. that the
325 so2: seg es ; magic locations are mirrored
326 mov byte ptr 0x2AAA,#0x55 ; every 32kB; the hardware address
327 jcxz so3 ; might have to be adjusted to a
328 so3: jcxz so4 ; 32kB boundary
329 so4: seg es
330 mov byte ptr 0x5555,dl
334 ;----------------------------------------------------------------------------\f
336 ; WAITOP -- wait for command to complete, address is passed in DI:BP
337 ; ======
339 ; for details on the programming algorithm, c.f. http://www.amd.com
341 ; changes: AX, DL, ES, CF
343 waitop: and al,#0x80 ; monitor bit 7
344 mov es,di
345 wait1: seg es ; read contents of EPROM cell that is
346 mov ah,byte ptr [bp] ; being programmed
347 mov dl,ah
348 and ah,#0x80
349 cmp al,ah ; bit 7 indicates sucess
350 je waitok
351 test dl,#0x20 ; bit 5 indicates timeout/error
352 jz wait1 ; otherwise wait for cmd to complete
353 seg es
354 mov ah,byte ptr [bp] ; check error condition once again,
355 and ah,#0x80 ; because bits 7 and 5 can change
356 cmp al,ah ; simultaneously
357 je waitok
360 waitok: clc
363 ;----------------------------------------------------------------------------\f
365 ; PRNSTR -- prints a string in DS:SI onto the console
366 ; ======
368 ; changes: AL
370 prnstr: push si
372 prns1: lodsb ; loop over all characters of
373 or al,al ; string
374 jz prns2
375 call prnchr ; print character
376 jmp prns1
377 prns2: pop si
381 ;----------------------------------------------------------------------------\f
383 ; PRNWRD, PRNBYT, PRNNIB, PRNCHR -- prints hexadezimal values, or ASCII chars
384 ; ====== ====== ====== ======
386 ; changes: AX
388 prnwrd: push ax
389 mov al,ah
390 call prnbyt ; print the upper byte
391 pop ax
392 prnbyt: push ax
393 shr al,1 ; prepare upper nibble
394 shr al,1
395 shr al,1
396 shr al,1
397 call prnnib ; print it
398 pop ax
399 prnnib: and al,#0x0F ; prepare lower nibble
400 add al,#0x30
401 cmp al,#0x39 ; convert it into hex
402 jle prnchr
403 add al,#7
404 prnchr: push bx
405 mov ah,#0x0E ; print it
406 mov bl,#0x07
407 xor bh,bh
408 int 0x10
409 pop bx
413 ;----------------------------------------------------------------------------\f
415 magic: .byte 0xE4,0xE4
417 badmagic:.byte 0xa,0xd
418 .ascii "There does not appear to be a ROM image attached to the"
419 .ascii "flash EPROM utility;"
420 .byte 0xa,0xd
421 resetmsg:.ascii "Reboot to proceed..."
422 .byte 0
424 welcome:.byte 0xa,0xd
425 .ascii "Flash EPROM programming utility V1.0"
426 .byte 0xa,0xd
427 .ascii "Copyright (c) 1997 by M. Gutschke <gutschk@uni-muenster.de>"
428 .byte 0xa,0xd
429 .ascii "==========================================================="
430 .byte 0xa,0xd
431 prompt: .byte 0xa,0xd
432 .ascii "Enter base address for AMD29F010 flash EPROM on FlashCard or"
433 .byte 0xa,0xd
434 .ascii "press <RETURN> to start autoprobing; the base address has"
435 .byte 0xa
436 clrline1:.byte 0xd
437 .ascii "to be in the range C800..E600: "
438 .ascii " "
439 .byte 0x8,0x8,0x8,0x8
440 .byte 0
442 delchar:.byte 0x8,0x20,0x8
443 .byte 0
445 automsg:.ascii "autoprobing... "
446 .byte 0
448 failmsg:.ascii "failed!"
449 basemsg:.byte 0xa
450 clrline2:.byte 0xd
451 .ascii "Enter base address: "
452 .ascii " "
453 .byte 0x8,0x8,0x8,0x8
454 .byte 0
456 fndmsg: .byte 0xa,0xd
457 .ascii "Found flash EPROM at: "
458 .byte 0
460 alignmsg:.byte 0xa,0xd
461 .ascii "FlashCard requires the hardware address to be aligned to a"
462 .byte 0xa,0xd
463 .ascii "32kB boundary; automatically adjusting..."
464 .byte 0
466 nofndmsg:.byte 0xa,0xd
467 .ascii "No AMD29F010 flash EPROM found"
468 .byte 0
470 ersmsg: .byte 0xa,0xd
471 .ascii "Erasing old contents... "
472 .byte 0
474 prg1msg:.ascii "done"
475 .byte 0xa,0xd
476 .ascii "Programming from "
477 .byte 0
479 prg2msg:.ascii ":0000 to "
480 .byte 0
482 donemsg:.ascii "done!"
483 .byte 0xa,0xd
484 .byte 0
486 failresmsg:
487 .ascii "failed!"
488 .byte 0xa,0xd
489 .byte 0
492 ;----------------------------------------------------------------------------\f
494 .align 16
495 .org *-1
496 .byte 0x00
497 romdata: