[eepro100] Convert to native gPXE API
[people/andreif/gpxe.git] / contrib / flashimg / flashimg.asm
1 ; Copyright (C) 1997 Markus Gutschke <gutschk@uni-muenster.de>
2 ;
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.
7 ;
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.
12 ;
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.
16
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.
23
24
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   */
33
34 ;----------------------------------------------------------------------------\f
35
36
37         .text
38         .org    0
39
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
61
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
68
69         .org    510
70         .byte   0x55,0xAA
71
72 !----------------------------------------------------------------------------\f
73
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
248
249
250 ;----------------------------------------------------------------------------\f
251
252 ; READID -- read EPROM id number, base address is passed in BX
253 ; ======
254 ;
255 ; changes: AX, DL, ES
256
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
266
267
268 ;----------------------------------------------------------------------------\f
269
270 ; ERASE -- erase entire EPROM, base address is passed in BX
271 ; =====
272 ;
273 ; changes: AL, CX, DL, ES, CF
274
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
288         stc
289 erfail: ret
290
291
292 ;----------------------------------------------------------------------------\f
293
294 ; PROGRAM -- write data block at DS:SI of length CX into EPROM at DI:BP
295 ; =======
296 ;
297 ; changes: AX, CX, DL, BP, ES, CF
298
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
311
312
313 ;----------------------------------------------------------------------------\f
314
315 ; SENDOP -- send command in DL to EPROM, base address is passed in BX
316 ; ======
317 ;
318 ; changes: ES
319
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
331         ret
332
333
334 ;----------------------------------------------------------------------------\f
335
336 ; WAITOP -- wait for command to complete, address is passed in DI:BP
337 ; ======
338 ;
339 ; for details on the programming algorithm, c.f. http://www.amd.com
340 ;
341 ; changes: AX, DL, ES, CF
342
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
358         stc
359         ret
360 waitok: clc
361         ret
362
363 ;----------------------------------------------------------------------------\f
364
365 ; PRNSTR -- prints a string in DS:SI onto the console
366 ; ======
367 ;
368 ; changes: AL
369
370 prnstr: push    si
371         cld
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
378         ret
379
380
381 ;----------------------------------------------------------------------------\f
382
383 ; PRNWRD, PRNBYT, PRNNIB, PRNCHR -- prints hexadezimal values, or ASCII chars
384 ; ======  ======  ======  ======
385 ;
386 ; changes: AX
387
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
410         ret
411
412
413 ;----------------------------------------------------------------------------\f
414
415 magic:  .byte   0xE4,0xE4
416
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
423         
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
441
442 delchar:.byte   0x8,0x20,0x8
443         .byte   0
444
445 automsg:.ascii  "autoprobing... "
446         .byte   0
447
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
455
456 fndmsg: .byte   0xa,0xd
457         .ascii  "Found flash EPROM at: "
458         .byte   0
459
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
465         
466 nofndmsg:.byte  0xa,0xd
467         .ascii  "No AMD29F010 flash EPROM found"
468         .byte   0
469
470 ersmsg: .byte   0xa,0xd
471         .ascii  "Erasing old contents... "
472         .byte   0
473
474 prg1msg:.ascii  "done"
475         .byte   0xa,0xd
476         .ascii  "Programming from "
477         .byte   0
478         
479 prg2msg:.ascii  ":0000 to "
480         .byte   0
481
482 donemsg:.ascii  "done!"
483         .byte   0xa,0xd
484         .byte   0
485        
486 failresmsg:
487         .ascii  "failed!"
488         .byte   0xa,0xd
489         .byte   0
490
491
492 ;----------------------------------------------------------------------------\f
493
494         .align  16
495         .org    *-1
496         .byte   0x00
497 romdata: