; ; WRAP BIOS update - for Xmodem upload ; ; pd 030807, 030812 ; pd 050625 add 39VF040 ; rombase equ 0fffe0000 CONSOLE equ 03f8 port61 equ 061 iowait equ 0eb org 0 db "TB" ;signature entry: jmp start ; ; output AL to serial port ; xm_out: push dx push ax mov dx,CONSOLE+5 xm_out1: in al,dx ;wait for transmit ready out iowait,ax test al,40h jz xm_out1 mov dl,low(CONSOLE) pop ax out dx,al pop dx ret ; ; display message [cs:si] ; v_msg1: call xm_out v_msg: cs: lodsb cmp al,0 jnz v_msg1 ret ; ; variables ; even bufpt: dd 0 ;buffer pointer devid: dw 0 ;device ID file: dw 0 ;file handle bufseg: dw 0 ;buffer segment curseg: dw 0 ;current segment count: db 4 ;number of 32KB blocks to be read rom64: db 0 ;1 = 64KB flash msg_strt: db "WRAP flash update",13,10,0 msg_len: db "Invalid image length",13,10,0 msg_open: db "Flash ID",0 msg_fail: db " - FAIL !",13,10,0 msg_zap: db 13,10,"Erase",0 msg_set: db " Program",0 msg_cmp: db " Verify",0 msg_ok: db 13,10,"Flash updated successfully.",13,10,0 ; ; main code ; start: cld push cs pop ds mov si,offset msg_strt call v_msg mov si,offset msg_len mov ax,es ;verify image length cmp ax,03000 jnz barf ;:bad cmp di,buf jb barf ; set segment values xor eax,eax ;set buffer segment mov ax,cs shl eax,4 ;-> physical add eax,offset buf mov [bufpt],eax shr eax,4 ;-> segment mov [bufseg],ax mov [curseg],ax xor eax,eax ;set GDT physical address mov ax,cs shl eax,4 add eax,offset gdt mov dword [gdtadr],eax mov si,offset msg_open ;look for flash call v_msg call rom_open ;read device ID jb barf mov si,offset msg_zap ;erase flash call v_msg call rom_zap jb barf mov si,offset msg_set ;program flash call v_msg call rom_set jb barf mov si,offset msg_cmp ;verify flash call v_msg call rom_cmp jb barf mov si,offset msg_ok ;success message barf: call v_msg call rom_exit ;write-protect flash xor ax,ax ;restore DS,ES mov ds,ax mov es,ax retf ;return to setup ; ; global descriptor table (GDT) for unreal mode ; db (($+15) and 0fff0h)-$ dup 0ffh ;even 16 gdt: dw gdtend-gdt-1 ;GDT limit gdtadr: dw gdt,000fh ;linear address of GDT dw 0 dw 0ffffh,0,9300h,008fh ;4G data segment, accessed gdtend: ; ; Enter unreal (4GB segment) mode -> change DS,ES selector ; ; based on code in DDJ 7/90 ; getunreal: cli ;disable interrupts cs: lgdt [gdt] ;load GDT (in data module, writeable) mov eax,cr0 or al,1 ;enable protected mode mov cr0,eax jmp short getunrl2 ;flush queue getunrl2: mov bx,8 ;selector mov ds,bx mov es,bx and al,0feh ;exit protected mode mov cr0,eax ret ; ; get back to normal segments ; getreal: push cs pop ds sti ret ; ; open flash access ; rom_open: mov eax,80009050h ;9052 enable flash writes sc172 mov dx,0cf8 out dx,eax xchg eax,ebx mov dl,0fe in al,dx or al,2 ;enable flash write xchg eax,ebx mov dl,0f8 out dx,eax mov dl,0fe xchg eax,ebx out dx,al ; read device ID call getunreal ;enter unreal mode mov ebx,rombase mov byte [ebx+05555],0aa ;software ID mov byte [ebx+02aaa],055 mov byte [ebx+05555],090 out iowait,al ;short delay mov ax,[ebx] ;read the device ID mov byte [ebx],0f0 ;exit ID mode call getreal mov [devid],ax ; check device ID cmp al,0bf ;SST ? jnz rom_open9 ;no: fail cmp ah,0d6 ;39VF020 jz rom_open8 cmp ah,0d7 ;39VF040 jz rom_open8 cmp ah,0b5 ;39SF010 jz rom_open8 cmp ah,0d5 ;39VF010 jz rom_open8 inc byte [rom64] ;set flag for 64KB flash cmp ah,0b4 ;39SF512 jz rom_open8 cmp ah,0d4 ;39VF512 jnz rom_open9 rom_open8: clc ret rom_open9: stc mov si,offset msg_fail ret ; ; close flash access ; rom_exit: mov eax,80009050h ;9052 disable flash writes sc172 mov dx,0cf8 out dx,eax xchg eax,ebx mov dl,0fe in al,dx and al,not 2 ;enable flash write xchg eax,ebx mov dl,0f8 out dx,eax mov dl,0fe xchg eax,ebx out dx,al ret ; ; chip erase flash ; rom_zap: call getunreal ;enter unreal mode mov ebx,rombase mov byte [ebx+05555],0aa ;erase setup mov byte [ebx+02aaa],055 mov byte [ebx+05555],080 mov byte [ebx+05555],0aa ;erase command mov byte [ebx+02aaa],055 mov byte [ebx+05555],010 mov bx,100 ;wait for 100 ms call cs_waitbx mov eax,0ffffffff ;check for erase mov ecx,08000 ;128KB mov edi,rombase a4 repz scasd jnz rom_open9 ;:failure call getreal clc ret ; ; program flash [bufpt] -> [rombase] ; rom_set: mov esi,[bufpt] mov edi,rombase mov ecx,020000 ;128KB cmp byte [rom64],1 ;64KB flash ? jnz rom_set2 shr ecx,1 ;yes add esi,ecx add edi,ecx rom_set2: call getunreal mov ebx,edi ;^base rom_set3: mov al,[esi] ;data byte cmp al,0ff jz rom_set5 ;blank -> skip mov byte [ebx+05555],0aa ;byte program command mov byte [ebx+02aaa],055 mov byte [ebx+05555],0a0 mov [edi],al mov dx,1000 ;time-out rom_set4: cmp [edi],al ;correct data ? jz rom_set5 ;:yes dec dx jnz rom_set4 jmp rom_open9 ;program failure, bail rom_set5: inc esi inc edi dec ecx jnz rom_set3 ;:another call getreal clc ret ; ; compare flash [bufpt] -> [rombase] ; rom_cmp: mov esi,[bufpt] mov edi,rombase mov ecx,020000 ;128KB cmp byte [rom64],1 ;64KB flash ? jnz rom_cmp2 shr ecx,1 ;yes add esi,ecx add edi,ecx rom_cmp2: call getunreal shr ecx,2 mov eax,[esi] cmp [edi],eax jnz rom_open9 ;:failure lea esi,[esi+4] lea edi,[edi+4] dec ecx jnz rom_cmp2 call getreal clc ret ; ; Wait BX milliseconds - depends on refresh rate !!! ; cs_waitbx: inc bx jmp short cs_wbx8 cs_wbx1: mov cx,62 ;62 refresh cycles per millisecond cs_wbx2: in al,port61 and al,10h mov ah,al cs_wbx3: in al,port61 ;wait for refresh bit to change state and al,10h cmp al,ah jz cs_wbx3 loop cs_wbx2 ;:another iteration cs_wbx8: dec bx ;another millisecond ? jnz cs_wbx1 cs_wbx9: ret ; ; flash image is appended here ; db (($+15) and 0fff0h)-$ dup 0ffh ;even 16 buf: ;flash image follows here