Package: syslinux
Version: 3.11-3
Severity: wishlist
Tags: patch

Hi,

SuSE have developed a set of bootloader extensions called gfxboot, which
they use on their installation CDs. This consists of an interpreter for
a somewhat PostScript-like language that's capable of drawing on the
screen, acting on keypresses, and so on, and patches to each of various
bootloaders to call hooks in gfxboot at various points.

It used to be that the gfxboot patch to syslinux was extremely invasive
and complex. It's still complex, but I think the current version of it
is much, much better-designed and not painfully invasive in the way it
used to be. We've been using it in Ubuntu install CDs for the last month
or two to provide better usability and eye-candy on the CD bootloader
screen, and I think it'd be really nice if we could do the same thing in
Debian.

I'd be happy to provide a package of gfxboot itself and a skeleton
gfxboot theme more or less suitable for installation CDs if you'd be
willing to apply the relevant patches to syslinux.

I've attached three patches. The first (gfxboot.diff) is the main
gfxboot patch straight from SuSE. The second (localboot-gfxdone.diff)
fixes a failure of the first patch to clear the screen when booting with
the LOCALBOOT command. The third (gfxboot-cpio-swab.diff) makes gfxboot
check for byte-swapped cpio archives, so that it's easier to do gfxboot
theme development on powerpc (which happens to be my main development
box).

Thanks,

-- 
Colin Watson                                       [EMAIL PROTECTED]
--- conio.inc
+++ conio.inc
@@ -48,6 +48,13 @@
 ;               set by routine searchdir
 ;
 get_msg_file:
+%ifdef WITH_GFX
+               ; don't load if graphics code is active
+               cmp byte [gfx_ok],0
+               jz .nogfx
+               ret
+.nogfx:
+%endif
                push es
                shl edx,16                      ; EDX <- DX:AX (length of file)
                mov dx,ax
--- gfxboot.inc
+++ gfxboot.inc
@@ -0,0 +1,1255 @@
+               section .text
+
+load_gfx_msg   db 'Loading...', 0
+no_msg         db 0
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; do a reboot
+;
+do_reboot:
+               call gfx_done
+               mov word [472h],1234h
+               push word 0ffffh
+               push word 0
+               retf
+               int 19h
+               jmp $
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; wait for 'enter' key pressed
+;
+wait_for_key:
+               pusha
+wait_for_key_10:
+               mov ah,0
+               int 16h
+               cmp al,13
+               jnz wait_for_key_10
+               popa
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; read gfx data
+get_gfx_file:
+               push si
+               mov si,load_gfx_msg
+               call cwritestr
+               pop si
+               mov word [gfx_mem_start_seg],first_free_seg
+               push ds
+               push 40h
+               pop ds
+               mov bx,[13h]                    ; mem size in kb
+               pop ds
+               shl bx,6
+               mov word [gfx_mem_end_seg],bx
+
+               call gfx_init                   ; Load and display file
+               cmp byte [gfx_ok],0
+               jz .done
+               mov si,crlf_msg
+               call cwritestr
+.done:
+               ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; read from disk, ask for disk change, if necessary
+
+;       EAX - Linear sector number
+;       ES:BX   - Target buffer
+;       BP      - Sector count
+;
+;       (es:)bx gets updated
+
+%if IS_SYSLINUX
+
+; %define DEBUG_XXX
+
+getlinsec3:
+%ifdef DEBUG_XXX
+               mov si,txt0
+               call dump_params
+               call crlf
+%endif
+               mov cx,[DiskSize]
+               or cx,cx
+               jz getlinsec3_70                ; unlimited
+
+               xor dx,dx
+               div cx
+               xchg ax,dx
+               movzx eax,ax
+
+               mov si,ax
+               add si,bp
+               sub si,cx
+               jbe getlinsec3_40
+               ; split
+
+               sub bp,si
+               movzx ebp,bp
+               push ebp
+               push eax
+               push si
+               push dx
+               call getlinsec3_40
+               pop dx
+               pop bp
+               pop eax
+               pop esi
+               add eax,esi
+               movzx ebp,bp
+               inc dl
+
+getlinsec3_40:
+               push es
+               pushad
+               call disk_change
+               popad
+               pop es
+               jc kaboom
+getlinsec3_70:
+%ifdef DEBUG_XXX
+               mov si,txt1
+               call dump_params
+               mov si,txt3
+               call cwritestr
+               push ax
+               mov al,[CurrentDisk]
+               call writehex2
+               pop ax
+               call crlf
+               pushad
+               call getchar
+               popad
+%endif
+               xor edx,edx
+               call getlinsec.jmp
+               ret
+
+%ifdef DEBUG_XXX
+dump_params:
+               push eax
+               call cwritestr
+               mov ax,es
+               call writehex4
+               mov si,txt2
+               call cwritestr
+               mov ax,bx
+               call writehex4
+               mov si,txt3
+               call cwritestr
+               pop eax
+               push eax
+               call writehex8
+               mov si,txt3
+               call cwritestr
+               mov ax,bp
+               call writehex4
+               pop eax
+               ret
+
+txt0           db 'linsec3: ', 0
+txt1           db 'linsec:  ', 0
+txt2           db ':', 0
+txt3           db ', ', 0
+
+%include "writehex.inc"
+
+%endif
+
+
+; dl: new disk
+; return: CF = 1 -> error
+disk_change:
+               cmp dl,[CurrentDisk]
+               jz disk_change_90
+
+               mov [CurrentDisk],dl
+               movzx eax,dl
+               mov [gfx_user_info_0],eax
+               add dl,'1'
+               mov [boot_disk_msg0],dl
+               mov [boot_ndisk_msg0],dl
+
+disk_change_20:
+               cmp byte [gfx_ok],0
+               jz disk_change_40
+               mov al,3
+               xor di,di
+               xor si,si
+               call gfx_infobox
+
+               jmp disk_change_50
+disk_change_40:
+               mov si,clrln_msg
+               call cwritestr
+               mov si,boot_disk_msg
+               call cwritestr
+               call wait_for_key
+               mov si,clrln_msg
+               call cwritestr
+disk_change_50:
+               xor eax,eax
+               mov bp,1
+               push bx
+               xor edx,edx
+               call getlinsec.jmp
+               pop bx
+               mov eax,[es:bx+27h]
+               sub eax,[bsVolumeID]
+               movzx edx,byte [CurrentDisk]
+               cmp eax,edx
+               jz disk_change_90
+               mov [gfx_user_info_1],eax
+
+               cmp byte [gfx_ok],0
+               jz disk_change_70
+               mov al,4
+               xor di,di
+               xor si,si
+               call gfx_infobox
+
+               jmp disk_change_50
+disk_change_70:
+               mov si,clrln_msg
+               call cwritestr
+               mov si,boot_ndisk_msg
+               call cwritestr
+;              mov eax,[es:bx+27h]
+;              call writehex8
+               call wait_for_key
+               mov si,clrln_msg
+               call cwritestr
+
+               jmp disk_change_20
+disk_change_90:
+               ret
+
+
+bsVolumeID     equ bsHugeSectors+7
+
+boot_disk_msg  db 'Please insert boot disk '
+boot_disk_msg0 db '0; then press ENTER to continue.', 0
+boot_ndisk_msg db 'This is not boot disk '
+boot_ndisk_msg0        db '0. Press ENTER to continue.', 0
+
+DiskSize       dw 0                    ; unlimited
+CurrentDisk    db 0                    ; current disk
+
+clrln_msg      db 0dh, '                                                       
     ', 0dh, 0
+
+
+cache_metadata:
+               cmp word [DiskSize],0
+               jz cache_md_90
+
+               mov eax,[FAT]
+               mov ecx,[bxFATsecs]
+cache_md_20:
+               push eax
+               push cx
+               call getcachesector
+               pop cx
+               pop eax
+               inc eax
+               loop cache_md_20
+
+               mov eax,[RootDir]
+cache_md_40:
+               push eax
+               call getcachesector
+               pop eax
+               call nextsector
+               jnc cache_md_40
+               
+cache_md_90:
+               ret
+
+
+%endif
+
+
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; gfx stuff
+;
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+gfx_menu_seg           equ real_mode_seg
+
+; != 0 -> graphics active
+gfx_ok                 db 0
+gfx_cwritestr_old      db 0c3h         ; 'ret'
+
+gfx_mem_start_seg      dw 0
+gfx_mem_end_seg                dw 0
+
+                       align 4, db 0
+; the memory area we are working with
+gfx_mem                        dd 0            ; linear address
+gfx_mem_align          dd 0            ; aligned data start
+gfx_mem_file           dd 0            ; aligned gfx data start
+gfx_mem_max            dd 0            ; end address
+gfx_mem_free           dd 0            ; start of free area for malloc (after 
pcx image)
+
+; interface to loadable gfx extension (seg:ofs values)
+gfx_bc_jt              dd 0
+
+gfx_bc_init            dd 0
+gfx_bc_done            dd 0
+gfx_bc_input           dd 0
+gfx_bc_menu_init       dd 0
+gfx_bc_infobox_init    dd 0
+gfx_bc_infobox_done    dd 0
+gfx_bc_progress_init   dd 0
+gfx_bc_progress_done   dd 0
+gfx_bc_progress_update dd 0
+gfx_bc_progress_limit  dd 0
+gfx_bc_password_init   dd 0
+gfx_bc_password_done   dd 0
+
+; menu entry descriptor
+menu_entries           equ 0
+menu_default           equ 2           ; seg:ofs
+menu_ent_list          equ 6           ; seg:ofs
+menu_ent_size          equ 10
+menu_arg_list          equ 12          ; seg:ofs
+menu_arg_size          equ 16
+sizeof_menu_desc       equ 18
+
+menu_desc              zb sizeof_menu_desc
+
+; system config data (32 bytes)
+gfx_sysconfig          equ $
+gfx_bootloader         db 1                    ;  0: boot loader type (0: 
lilo, 1: syslinux, 2: grub)
+gfx_sector_shift       db SECTOR_SHIFT         ;  1: sector shift
+gfx_media_type         db 0                    ;  2: media type (0: disk, 1: 
floppy, 2: cdrom)
+gfx_failsafe           db 0                    ;  3: turn on failsafe mode
+gfx_reserved_1         db 0                    ;  4
+gfx_boot_drive         db 0                    ;  5: BIOS boot drive
+gfx_reserved_2         zb 3                    ;  6
+gfx_callback           dw gfx_cb               ;  9: offset to callback handler
+gfx_reserved_3         db 0                    ; 11
+gfx_user_info_0                dd 0                    ; 12: data for info box
+gfx_user_info_1                dd 0                    ; 16: data for info box
+gfx_mem_size           dd 0                    ; 20: BIOS memory size (in 
bytes)
+gfx_xmem_0             dw 0                    ; 24: extended mem area 0 
(start:size in MB; 12:4 bits)
+gfx_xmem_1             dw 0                    ; 26: extended mem area 1
+gfx_reserved_4         dd 0                    ; 28
+                                               ; 32
+
+gfx_slash              db '/', 0
+
+%macro         lin2segofs 3
+               push %1
+               call gfx_l2so
+               pop %3
+               pop %2
+%endmacro
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+; must not change registers!
+;
+gfx_get_sysconfig:
+               push ax
+%if IS_ISOLINUX
+               mov al,[DriveNo]
+%else
+               mov al,[DriveNumber]
+%endif
+               mov [gfx_boot_drive],al
+
+%if IS_ISOLINUX
+               mov ah,2
+%else
+               mov ah,0
+%endif
+               cmp al,80h      ; floppy ?
+               jae gfx_get_sysconfig_20
+               mov ah,1
+gfx_get_sysconfig_20:
+
+               mov [gfx_media_type],ah
+
+               pop ax
+               ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Initialize graphics code. Load and display graphics data.
+;
+;  dx:ax       file length
+;  si          start cluster
+;
+;  return:     [gfx_ok] = 0/1
+;
+gfx_init:
+               push es
+
+               test byte [KbdFlags],3
+               jz gfx_init_10
+               mov byte [gfx_failsafe],1
+               call ask_user
+gfx_init_10:
+
+               cmp byte [gfx_failsafe],2
+               jae gfx_init_80
+
+               call highmemsize
+
+               ; setup extended memory areas
+               pusha
+               mov eax,[HighMemSize]
+               mov [gfx_mem_size],eax
+               shr eax,20
+               cmp ax,16
+               jb gfx_init_40                  ; at least 16MB
+               mov word [gfx_xmem_0],81h       ; 1MB at 8MB
+               mov word [gfx_xmem_1],0a1h      ; 1MB at 10MB
+gfx_init_40:
+               popa
+
+               cld
+
+               movzx ebx,word [gfx_mem_start_seg]
+               shl ebx,4
+               jz gfx_init_80
+
+               movzx ecx,word [gfx_mem_end_seg]
+               shl ecx,4
+               jz gfx_init_80
+
+               cmp ecx,ebx
+               jbe gfx_init_80
+
+               ; define our memory area
+               ; gfx_mem _must_ be 16-byte aligned
+               mov dword [gfx_mem],ebx
+               mov dword [gfx_mem_free],ebx
+               mov dword [gfx_mem_max],ecx
+
+               call gfx_read_file
+               cmp byte [gfx_ok],0
+               jz near gfx_init_90
+
+               call gfx_get_sysconfig
+
+               ; align 4
+               mov eax,[gfx_mem_free]
+               add eax,3
+               and eax,~3
+               mov [gfx_mem_free],eax
+
+               ; setup jump table
+               les bx,[gfx_bc_jt]
+
+               mov ax,[es:bx]
+               mov [gfx_bc_init],ax
+               mov [gfx_bc_init+2],es
+
+               mov ax,[es:bx+2]
+               mov [gfx_bc_done],ax
+               mov [gfx_bc_done+2],es
+
+               mov ax,[es:bx+4]
+               mov [gfx_bc_input],ax
+               mov [gfx_bc_input+2],es
+
+               mov ax,[es:bx+6]
+               mov [gfx_bc_menu_init],ax
+               mov [gfx_bc_menu_init+2],es
+
+               mov ax,[es:bx+8]
+               mov [gfx_bc_infobox_init],ax
+               mov [gfx_bc_infobox_init+2],es
+
+               mov ax,[es:bx+10]
+               mov [gfx_bc_infobox_done],ax
+               mov [gfx_bc_infobox_done+2],es
+
+               mov ax,[es:bx+12]
+               mov [gfx_bc_progress_init],ax
+               mov [gfx_bc_progress_init+2],es
+
+               mov ax,[es:bx+14]
+               mov [gfx_bc_progress_done],ax
+               mov [gfx_bc_progress_done+2],es
+
+               mov ax,[es:bx+16]
+               mov [gfx_bc_progress_update],ax
+               mov [gfx_bc_progress_update+2],es
+
+               mov ax,[es:bx+18]
+               mov [gfx_bc_progress_limit],ax
+               mov [gfx_bc_progress_limit+2],es
+
+               mov ax,[es:bx+20]
+               mov [gfx_bc_password_init],ax
+               mov [gfx_bc_password_init+2],es
+
+               mov ax,[es:bx+22]
+               mov [gfx_bc_password_done],ax
+               mov [gfx_bc_password_done+2],es
+
+               mov eax,[gfx_mem_file]
+               mov ebx,[gfx_mem_free]
+               mov ecx,[gfx_mem_max]
+               mov edi,[gfx_mem_align]
+               mov dx,cs
+
+               mov si,gfx_sysconfig
+               call far [gfx_bc_init]
+               jc gfx_init_80
+
+               mov byte [gfx_ok],1
+
+               ; turn off 'cwritestr'
+               mov al,[cwritestr]
+               cmp al,0c3h
+               jz gfx_init_90
+               mov [gfx_cwritestr_old],al
+
+               jmp gfx_init_90
+
+gfx_init_80:
+               mov byte [gfx_ok],0
+gfx_init_90:
+               pop es
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Back to text mode.
+;
+;  return:     [gfx_ok] = 0
+;
+gfx_done:
+               cmp byte [gfx_ok],0
+               jz gfx_done_90
+               call far [gfx_bc_done]
+               mov byte [gfx_ok],0
+
+               ; reactivate 'cwritestr'
+               mov al,[gfx_cwritestr_old]
+               cmp al,0c3h
+               jz gfx_done_90
+               mov [cwritestr],al
+gfx_done_90:
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+gfx_input:
+               cmp byte [gfx_ok],0
+               jz gfx_input_90
+               call far [gfx_bc_input]
+               jnc gfx_input_50
+               mov ax,1
+gfx_input_50:
+               cmp ax,1
+               jnz gfx_input_90
+               push ax
+               call gfx_done
+               pop ax
+gfx_input_90:
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; es:di                string
+; return:
+;  cx          length
+gfx_strlen:
+               mov cx,-1
+               mov al,0
+               repnz scasb
+               not cx
+               dec cx
+               ret
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+gfx_setup_menu:
+               cmp byte [gfx_ok],0
+               jz gfx_setup_menu_90
+
+               mov dword [menu_desc+menu_default],gfx_menu_seg << 16
+
+               push ds
+               pop es
+               mov si,default_cmd
+               mov di,trackbuf
+               call mangle_name
+               mov si,trackbuf
+               les di,[menu_desc+menu_default]
+               call unmangle_name
+               inc di
+
+               mov [menu_desc+menu_ent_list],di
+               mov [menu_desc+menu_ent_list+2],es
+               mov [menu_desc+menu_arg_list],di
+               mov [menu_desc+menu_arg_list+2],es
+
+               ; first, count entries and find max kernel and append length
+
+               push ds
+               pop es
+
+               xor si,si
+               jmp gfx_setup_menu_20
+gfx_setup_menu_10:
+               push ds
+               push word vk_seg
+               pop ds
+               mov di,VKernelBuf
+               call rllunpack
+               pop ds
+
+               ; count only non empty entries
+               cmp byte [es:VKernelBuf],0
+               jz gfx_setup_menu_20
+
+               inc word [menu_desc+menu_entries]
+
+               push si
+               mov si,VKernelBuf
+               mov di,KernelCName
+               push di
+               call unmangle_name
+               pop di
+               pop si
+
+               call gfx_strlen
+
+               cmp cx,[menu_desc+menu_ent_size]
+               jbe gfx_setup_menu_15
+               mov [menu_desc+menu_ent_size],cx
+gfx_setup_menu_15:
+               mov ax,[VKernelBuf+vk_appendlen]
+               cmp ax,[menu_desc+menu_arg_size]
+               jbe gfx_setup_menu_20
+               mov [menu_desc+menu_arg_size],ax
+
+gfx_setup_menu_20:
+               cmp si,[VKernelBytes]
+               jb gfx_setup_menu_10
+
+               inc word [menu_desc+menu_ent_size]
+               mov ax,[menu_desc+menu_ent_size]
+               inc ax
+               add [menu_desc+menu_arg_size],ax
+
+               ; ...and again, but this time copy entries
+
+               mov word [menu_desc+menu_entries],0
+
+               xor si,si
+               jmp gfx_setup_menu_60
+gfx_setup_menu_30:
+               push ds
+               pop es
+               push ds
+               push word vk_seg
+               pop ds
+               mov di,VKernelBuf
+               call rllunpack
+               pop ds
+
+               ; count only non empty entries
+               cmp byte [es:VKernelBuf],0
+               jz gfx_setup_menu_60
+
+               mov di,[menu_desc+menu_arg_list]
+               add di,[menu_desc+menu_arg_size]
+               jc gfx_setup_menu_60
+
+               inc word [menu_desc+menu_entries]
+
+               push si
+
+               mov si,VKernelBuf
+               mov di,KernelCName
+               push ds
+               pop es
+               push di
+               call unmangle_name
+               pop si
+               mov cx,[menu_desc+menu_ent_size]
+               les di,[menu_desc+menu_arg_list]
+
+               rep movsb
+
+               mov cx,[VKernelBuf+vk_appendlen]
+               mov si,VKernelBuf+vk_append
+               rep movsb
+               mov byte [es:di],0
+
+               pop si
+
+               mov ax,[menu_desc+menu_arg_size]
+               add [menu_desc+menu_arg_list],ax
+
+gfx_setup_menu_60:
+               cmp si,[VKernelBytes]
+               jb gfx_setup_menu_30
+
+               mov ax,[menu_desc+menu_ent_size]
+               mov bx,[menu_desc+menu_arg_size]
+               mov [menu_desc+menu_ent_size],bx
+               add ax,[menu_desc+menu_ent_list]
+               mov [menu_desc+menu_arg_list],ax
+
+               mov si,menu_desc
+
+               push ds
+               pop es
+
+               call far [gfx_bc_menu_init]
+
+gfx_setup_menu_90:
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+gfx_infobox:
+               pushad
+               cmp byte [gfx_ok],0
+               jz gfx_infobox_90
+               call far [gfx_bc_infobox_init]
+               xor di,di
+               xor ax,ax
+               call far [gfx_bc_input]
+               call far [gfx_bc_infobox_done]
+gfx_infobox_90:
+               popad
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+gfx_progress_init:
+               pushad
+               cmp byte [gfx_ok],0
+               jz gfx_progress_init_90
+               call far [gfx_bc_progress_init]
+gfx_progress_init_90:
+               popad
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+gfx_progress_done:
+               pushad
+               cmp byte [gfx_ok],0
+               jz gfx_progress_done_90
+               call far [gfx_bc_progress_done]
+gfx_progress_done_90:
+               popad
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+gfx_progress_update:
+               pushad
+               cmp byte [gfx_ok],0
+               jz gfx_progress_update_90
+               movzx eax,cx
+               call far [gfx_bc_progress_update]
+gfx_progress_update_90:
+               popad
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+gfx_progress_limit:
+               pushad
+               cmp byte [gfx_ok],0
+               jz gfx_progress_limit_90
+               movzx eax,ax
+               movzx edx,dx
+               call far [gfx_bc_progress_limit]
+gfx_progress_limit_90:
+               popad
+               ret
+
+
+%if 0
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+gfx_password:
+               pushad
+               cmp byte [gfx_ok],0
+               stc
+               jz gfx_password_90
+               call far [gfx_bc_password_init]
+               mov di,gfx_password_buf
+               mov cx,32
+               xor ax,ax
+               call far [gfx_bc_input]
+               mov si,gfx_password_buf
+               call far [gfx_bc_password_done]
+               jnc gfx_password_90
+               mov si,gfx_msg_wrong_password
+               xor di,di
+               mov al,0
+               call far [gfx_bc_infobox_init]
+               xor di,di
+               xor ax,ax
+               call far [gfx_bc_input]
+               call far [gfx_bc_infobox_done]
+               stc
+gfx_password_90:
+                popad
+                ret
+%endif
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Read graphics data and store them at [gfx_mem].
+;
+;  dx:ax       file length
+;  si          start cluster
+;
+;  return:     [gfx_ok] = 0/1
+;
+gfx_read_file:
+               push es
+               mov byte [gfx_ok],0
+               mov edi,[gfx_mem]
+               push dx                         ; DX:AX = length of file
+                push ax
+               pop edx
+               mov eax,[gfx_mem_free]
+               lea eax,[eax+edx+0fh]           ; add space for alignment
+               cmp eax,[gfx_mem_max]           ; max. length
+               ja near gfx_read_file_90
+               mov [gfx_mem_free],eax
+
+gfx_read_file_10:
+               mov bx,trackbuf
+               mov cx,[BufSafe]
+               push edi
+               push edx
+               call getfssec
+               pop edx
+               pop edi
+               movzx ecx,word [BufSafeBytes]
+               cmp edx,ecx
+               jae gfx_read_file_20
+               mov ecx,edx
+gfx_read_file_20:
+               push ecx
+               push edi
+               push si                         ; Save current cluster
+               push es
+               mov si,trackbuf
+               push edi
+               call gfx_l2so
+               pop di
+               pop es
+               rep movsb
+               pop es
+               pop si
+               pop edi
+               pop ecx
+               add edi,ecx
+               sub edx,ecx
+               ja gfx_read_file_10
+
+               call find_file
+               or eax,eax
+               jz gfx_read_file_90
+               push edi
+               push eax
+               add eax,edi
+               call align_it
+               pop eax
+               pop edi
+               sub edi,[gfx_mem]
+               add edi,[gfx_mem_align]
+               mov [gfx_mem_file],edi
+               add eax,edi
+               shr eax,4
+               mov [gfx_bc_jt+2],ax
+
+               mov byte [gfx_ok],1
+
+gfx_read_file_90:
+               pop es
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; locate graphics file
+;
+; return:      eax: code offset (0 -> no file found)
+;              edi: gfx file start
+;
+find_file:
+               mov edi,[gfx_mem]
+               lin2segofs edi,es,bx
+               call magic_ok
+               or eax,eax
+               jnz find_file_90
+
+               ; ok, maybe it's a cpio archive
+
+               ; note: edi must be properly aligned (2)!
+
+find_file_20:
+               mov ecx,[gfx_mem_free]
+               sub ecx,26 + 12                 ; min cpio header + gfx header
+               cmp edi,ecx
+               jae find_file_90
+
+               lin2segofs edi,es,bx
+               cmp word [es:bx],71c7h
+               jnz find_file_90                ; no cpio record
+
+               movzx esi,word [es:bx+20]       ; file name size
+
+               inc si
+               and si,~1                       ; align
+
+               mov ecx,[es:bx+22]              ; data size
+               rol ecx,16                      ; get word order right
+
+               inc ecx
+               and ecx,byte ~1                 ; align
+
+               add si,26                       ; skip header
+
+               add edi,esi
+               add bx,si
+               call magic_ok
+               or eax,eax
+               jnz find_file_90
+
+               add edi,ecx
+               jmp find_file_20
+
+find_file_90:
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+;  es:bx       file start
+;
+;  return:     eax:    offset to code entry
+;
+; Notes:
+;  - changes no regs except eax
+;
+magic_ok:
+               xor eax,eax
+               cmp dword [es:bx],0b2d97f00h    ; header.magic_id
+               jnz magic_ok_90
+               cmp byte [es:bx+4],7            ; header.version
+               jnz magic_ok_90
+               mov eax,[es:bx+8]
+magic_ok_90:
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+;  eax         address to be aligned
+;
+align_it:
+               push dword [gfx_mem]
+               pop dword [gfx_mem_align]
+               neg al
+               and eax,byte 0fh
+               jz align_it_90
+               add [gfx_mem_align],eax
+               mov esi,[gfx_mem]
+               mov ebx,[gfx_mem_free]
+               sub ebx,esi
+               sub ebx,byte 0fh
+               add esi,ebx
+               dec esi
+
+               std
+
+align_it_30:
+               or ebx,ebx
+               jz align_it_60
+               mov ecx,ebx
+               cmp ebx,8000h
+               jb align_it_40
+               mov ecx,8000h
+align_it_40:
+               push esi
+               sub ebx,ecx
+               sub [esp],ecx
+               push esi
+               call gfx_l2so
+               pop si
+               add si,8000h
+               sub word [esp],(8000h >> 4)
+               pop es
+               mov di,si
+               add di,ax
+               es rep movsb
+               pop esi
+               jmp align_it_30
+align_it_60:
+
+               cld
+
+align_it_90:
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Ask user whether to continue.
+;
+; don't change regs
+;
+ask_user:
+               pushad
+
+               mov si,failsafe_msg
+               call cwritestr
+
+ask_user_20:
+               mov ah,0
+               int 16h
+
+               cmp al,13
+               jnz ask_user_30
+               mov al,'c'
+ask_user_30:
+               or al,20h               ; force lower case
+
+               cmp al,'c'
+               jz ask_user_50
+               cmp al,'a'
+               jnz ask_user_20
+               mov byte [gfx_failsafe],2
+
+ask_user_50:
+
+               mov si,failsafe_key
+               mov [si],al
+               call cwritestr
+
+               popad
+               ret
+
+failsafe_msg   db 13, 10, 10, 10, 'Loading boot graphics... ',
+               db 'continue, abort (c/a)? c', 8, 0
+failsafe_key   db 0, 13, 10, 0
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+; Convert 32bit linear address to seg:ofs.
+;
+;  dword [esp + 2]:    linear address
+;
+; return:
+;  dword [esp + 2]:    seg:ofs
+;
+; Notes:
+;  - changes no regs
+;
+gfx_l2so:
+               push eax
+               mov eax,[esp + 6]
+               shr eax,4
+               mov [esp + 8],ax
+               and word [esp + 6],byte 0fh
+               pop eax
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
+cb_table       dw cb_status
+               dw cb_fopen
+               dw cb_fread
+               dw cb_getcwd
+               dw cb_chdir
+               dw cb_readsector
+cb_len         equ ($-cb_table)/2
+
+f_handle       dw 0
+f_size         dd 0
+fname_buf      times 64 db 0
+fname_buf_len  equ $ - fname_buf
+
+
+gfx_cb:
+               push cs
+               pop ds
+
+               cmp al,cb_len
+               jae gfx_cb_80
+
+               movzx bx,al
+               add bx,bx
+               call word [bx+cb_table]
+               jmp gfx_cb_90
+
+gfx_cb_80:
+               mov al,0ffh
+gfx_cb_90:
+               retf
+
+
+; Return status info.
+;
+; return:
+;  edx         filename buffer (64 bytes)
+;
+cb_status:
+               mov edx,cs
+               shl edx,4
+               add edx,fname_buf
+
+               xor al,al
+               ret
+
+; Open file.
+;
+; return:
+;    al                0: ok, 1: file not found
+;   ecx                file length (al = 0)
+;
+cb_fopen:
+               mov si,fname_buf
+               mov di,VGAFileMBuf      ; we just need some space
+               push ds
+               pop es
+               push di
+               call mangle_name
+               pop di
+               call searchdir
+               xchg ax,bx
+               mov al,1
+               jz cb_fopen_90
+               mov [f_handle],si
+               mov cx,dx
+               shl ecx,16
+               mov cx,bx
+               mov [f_size],ecx
+cb_fopen_80:
+               xor al,al
+cb_fopen_90:
+               ret
+
+
+; Read next chunk.
+;
+; return:
+;   edx                buffer address (linear)
+;   ecx                data length (< 64k)
+;
+cb_fread:
+               cmp dword [f_size],0
+               jz cb_fread_80
+               push cs
+               pop es
+               mov bx,trackbuf
+               mov cx,[BufSafe]
+               mov si,[f_handle]
+               call getfssec
+               mov [f_handle],si
+               mov ecx,[f_size]
+               movzx edx,word [BufSafeBytes]
+               cmp ecx,edx
+               jbe cb_fread_50
+               mov ecx,edx
+cb_fread_50:
+               sub [f_size],ecx
+               mov edx,cs
+               shl edx,4
+               add edx,trackbuf
+
+cb_fread_80:
+               xor al,al
+cb_fread_90:
+               ret
+
+
+; Return current working directory.
+;
+; return:
+;  edx         filename
+;
+cb_getcwd:
+               mov edx,cs
+               shl edx,4
+%if IS_ISOLINUX
+               add edx,isolinux_dir
+%else
+               add edx,gfx_slash
+%endif
+               xor al,al
+               ret
+
+
+; Set current working directory.
+;
+cb_chdir:
+%if IS_ISOLINUX
+
+               push cs
+               pop es
+               mov si,fname_buf
+               mov di,isolinux_dir
+cb_chdir_20:
+               lodsb
+               stosb
+               or al,al
+               jz cb_chdir_60
+               cmp di,isolinux_cfg - 1
+               jb cb_chdir_20
+               xor al,al
+               stosb
+cb_chdir_60:
+               call get_fs_structures
+
+%endif
+               xor al,al
+               ret
+
+
+; read sector
+;
+;  edx         sector
+;
+; return:
+;  edx         buffer (linear address)
+;
+;  Note: does not return on error!
+;
+cb_readsector:
+               mov eax,edx
+               push ds
+               pop es
+               mov bx,trackbuf
+               call getonesec
+               mov edx,ds
+               shl edx,4
+               add edx,trackbuf
+               xor al,al
+               ret
+
--- keywords
+++ keywords
@@ -32,3 +32,5 @@
 f10
 f11
 f12
+gfxboot
+disksize
--- Makefile
+++ Makefile
@@ -122,7 +122,7 @@
 kwdhash.gen: keywords genhash.pl
        $(PERL) genhash.pl < keywords > kwdhash.gen
 
-ldlinux.bin: ldlinux.asm kwdhash.gen version.gen
+ldlinux.bin: ldlinux.asm kwdhash.gen version.gen gfxboot.inc
        $(NASM) -f bin -DDATE_STR="'$(DATE)'" -DHEXDATE="$(HEXDATE)" \
                -DMAP=$(@:.bin=.map) -l $(@:.bin=.lst) -o $@ $<
        $(PERL) checkov.pl ldlinux.map $@
@@ -132,16 +132,18 @@
                -DMAP=$(@:.bin=.map) -l $(@:.bin=.lst) -o $@ $<
        $(PERL) checkov.pl $(@:.bin=.map) $@
 
-isolinux.bin: isolinux.asm kwdhash.gen version.gen checksumiso.pl
+isolinux.bin: isolinux.asm kwdhash.gen version.gen checksumiso.pl gfxboot.inc
        $(NASM) -f bin -DDATE_STR="'$(DATE)'" -DHEXDATE="$(HEXDATE)" \
                -DMAP=$(@:.bin=.map) -l $(@:.bin=.lst) -o $@ $<
+       ./add_crc $@
        $(PERL) checkov.pl $(@:.bin=.map) $@
        $(PERL) checksumiso.pl $@
 
 # Special verbose version of isolinux.bin
-isolinux-debug.bin: isolinux-debug.asm kwdhash.gen version.gen checksumiso.pl
+isolinux-debug.bin: isolinux-debug.asm kwdhash.gen version.gen checksumiso.pl 
gfxboot.inc
        $(NASM) -f bin -DDATE_STR="'$(DATE)'" -DHEXDATE="$(HEXDATE)" \
                -DMAP=$(@:.bin=.map) -l $(@:.bin=.lst) -o $@ $<
+       ./add_crc $@
        $(PERL) checkov.pl $(@:.bin=.map) $@
        $(PERL) checksumiso.pl $@
 
--- runkernel.inc
+++ runkernel.inc
@@ -202,6 +202,13 @@
                 pop ds
                sub si,cmd_line_here
                mov [CmdLineLen],si             ; Length including final null
+
+%ifdef WITH_GFX
+               mov eax,[KernelSects]
+               mov si,KernelCName
+               call gfx_progress_init
+%endif
+
 ;
 ; Now check if we have a large kernel, which needs to be loaded high
 ;
@@ -298,6 +305,11 @@
                 jz nk_noinitrd
                call parse_load_initrd
 nk_noinitrd:
+
+%ifdef WITH_GFX
+               call gfx_progress_done
+%endif 
+
 ;
 ; Abandon hope, ye that enter here!  We do no longer permit aborts.
 ;
@@ -306,6 +318,10 @@
                mov si,ready_msg
                call cwritestr
 
+%ifdef WITH_GFX
+               call gfx_done
+%endif
+
                call vgaclearmode               ; We can't trust ourselves 
after this
 
                UNLOAD_PREP                     ; Module-specific hook
@@ -606,6 +622,18 @@
                jmp crlf                        ; Print carriage return and 
return
 
 .notthere:
+
+%ifdef WITH_GFX
+               cmp byte [gfx_ok],0
+               jz .nogfx
+               mov si,err_noinitrda
+               mov di,InitRDCName  
+               mov al,1
+               call gfx_infobox
+               call do_reboot  
+.nogfx:
+%endif
+
                 mov si,err_noinitrd
                 call cwritestr
                 mov si,InitRDCName
@@ -614,7 +642,19 @@
                 jmp abort_load
 
 no_high_mem:                                   ; Error routine
+
+%ifdef WITH_GFX
+               cmp byte [gfx_ok],0
+               jz .nogfx
                mov si,err_nohighmem
+               xor di,di
+               mov al,1 
+               call gfx_infobox
+               call do_reboot  
+.nogfx:
+%endif
+
+               mov si,err_nohighmem
                 jmp abort_load
 
                 ret
--- add_crc
+++ add_crc
@@ -0,0 +1,57 @@
+#! /usr/bin/perl
+
+use integer;
+
+# for isolinux
+#
+# Ensure checksum over (first sector - 64 bytes) [internally: FirstSecSum]
+# is 0 by adjusting the variable csum_value.
+#
+# Though isolinux checks the integrity with a separate checksum after all
+# data has been loaded this does not help with BIOSes that don't get even
+# the first 2k right. Hence this additional check. :-(
+#
+
+$file = shift;
+$list = "$file";
+$list =~ s/\.bin$/.lst/;
+
+open F, $list;
+
+while(<F>) {
+  if(/^\s*\d+\s*(\S+)\s*0+\s*(\<\d+\>\s*)?csum_value\s*dd\s*0/) {
+    $ofs = hex $1;
+  }
+}
+close F;
+
+die "oops 1\n" unless $ofs && !($ofs & 3);
+
+# print "$ofs\n";
+
+open F, $file or die "$file: $!\n";
+
+$file_size = -s $file;
+
+sysread F, $buf, $file_size;
+
+close F;
+
+die "oops 1\n" if $file_size != length($buf);
+
[EMAIL PROTECTED] = unpack "V512", $buf;
+
+for ($sum = 0, $i = 16; $i < 512; $i++) {
+  $sum += $x[$i];
+}
+
+# printf "0x%08x\n", $sum;
+
+$ns = pack "V", -$sum;
+
+substr($buf, $ofs, 4) = $ns;
+
+open F, ">$file" or die "$file: $!\n";
+
+syswrite F, $buf;
+
--- ui.inc
+++ ui.inc
@@ -16,6 +16,12 @@
 ;
                call parse_config               ; Parse configuration file
 no_config_file:
+
+%ifdef WITH_GFX
+               ; build gfx menu
+               call gfx_setup_menu
+%endif
+
 ;
 ; Check whether or not we are supposed to display the boot prompt.
 ;
@@ -29,6 +35,19 @@
                cmp word [NoEscape],0           ; If NOESCAPE, no prompt,
                jne auto_boot                   ; always run default cmd
 
+%ifdef WITH_GFX
+               cmp byte [gfx_ok],0
+               jz .nogfx
+               mov di,command_line
+               mov cx,max_cmd_len
+               xor eax,eax
+               xchg eax,[KbdTimeout]           ; only the first time
+               call gfx_input
+               cmp ax,1
+               jnz load_kernel
+.nogfx:
+%endif
+
                mov si,boot_prompt
                call cwritestr
 
@@ -261,9 +280,21 @@
                push word real_mode_seg
                pop es
                mov di,cmd_line_here
+
+%ifdef WITH_GFX
+               ; gfx code includes them
+               cmp byte [gfx_ok],0
+               jnz .isgfx
+%endif
+
                mov si,VKernelBuf+vk_append
                mov cx,[VKernelBuf+vk_appendlen]
                rep movsb
+
+%ifdef WITH_GFX
+.isgfx:
+%endif
+
                mov [CmdLinePtr],di             ; Where to add rest of cmd
                pop es
                mov di,KernelName
@@ -278,7 +309,7 @@
 %endif
                xor bx,bx                       ; Try only one version
 
-%if IS_PXELINUX || IS_ISOLINUX
+%if IS_PXELINUX || IS_ISOLINUX || IS_SYSLINUX
                ; Is this a "localboot" pseudo-kernel?
 %if IS_PXELINUX
                cmp byte [VKernelBuf+vk_rname+4], 0
@@ -362,6 +393,18 @@
                push di
                 call unmangle_name              ; Get human form
                mov si,err_notfound             ; Complain about missing kernel
+
+%ifdef WITH_GFX
+               cmp byte [gfx_ok],0
+               jz .nogfx
+               pop di
+               mov al,2
+               call gfx_infobox
+               mov si,no_msg
+               jmp abort_load
+.nogfx:
+%endif
+
                call cwritestr
                pop si                          ; KernelCName
                 call cwritestr
--- rllpack.inc
+++ rllpack.inc
@@ -29,7 +29,7 @@
 ;
 ; rllpack:
 ;      Pack CX bytes from DS:SI into ES:DI
-;      Returns updated SI, DI and CX = number of bytes output
+;      Returns updated SI, DI and DX = number of bytes output
 ;
 rllpack:
                push ax
--- README.gfxboot
+++ README.gfxboot
@@ -0,0 +1,41 @@
+Graphical boot screen
+=====================
+
+  syslinux/isolinux support a graphical boot screen using VESA BIOS
+  extensions. (Note that this is different from the graphics support that
+  syslinux comes with which uses a 640x480, 16 colors VGA mode).
+
+  To use it you have to prepare a special boot logo file and put a line like
+  this into syslinux.cfg/isolinux.cfg:
+
+    gfxboot foo
+
+  The tools to create 'foo' from the above example are in the gfxboot
+  package. Please _do_ have a look at its documentation before you begin.
+
+  Note that you cannot use comboot images and graphics at the same time as
+  the memory used for the picture overlaps the comboot loading area.
+
+  If you encouter problems with the graphics code, hold down SHIFT while
+  syslinux starts. This will put it into 'failsafe' mode that lets you
+  interactively skip critical parts (like monitor detection).
+
+
+
+Spread boot images over several floppy disks (syslinux)
+=======================================================
+
+  You can prepare boot disks with a file system that spans several disks.
+  The 'mkbootdisk' script from the openSUSE project can create a suitable
+  file system.
+
+  syslinux will ask you for disk changes if necessary. To enable this
+  feature, use
+
+    disksize <size_of_single_disk_in_sectors>
+
+  Note that every individual disk must have at least a valid FAT boot
+  sector. syslinux will use the serial number stored there to verify that
+  the correct disk has been inserted (its last hex digit is the zero based
+  disk number).
+
--- keywords.inc
+++ keywords.inc
@@ -77,9 +77,16 @@
 %if IS_PXELINUX
                keyword ipappend,  pc_ipappend
 %endif
-%if IS_PXELINUX || IS_ISOLINUX
+%if IS_PXELINUX || IS_ISOLINUX || IS_SYSLINUX
                keyword localboot, pc_localboot
 %endif
 
+%ifdef WITH_GFX
+               keyword gfxboot,   pc_filecmd,  get_gfx_file
+%if IS_SYSLINUX
+               keyword disksize,  pc_disksize, DiskSize
+%endif
+%endif
+
 keywd_count    equ ($-keywd_table)/keywd_size
 
--- isolinux.asm
+++ isolinux.asm
@@ -20,6 +20,10 @@
 ; ****************************************************************************
 
 %define IS_ISOLINUX 1
+
+%define WITH_GFX 1
+; %define DEBUG_DISKIO
+
 %include "macros.inc"
 %include "config.inc"
 %include "kernel.inc"
@@ -76,6 +80,7 @@
 vk_seg          equ 2000h              ; Virtual kernels
 xfer_buf_seg   equ 1000h               ; Bounce buffer for I/O to high mem
 comboot_seg    equ real_mode_seg       ; COMBOOT image loading zone
+first_free_seg equ 4000h               ; end of isolinux used memory
 
 ;
 ; File structure.  This holds the information for each currently open file.
@@ -270,6 +275,21 @@
                mov [FirstSecSum],edi
 
                mov [DriveNo],dl
+
+               ; check whether the BIOS did load us correctly
+               cmp dl,80h                      ; some BIOSes try to do floppy 
emulation...
+               jb bios_err
+               cmp dword [FirstSecSum], byte 0
+               jz bios_ok
+bios_err:
+               mov si,broken_bios_msg
+               call writemsg
+               jmp short $
+broken_bios_msg        db 13, 10, 'Cannot boot from this CD. Please use CD2 or 
try a BIOS update.', 13, 10, 0
+               align 4
+csum_value     dd 0
+bios_ok:
+
 %ifdef DEBUG_MESSAGES
                mov si,startup_msg
                call writemsg
@@ -294,6 +314,9 @@
                ; Other nonzero fields
                inc word [dsp_sectors]
 
+%if 0
+               ; Some BIOSes don't like that call.
+
                ; Now figure out what we're actually doing
                ; Note: use passed-in DL value rather than 7Fh because
                ; at least some BIOSes will get the wrong value otherwise
@@ -314,6 +337,8 @@
                call crlf
 %endif
 
+%endif
+
 found_drive:
                ; Alright, we have found the drive.  Now, try to find the
                ; boot file itself.  If we have a boot info table, life is
@@ -438,6 +463,9 @@
 %endif
                jmp all_read                    ; Jump to main code
 
+%if 0
+               ; doesn't work anyway, see above
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Start of BrokenAwardHack --- 10-nov-2002           [EMAIL PROTECTED]
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -621,6 +649,7 @@
                mov si,trysbm_msg
                call writemsg
                jmp .found_drive                ; Pray that this works...
+%endif
 
 fatal_error:
                mov si,nothing_msg
@@ -680,10 +709,17 @@
 ;
 getlinsec:
                mov si,dapa                     ; Load up the DAPA
+               mov [si+8],eax
+               ; seems that some BIOSes have problems if the target
+               ; segment is 0 (don't ask); to avoid this, we normalize
+               ; the buffer address here
+               ; -> seen on Acer TravelMate C102Ti
                mov [si+4],bx
-               mov bx,es
-               mov [si+6],bx
-               mov [si+8],eax
+               and word [si+4],0fh
+               mov ax,es
+               shr bx,4
+               add ax,bx
+               mov [si+6],ax
 .loop:
                push bp                         ; Sectors left
                cmp bp,[MaxTransfer]
@@ -710,14 +746,77 @@
                ; INT 13h with retry
 xint13:                mov byte [RetryCount],retry_count
 .try:          pushad
+%ifdef DEBUG_DISKIO
+               pushad
+               mov cx,16
+.zap:
+               lodsb
+               call writehex2
+               mov al,' '
+               call writechr
+               loop .zap
+               mov ah,0
+               int 16h
+               popad
+%endif
+               ; seen buggy bios that overwrites buffer address on error...
+               push dword [dapa + 4]
                int 13h
+               pop dword [dapa + 4]
+%ifdef DEBUG_DISKIO   
+               pushad
+               pushf
+               push ax
+               mov al,':'
+               call writechr
+               mov al,' '
+               call writechr
+               pop ax
+               sbb al,al
+               call writehex4
+               call crlf
+               mov ah,0
+               int 16h
+               popf
+               popad
+%endif
                jc .error
+.noerror:
                add sp,byte 8*4                 ; Clean up stack
                ret
 .error:
+               or ah,ah
+               jz .noerror
                mov [DiskError],ah              ; Save error code
                popad
                mov [DiskSys],ax                ; Save system call number
+
+%if 0
+               ; eject currently not supported - doesn't work anyway with
+               ; most BIOSes
+
+               test byte [gfx_user_note],1
+               jz .noeject
+               cmp byte [RetryCount],4
+               ja .noeject
+               cmp byte [DiskError],0aah       ; drive not ready
+               jnz .noeject
+               ; might have been cdrom eject, wait a bit
+               cmp byte [gfx_ok],0
+               jz .noeject
+               push si
+               push di
+               push ax
+               mov si,err_not_ready
+               xor di,di
+               mov al,0
+               call gfx_infobox
+               pop ax
+               pop di
+               pop si
+%endif
+.noeject:
+
                dec byte [RetryCount]
                jz .real_error
                push ax
@@ -766,6 +865,17 @@
                mov fs,ax
                mov gs,ax
                sti
+
+               cmp byte [gfx_ok],0
+               jz .nogfx
+               mov si,err_failed_gfx
+               xor di,di
+               mov al,1
+               call gfx_infobox
+               call gfx_done
+               call do_reboot
+.nogfx:
+
                mov si,err_bootfailed
                call cwritestr
                call getchar
@@ -817,6 +927,9 @@
 crlf_msg       db CR, LF
 null_msg       db 0
 
+err_failed_gfx db 'Error reading boot CD.', 0
+err_not_ready  db 'CDROM drive not ready.', 0
+
                alignb 4, db 0
 StackPtr       dw StackBuf, 0                  ; SS:SP for stack reset
 MaxTransfer    dw 32                           ; Max sectors per transfer
@@ -886,6 +999,9 @@
 ; (which will be at 16 only for a single-session disk!); from the PVD
 ; we should be able to find the rest of what we need to know.
 ; 
+               call get_fs_structures
+               jmp get_fs_struct_done
+
 get_fs_structures:
                mov eax,[bi_pvd]
                mov bx,trackbuf
@@ -911,10 +1027,15 @@
                ; Look for an isolinux directory, and if found,
                ; make it the current directory instead of the root
                ; directory.
+
+               cmp byte [gfx_ok],0             ; don't look at both
+               jnz .gfx
+
                mov di,boot_dir                 ; Search for /boot/isolinux
                mov al,02h
                call searchdir_iso
                jnz .found_dir
+.gfx:
                mov di,isolinux_dir
                mov al,02h                      ; Search for /isolinux
                call searchdir_iso
@@ -935,7 +1056,10 @@
                call crlf
 %endif
 .no_isolinux_dir:
+               ret
 
+get_fs_struct_done:
+
 ;
 ; Locate the configuration file
 ;
@@ -1496,6 +1620,9 @@
 %include "strcpy.inc"          ; strcpy()
 %include "rawcon.inc"          ; Console I/O w/o using the console functions
 
+%include "gfxboot.inc"         ; add gfx things
+
+
 ; -----------------------------------------------------------------------------
 ;  Begin data section
 ; -----------------------------------------------------------------------------
@@ -1517,7 +1644,8 @@
                db 'booting, and I will take your word for it.', CR, LF, 0
 err_badcfg      db 'Unknown keyword in config file.', CR, LF, 0
 err_noparm      db 'Missing parameter in config file.', CR, LF, 0
-err_noinitrd    db CR, LF, 'Could not find ramdisk image: ', 0
+err_noinitrd    db CR, LF
+err_noinitrda  db 'Could not find ramdisk image: ', 0
 err_nohighmem   db 'Not enough memory to load specified kernel.', CR, LF, 0
 err_highload    db CR, LF, 'Kernel transfer failure.', CR, LF, 0
 err_oldkernel   db 'Cannot load a ramdisk with an old kernel image.'
@@ -1542,6 +1670,7 @@
 default_len    equ ($-default_str)
 boot_dir       db '/boot'                      ; /boot/isolinux
 isolinux_dir   db '/isolinux', 0
+               zb 64
 ConfigName     equ $
 isolinux_cfg   db 'isolinux.cfg', 0
 err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0
--- ldlinux.asm
+++ ldlinux.asm
@@ -25,6 +25,9 @@
 %ifndef IS_MDSLINUX
 %define IS_SYSLINUX 1
 %endif
+
+%define WITH_GFX 1
+
 %include "macros.inc"
 %include "config.inc"
 %include "kernel.inc"
@@ -87,6 +90,7 @@
 vk_seg          equ 2000h              ; Virtual kernels
 xfer_buf_seg   equ 1000h               ; Bounce buffer for I/O to high mem
 comboot_seg    equ real_mode_seg       ; COMBOOT image loading zone
+first_free_seg equ 5000h               ; end of syslinux used memory
 
 ;
 ; File structure.  This holds the information for each currently open file.
@@ -373,6 +377,8 @@
                add eax,[bsHidden]              ; Add partition offset
                xor edx,edx                     ; Zero-extend LBA (eventually 
allow 64 bits)
 
+.patch:                jmp strict near .jmp
+
 .jmp:          jmp strict short getlinsec_cbios
 
 ;
@@ -932,6 +938,47 @@
 %include "bootsect.inc"
 
 ;
+; Boot a specified local disk.  AX specifies the BIOS disk number; or
+; 0xFFFF in case we should execute INT 18h ("next device.")
+;
+local_boot:
+               call vgaclearmode
+               lss sp,[cs:Stack]               ; Restore stack pointer
+               xor dx,dx
+               mov ds,dx
+               mov es,dx
+               mov fs,dx
+               mov gs,dx
+               mov si,localboot_msg
+               call cwritestr
+               cmp ax,-1
+               je .int18
+
+               ; Load boot sector from the specified BIOS device and jump to 
it.
+               mov dl,al
+               xor dh,dh
+               push dx
+               xor ax,ax                       ; Reset drive
+               int 13h
+               mov ax,0201h                    ; Read one sector
+               mov cx,0001h                    ; C/H/S = 0/0/1 (first sector)
+               mov bx,trackbuf
+               int 13h
+               pop dx
+               cli                             ; Abandon hope, ye who enter 
here
+               mov si,trackbuf
+               mov di,07C00h
+               mov cx,512                      ; Probably overkill, but should 
be safe
+               rep movsd
+               mov ss,cx
+               mov sp,7c00h
+               jmp 0:07C00h                    ; Jump to new boot sector
+
+.int18:
+               int 18h                         ; Hope this does the right 
thing...
+               jmp kaboom                      ; If we returned, oh boy...
+
+;
 ; Abort loading code
 ;
 %include "abort.inc"
@@ -1072,6 +1119,15 @@
 ;         starting with "kaboom.patch" with this part
 
 kaboom2:
+               cmp byte [gfx_ok],0
+               jz .nogfx
+               mov si,err_failed_gfx
+               xor di,di
+               mov al,1
+               call gfx_infobox
+               call gfx_done
+               call do_reboot
+.nogfx:
                mov si,err_bootfailed
                call cwritestr
                call getchar
@@ -1441,6 +1497,8 @@
 %include "strcpy.inc"           ; strcpy()
 %include "cache.inc"           ; Metadata disk cache
 
+%include "gfxboot.inc"         ; add gfx things
+
 ; -----------------------------------------------------------------------------
 ;  Begin data section
 ; -----------------------------------------------------------------------------
@@ -1473,7 +1531,8 @@
                db 'booting, and I will take your word for it.', CR, LF, 0
 err_badcfg      db 'Unknown keyword in syslinux.cfg.', CR, LF, 0
 err_noparm      db 'Missing parameter in syslinux.cfg.', CR, LF, 0
-err_noinitrd    db CR, LF, 'Could not find ramdisk image: ', 0
+err_noinitrd    db CR, LF
+err_noinitrda   db 'Could not find ramdisk image: ', 0
 err_nohighmem   db 'Not enough memory to load specified kernel.', CR, LF, 0
 err_highload    db CR, LF, 'Kernel transfer failure.', CR, LF, 0
 err_oldkernel   db 'Cannot load a ramdisk with an old kernel image.'
@@ -1483,7 +1542,9 @@
 err_a20                db CR, LF, 'A20 gate not responding!', CR, LF, 0
 err_bootfailed db CR, LF, 'Boot failed: please change disks and press '
                db 'a key to continue.', CR, LF, 0
+err_failed_gfx db 'Error reading from disk.', 0
 ready_msg      db 'Ready.', CR, LF, 0
+localboot_msg  db 'Booting from local disk...', CR, LF, 0
 crlfloading_msg        db CR, LF
 loading_msg     db 'Loading ', 0
 dotdot_msg      db '.'
--- syslinux.doc
+++ syslinux.doc
@@ -187,7 +187,7 @@
         Append nothing.  APPEND with a single hyphen as argument in a
         LABEL section can be used to override a global APPEND.
 
-  LOCALBOOT type                       [ISOLINUX, PXELINUX]
+  LOCALBOOT type                       [ISOLINUX, SYSLINUX, PXELINUX]
        On PXELINUX, specifying "LOCALBOOT 0" instead of a "KERNEL"
        option means invoking this particular label will cause a local
        disk boot instead of booting a kernel.
@@ -201,12 +201,11 @@
        UNDI or PXE stacks are, don't worry -- you don't want them,
        just specify 0.
 
-       On ISOLINUX, the "type" specifies the local drive number to
-       boot from; 0x00 is the primary floppy drive and 0x80 is the
-       primary hard drive.  The special value -1 causes ISOLINUX to
-       report failure to the BIOS, which, on recent BIOSes, should
-       mean that the next boot device in the boot sequence should be
-       activated.
+       On ISOLINUX and SYSLINUX, the "type" specifies the local drive
+       number to boot from; 0x00 is the primary floppy drive and 0x80 is
+       the primary hard drive.  The special value -1 causes them to report
+       failure to the BIOS, which, on recent BIOSes, should mean that the
+       next boot device in the boot sequence should be activated.
 
 IMPLICIT flag_val
         If flag_val is 0, do not load a kernel image unless it has been
--- loadhigh.inc
+++ loadhigh.inc
@@ -65,6 +65,11 @@
                push edi                        ; <C> Target buffer
                mov cx,ax
                xor bx,bx                       ; ES:0
+
+%ifdef WITH_GFX
+               call gfx_progress_update
+%endif
+
                call getfssec                   ; Load the data into 
xfer_buf_seg
                pop edi                         ; <C> Target buffer
                pop ecx                         ; <B> Byte count this round
--- parseconfig.inc
+++ parseconfig.inc
@@ -82,7 +82,7 @@
 ;
 ; "localboot" command (PXELINUX, ISOLINUX)
 ;
-%if IS_PXELINUX || IS_ISOLINUX
+%if IS_PXELINUX || IS_ISOLINUX || IS_SYSLINUX
 pc_localboot:  call getint
                cmp byte [VKernel],0            ; ("label" section only)
                je .err
@@ -263,7 +263,26 @@
                mov [SerialPort], word 0
                ret
 
+%ifdef WITH_GFX
+%if IS_SYSLINUX
 ;
+; like pc_setint16, but patch sector read funtion, too
+;
+pc_disksize:
+               push ax
+               call getint
+               pop si
+               jc .err
+               mov [si],bx
+               mov word [getlinsec.patch+1], getlinsec3 - getlinsec.patch - 3
+               or bx,bx
+               jz .err
+               call cache_metadata
+.err:          ret
+%endif
+%endif
+
+;
 ; "F"-key command
 ;
 pc_fkey:       push ax
diff -u syslinux-3.11/isolinux.asm syslinux-3.11/isolinux.asm
--- syslinux-3.11/isolinux.asm
+++ syslinux-3.11/isolinux.asm
@@ -1237,6 +1237,9 @@
 ; 0xFFFF in case we should execute INT 18h ("next device.")
 ;
 local_boot:
+%ifdef WITH_GFX
+               call gfx_done
+%endif
                call vgaclearmode
                lss sp,[cs:Stack]               ; Restore stack pointer
                xor dx,dx
diff -u syslinux-3.11/gfxboot.inc syslinux-3.11/gfxboot.inc
--- syslinux-3.11/gfxboot.inc
+++ syslinux-3.11/gfxboot.inc
@@ -533,17 +533,28 @@
 ;  return:     [gfx_ok] = 0
 ;
 gfx_done:
+               pusha
                cmp byte [gfx_ok],0
                jz gfx_done_90
                call far [gfx_bc_done]
                mov byte [gfx_ok],0
 
+               ; make sure the screen gets cleared
+               push ds
+               push es
+               mov ax,cs
+               mov ds,ax
+               call vgasetmode
+               pop es
+               pop ds
+
                ; reactivate 'cwritestr'
                mov al,[gfx_cwritestr_old]
                cmp al,0c3h
                jz gfx_done_90
                mov [cwritestr],al
 gfx_done_90:
+               popa
                ret
 
 
diff -u syslinux-3.11/ldlinux.asm syslinux-3.11/ldlinux.asm
--- syslinux-3.11/ldlinux.asm
+++ syslinux-3.11/ldlinux.asm
@@ -942,6 +942,9 @@
 ; 0xFFFF in case we should execute INT 18h ("next device.")
 ;
 local_boot:
+%ifdef WITH_GFX
+               call gfx_done
+%endif
                call vgaclearmode
                lss sp,[cs:Stack]               ; Restore stack pointer
                xor dx,dx
only in patch2:
unchanged:
--- syslinux-3.11.orig/pxelinux.asm
+++ syslinux-3.11/pxelinux.asm
@@ -903,6 +903,9 @@
 ; AX contains the appropriate return code.
 ;
 local_boot:
+%ifdef WITH_GFX
+               call gfx_done
+%endif
                push cs
                pop ds
                mov [LocalBootType],ax
diff -u syslinux-3.11/gfxboot.inc syslinux-3.11/gfxboot.inc
--- syslinux-3.11/gfxboot.inc
+++ syslinux-3.11/gfxboot.inc
@@ -286,7 +286,9 @@
 ; != 0 -> graphics active
 gfx_ok                 db 0
 gfx_cwritestr_old      db 0c3h         ; 'ret'
+gfx_cpio_swab          db 0
 
+                       align 4, db 0
 gfx_mem_start_seg      dw 0
 gfx_mem_end_seg                dw 0
 
@@ -917,16 +919,28 @@
                jae find_file_90
 
                lin2segofs edi,es,bx
+               mov byte [gfx_cpio_swab],0
                cmp word [es:bx],71c7h
+               jz find_file_30                 ; normal cpio record
+               cmp word [es:bx],0c771h         ; maybe byte-swapped?
                jnz find_file_90                ; no cpio record
+               mov byte [gfx_cpio_swab],1
 
-               movzx esi,word [es:bx+20]       ; file name size
+find_file_30:
+               mov ax,[es:bx+20]               ; file name size
+               call cpio_swab
+               movzx esi,ax
 
                inc si
                and si,~1                       ; align
 
-               mov ecx,[es:bx+22]              ; data size
-               rol ecx,16                      ; get word order right
+               mov ax,[es:bx+22]               ; data size, MSW
+               call cpio_swab
+               mov cx,ax
+               shl ecx,16
+               mov ax,[es:bx+24]               ; data size, LSW
+               call cpio_swab
+               mov cx,ax
 
                inc ecx
                and ecx,byte ~1                 ; align
@@ -948,6 +962,24 @@
 
 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 ;
+; byte-swap cpio data if appropriate
+;
+;  ax:         word to swap
+;
+; return:
+;  ax:         swapped if [gfx_cpio_swab], otherwise same as input
+;
+cpio_swab:
+               cmp byte [gfx_cpio_swab],0
+               jz cpio_swab_90
+               xchg ah,al
+
+cpio_swab_90:
+               ret
+
+
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+;
 ;  es:bx       file start
 ;
 ;  return:     eax:    offset to code entry

Reply via email to