[syslinux] [PATCH] Gfxboot COMBOOT module

Sebastian Herbszt herbszt at gmx.de
Sun Apr 5 14:19:49 PDT 2009


This is the latest version of the gfxboot module. It's supposed to work on
all Syslinux derivatives.

I am not sure about the copyright notice and would appreciate any input.

- Sebastian

Index: syslinux-3.74-pre17-2-g2a9ddec/modules/Makefile
===================================================================
--- syslinux-3.74-pre17-2-g2a9ddec.orig/modules/Makefile
+++ syslinux-3.74-pre17-2-g2a9ddec/modules/Makefile
@@ -19,7 +19,7 @@ include $(topdir)/MCONFIG.embedded
 
 INCLUDES   = -I$(com32)/include
 
-BINS = pxechain.com
+BINS = pxechain.com gfxboot.com
 
 all: $(BINS)
 
Index: syslinux-3.74-pre17-2-g2a9ddec/modules/gfxboot.asm
===================================================================
--- /dev/null
+++ syslinux-3.74-pre17-2-g2a9ddec/modules/gfxboot.asm
@@ -0,0 +1,930 @@
+; ****************************************************************************
+;
+;  gfxboot.asm
+;
+;   Copyright 2008-2009 Sebastian Herbszt
+;
+;  This module is based on gfxboot integration patches by Steffen Winterfeldt.
+;  Some parts borrowed from Syslinux core.
+;
+;  This program is free software; you can redistribute it and/or modify
+;  it under the terms of the GNU General Public License as published by
+;  the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+;  Boston MA 02111-1307, USA; either version 2 of the License, or
+;  (at your option) any later version; incorporated herein by reference.
+;
+; ****************************************************************************
+
+		absolute 0
+pspInt20:	resw 1
+pspNextP:	resw 1
+		resb 124
+pspCmdLen:	resb 1
+pspCmdArg:	resb 127
+
+;%define DEBUG
+
+		section .text
+		org 100h
+
+_start:
+		mov ax,2
+		mov bx, msg_progname
+		int 22h
+
+		mov ax,2
+		mov bx, msg_crlf
+		int 22h
+
+		push es
+		mov ax,0ah
+		mov cl,9
+		int 22h
+		pop es
+		cmp al,32h
+		jnz not_pxelinux
+
+		mov dl,0 ; fake drive number
+		mov cl,11 ; fake sector size 2048 bytes
+
+not_pxelinux:
+		mov [derivative_id],al
+		mov [drivenumber],dl
+		mov [sectorshift],cl
+		mov ax,1
+		shl ax,cl
+		mov [sectorsize],ax
+		mov ax,trackbufsize
+		shr ax,cl
+		mov [BufSafe],ax
+
+		xor cx,cx
+		mov cl,[pspCmdLen]
+		dec cx
+		and cx,cx
+		jne continue
+
+		mov ax,2
+		mov bx, msg_usage
+		int 22h
+		ret
+continue:
+		mov di,pspCmdArg+1
+		add di,cx
+		dec di
+		std
+		mov al,' '
+		repe scasb
+		inc cx
+		cld
+		mov [pspCmdLen],cl
+		mov si,pspCmdArg+1
+		mov di,si
+		add di,cx
+		xor al,al
+		stosb
+		mov si,pspCmdArg+1
+
+; get config file name
+		mov ax,0eh
+		int 22h
+
+; open config file
+		mov si,bx ; es:bx config file name
+		mov ax,6
+		int 22h
+		jc no_config_file
+		and eax,eax
+		jz no_config_file
+		jmp got_config_file
+no_config_file:
+		push es
+		push bx
+		push cs
+		pop es
+		mov bx, msg_config_file
+		mov ax,2
+		int 22h
+		mov bx, msg_space
+		mov ax,2
+		int 22h
+		pop bx
+		pop es
+		mov ax,2
+		int 22h
+		push cs
+		pop es
+		mov bx, msg_space
+		mov ax,2
+		int 22h
+		mov bx, msg_missing
+		mov ax,2
+		int 22h
+		mov ax,2
+		mov bx, msg_crlf
+		int 22h
+		ret
+got_config_file:
+		push cs
+		pop es
+		call parse_config
+
+; get_gfx_file
+		mov ax,cs
+		add ax,2000h
+		mov word [gfx_mem_start_seg],ax
+		mov ax,[pspNextP]
+		mov word [gfx_mem_end_seg],ax
+
+		call gfx_init
+		jc error
+
+		call gfx_setup_menu
+		jc exit
+
+input:
+		call gfx_input
+		jc exit
+
+		cmp eax,1
+		jz exit
+
+		cmp eax,2
+		jz boot
+
+		jmp input
+
+boot:
+		call far [gfx_bc_done]
+		mov ax,cs
+		mov es,ax
+		mov bx,command_line
+		mov ax,3
+		int 22h
+exit:
+		call far [gfx_bc_done]
+error:
+		ret
+
+cb_table	dw cb_status		; 0
+		dw cb_fopen		; 1
+		dw cb_fread		; 2
+		dw cb_getcwd		; 3
+		dw cb_chdir		; 4
+		dw cb_readsector	; 5
+cb_len		equ ($-cb_table)/2
+
+gfx_cb:
+		push cs
+		pop ds
+
+		cmp al,cb_len
+		jae gfx_cb_error
+
+		movzx bx,al
+		add bx,bx
+		call word [bx+cb_table]
+		jmp gfx_cb_end
+gfx_cb_error:
+		mov al,0ffh
+gfx_cb_end:
+		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:
+		push ds
+		pop es
+		mov ax,6
+		mov si,fname_buf
+		int 22h
+		jnc cb_fopen_ok
+cb_fopen_failed:
+		mov al,1
+		jmp cb_fopen_end
+cb_fopen_ok:
+		mov ecx,eax
+		mov [f_handle],si
+		mov [f_size],ecx
+		xor al,al
+cb_fopen_end:
+		ret
+
+; Read next chunk
+;
+; return:
+;   edx		buffer address (linear)
+;   ecx		data length (< 64k)
+;
+cb_fread:
+		cmp dword [f_size],0
+		jz cb_fread_eof
+		push ds
+		pop es
+		mov ax,7
+		mov si,[f_handle]
+		mov bx,trackbuf
+		mov cx,[BufSafe]
+		int 22h
+		mov al,1
+		jc cb_fread_end
+		sub [f_size], ecx
+		or si,si
+		jnz cb_fread_noeof
+		and dword [f_size],0
+cb_fread_noeof:
+		mov edx,cs
+		shl edx,4
+		add edx,trackbuf
+		jmp cb_fread_ok
+cb_fread_eof:
+		xor ecx,ecx
+cb_fread_ok:
+		xor al,al
+cb_fread_end:
+		ret
+
+; Return current working directory
+;
+; return:
+;  edx		filename
+;
+cb_getcwd:
+		mov edx,cs
+		shl edx,4
+		add edx,gfx_slash
+		xor al,al
+		ret
+
+; Set current working directory
+;
+cb_chdir:
+		xor al,al
+		ret
+
+; Read sector
+;
+;   edx		sector
+;
+; return:
+;  edx		buffer (linear address)
+;
+;  Note: does not return on error!
+;
+cb_readsector:
+		push esi
+		push edi
+		push ds
+		pop es
+		mov ax,19h
+		xor esi,esi
+		xor edi,edi
+		mov cx,1
+		mov bx,trackbuf
+		int 22h
+		pop edi
+		pop esi
+		mov al,1
+		jc cb_readsector_end
+		mov edx,ds
+		shl dx,4
+		add edx,trackbuf
+		xor al,al
+cb_readsector_end:
+		ret
+
+gfx_init:
+		mov ax,0e801h
+		xor bx,bx
+		xor cx,cx
+		xor dx,dx
+		int 15h
+		jnc got_e801
+		
+		mov ax,2	
+		mov bx, msg_memory
+		int 22h
+		stc
+		ret
+
+got_e801:
+		cmp ax,3c00h
+		jb mem_below_16mb
+		shl ebx,6
+		add eax,ebx
+		
+mem_below_16mb:
+		shl eax,10
+		mov [gfx_bios_mem_size],eax
+		shr eax,20
+		cmp ax,16
+		jb skip_extended
+
+		mov word [gfx_xmem_0],88h       ; 8MB at 8MB
+		mov dword [gfx_save_area1],7f0000h      ; 8MB-64k
+
+skip_extended:
+		movzx ebx,word [gfx_mem_start_seg]
+		shl ebx,4
+
+		movzx ecx,word [gfx_mem_end_seg]
+		shl ecx,4
+
+		mov dword [gfx_mem],ebx
+		mov dword [gfx_mem0_start],ebx
+		mov dword [gfx_mem0_end],ecx
+
+		call gfx_read_file
+		jc gfx_init_end
+
+		call gfx_get_sysconfig
+
+		; align 4
+		mov eax,[gfx_mem0_start]
+		add eax,3
+		and eax,~3
+		mov [gfx_mem0_start],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 esi,cs
+		shl esi,4
+		add esi,gfx_sysconfig
+		call far [gfx_bc_init]
+
+gfx_init_end:
+		ret
+
+gfx_read_file:
+; open file
+; es:si - file name
+
+		push cs
+		pop es
+		mov ax,6
+		mov si,pspCmdArg+1
+		int 22h
+		jnc gfx_file_read
+		stc
+		ret
+
+gfx_file_read:
+; si - file handle
+; eax - length of file in bytes, or -1
+; cx - file block size
+
+		mov edx,[gfx_mem0_end]
+		sub edx,[gfx_mem0_start]
+		sub edx,0fh		; space to allow for aligning later
+		; edx: max allowed size
+
+		cmp eax,-1		; unknown file size -> set to max allowed size
+		jnz .has_size
+		mov eax,edx
+.has_size:
+		cmp eax,edx
+		jbe read_bootlogo
+
+gfx_file_too_big:
+		mov ax,2
+		mov bx,msg_bootlogo_toobig
+		int 22h
+		stc
+		ret
+
+read_bootlogo:
+		mov [file_length],eax
+		mov edi,[gfx_mem]
+
+; read file
+; si - file handle
+; es:bx - buffer
+; cx - number of blocks to read
+
+read:
+		push eax
+		mov ax,7
+		mov bx,trackbuf
+		mov cx,[BufSafe]
+		int 22h
+
+		push edi
+		push ecx
+		push si
+		push es
+
+		mov si,trackbuf
+		push edi
+		call gfx_l2so
+		pop di
+		pop es
+
+		rep movsb ; move ds:si -> es:di, length ecx
+		pop es
+		pop si
+		pop ecx
+		pop edi
+
+		pop eax
+
+		; si == 0: EOF
+		or si,si
+		jz gfx_read_done
+		add edi,ecx
+		sub eax,ecx
+		ja read
+		jmp gfx_file_too_big
+gfx_read_done:
+		sub eax,ecx
+		mov edx,[file_length]
+		sub edx,eax
+		; edx = real file size
+		mov [gfx_archive_end],edx
+		add edx,[gfx_mem0_start]
+		add edx,0fh		; for alignment
+		mov [gfx_mem0_start],edx
+
+bootlogo_read_done:
+		call find_file
+		or eax,eax
+		jnz found_bootlogo
+		stc
+		ret
+
+found_bootlogo:
+		push edi
+		push eax
+		add eax,edi
+		push dword [gfx_mem]
+		pop dword [gfx_archive_start]
+		neg al
+		and eax,byte 0fh
+		jz no_align
+		add [gfx_archive_start],eax
+
+no_align:
+		pop eax
+		pop edi
+		sub edi,[gfx_mem]
+		mov ecx,[gfx_archive_start]
+		add edi,ecx
+		mov [gfx_file],edi
+		add [gfx_archive_end],ecx
+		add eax,edi
+		shr eax,4
+		mov [gfx_bc_jt+2],ax
+		ret
+
+gfx_get_sysconfig:
+		mov ah,0
+		cmp byte [derivative_id],33h
+		jnz not_isolinux
+		mov ah,2
+not_isolinux:
+		mov al,[drivenumber]
+		mov [gfx_boot_drive],al
+		cmp al,80h	; floppy ?
+		jae not_floppy
+		mov ah,1
+not_floppy:
+		mov byte [gfx_media_type],ah
+		mov ah,[sectorshift]
+		mov byte [gfx_sector_shift],ah
+		mov ax,cs
+		mov [gfx_bootloader_seg],ax
+		ret
+
+gfx_setup_menu:
+		push es
+		push ds
+		pop es
+		
+		mov word [menu_desc+menu_ent_list],0
+		mov di,[menu_seg]
+		mov [menu_desc+menu_ent_list+2],di
+
+		mov word [menu_desc+menu_default],0
+		mov [menu_desc+menu_default+2],di
+
+		mov di,256
+		mov [menu_desc+menu_arg_list],di
+		mov di,[menu_seg]
+		mov [menu_desc+menu_arg_list+2],di
+
+		mov cx,[label_cnt]
+		mov [menu_desc+menu_entries],cx
+
+		mov cx,256*2
+		mov [menu_desc+menu_ent_size],cx
+		mov [menu_desc+menu_arg_size],cx
+
+		mov esi,ds
+		shl esi,4
+		add esi,menu_desc
+
+		call far [gfx_bc_menu_init]
+		pop es
+		ret
+
+magic_ok:
+		xor eax,eax
+		cmp dword [es:bx],0b2d97f00h    ; header.magic_id
+		jnz magic_ok_end
+		cmp byte [es:bx+4],8            ; header.version
+		jnz magic_ok_end
+		mov eax,[es:bx+8]
+magic_ok_end:
+		ret
+
+find_file:
+		mov edi,[gfx_mem]
+		push edi
+		call gfx_l2so
+		pop bx
+		pop es
+		call magic_ok
+		or eax,eax
+		jnz find_file_end
+
+find_file_loop:
+		mov ecx,[gfx_mem0_start]
+		sub ecx,26 + 12                 ; min cpio header + gfx header
+		cmp edi,ecx
+		jae find_file_end
+		push edi
+		call gfx_l2so
+		pop bx
+		pop es
+		cmp word [es:bx],71c7h
+		jnz find_file_end
+		mov ax,[es:bx+20]               ; file name size
+		movzx esi,ax
+
+		inc si
+		and si,~1                       ; align
+
+		mov eax,[es:bx+22]              ; data size
+		rol eax,16                      ; get word order right
+		mov ecx,eax
+
+		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_end
+
+		add edi,ecx
+		jmp find_file_loop
+
+find_file_end:
+		ret
+
+gfx_input:
+		mov edi,cs
+		shl edi,4
+		add edi, command_line ; buffer (0: no buffer)
+		mov ecx, max_cmd_len ; buffer size
+;		xor eax,eax ; timeout value (0: no timeout)
+		mov eax,100 ; timeout value (0: no timeout)
+
+		call far [gfx_bc_input]
+		ret
+
+gfx_l2so:
+		push eax
+		mov eax,[esp + 6]
+		shr eax,4
+		mov [esp + 8],ax
+		and word [esp + 6],byte 0fh
+		pop eax
+		ret
+
+parse_config:
+		mov [f_handle],si
+		push es
+		mov ax,cs
+		add ax,1000h
+		mov es,ax
+		mov word [menu_seg],ax
+		xor eax,eax
+		mov cx,4000h
+		mov di,0
+		rep stosd
+		pop es
+.read:
+		call skipspace
+		jz .eof
+		jc .read
+		cmp al,'#'
+		je .nextline
+		or al,20h ; convert to lower case
+		mov di,configbuf
+		stosb
+.read_loop:
+		call getc
+		jc .eof
+		cmp al,' '
+		jbe .done
+		or al,20h ; convert to lower case
+		stosb
+		jmp .read_loop
+.done:
+		call ungetc
+
+		xor ax,ax
+		stosb
+%ifdef DEBUG
+		mov ax,2
+		mov bx, configbuf
+		int 22h
+
+		mov ax,2
+		mov bx, msg_crlf
+		int 22h
+%endif
+		push si
+		push di
+		xor ecx,ecx
+		mov si,configbuf
+		mov di,label_keyword+1
+		mov cl, byte [label_keyword]
+		call memcmp
+		pop di
+		pop si
+		jz .do_label
+
+.nextline:
+		call skipline
+		jmp .read
+
+.do_label:
+		call skipspace
+		jz .eof
+		jc .noparm
+		call ungetc
+		push es
+		push di
+		mov ax,[menu_seg]
+		mov es,ax
+		mov di,[menu_off]
+		call getline
+		mov di,[menu_off]
+		add di,512
+		mov [menu_off],di
+		pop di
+		pop es
+		inc word [label_cnt]
+
+		jmp .read
+		
+.eof:
+.noparm:
+		ret
+
+skipline:
+		cmp al,10
+		je .end
+		call getc
+		jc .end
+		jmp skipline
+.end:
+		ret
+
+skipspace:
+.loop:
+		call getc
+		jc .eof
+		cmp al,0Ah
+		je .eoln
+		cmp al,' '
+		jbe .loop
+		ret
+.eof:
+		cmp al,al
+		stc
+		ret
+.eoln:
+		add al,0FFh
+		ret
+
+ungetc:
+		mov byte [ungetc_cnt],1
+		mov byte [ungetcdata],al
+		ret
+
+getc:
+		cmp byte [ungetc_cnt],1
+		jne .noungetc
+		mov byte [ungetc_cnt],0
+		mov al,[ungetcdata]
+		clc
+		ret
+.noungetc:
+		sub word [bufbytes],1
+		jc .get_data
+		mov si,trackbuf
+		add si,[bufdata]
+		mov al,[si]
+		inc word [bufdata]
+		clc
+		ret
+.get_data:
+		mov si,[f_handle]
+		and si,si
+		jz .empty
+		mov ax,7
+		mov bx,trackbuf
+		mov cx,[BufSafe]
+		int 22h
+		mov word [bufdata],0
+		jc .empty
+		mov [f_handle],si
+		mov [bufbytes],cx
+		jmp getc
+.empty:
+		mov word [f_handle],0
+		mov word [bufbytes],0
+		stc
+		ret
+
+getline:
+		call skipspace
+		jz .eof
+		jc .eoln
+		call ungetc
+.loop:
+		call getc
+		jc .ret
+		cmp al,' '
+		jna .ctrl
+.store:
+		stosb
+		jmp .loop
+.ctrl:
+		cmp al,10
+		je .ret
+		mov al,' '
+		jmp .store
+.eoln:
+		clc
+		jmp .ret
+.eof:
+		stc
+.ret:
+		xor al,al
+		stosb
+		ret
+		
+
+memcmp:
+		push si
+		push di
+		push ax
+.loop:
+		mov al,[si]
+		mov ah,[di]
+		inc si
+		inc di
+		cmp al,ah
+		loope .loop
+		pop ax
+		pop di
+		pop si
+		ret
+
+		section .data
+derivative_id		db 0
+drivenumber		db 0
+sectorshift		db 0
+sectorsize		dw 0
+trackbufsize		equ 16384
+trackbuf		times trackbufsize db 0
+BufSafe			dw 0
+file_length		dd 0
+
+bufbytes		dw 0
+bufdata			dw 0
+configbuf		times trackbufsize db 0
+ungetc_cnt		db 0
+ungetcdata		db 0
+label_keyword		db 6,'label',0
+label_cnt		dw 0
+
+msg_progname		db 'gfxboot: ',0
+msg_config_file		db 'Configuration file',0
+msg_missing		db 'missing',0
+msg_usage		db 'Usage: gfxboot.com <bootlogo>',0dh,0ah,0
+msg_memory		db 'Could not detect available memory size',0dh,0ah,0
+msg_bootlogo_toobig	db 'bootlogo file too big',0dh,0ah,0
+msg_pxelinux		db 'pxelinux is not supported',0dh,0ah,0
+msg_unknown_file_size	db 'unknown file size',0dh,0ah,0
+msg_space		db ' ',0
+msg_crlf		db 0dh,0ah,0
+
+f_handle		dw 0
+f_size			dd 0
+fname_buf		times 64 db 0
+fname_buf_len		equ $ - fname_buf
+gfx_slash		db '/', 0
+db0			db 0
+max_cmd_len  equ 2047
+command_line		times max_cmd_len+2 db 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		times sizeof_menu_desc db 0
+menu_seg		dw 0
+menu_off		dw 0
+
+gfx_mem_start_seg	dw 0
+gfx_mem_end_seg		dw 0
+
+			align 4, db 0
+gfx_mem			dd 0		; linear address
+gfx_save_area1		dd 0		; 64k
+gfx_save_area1_used	db 0		; != 0 if area1 is in use
+
+; 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
+
+; system config data (52 bytes)
+gfx_sysconfig		equ $
+gfx_bootloader		db 1			;  0: boot loader type (0: lilo, 1: syslinux, 2: grub)
+gfx_sector_shift	db 9			;  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 (bitmask)
+						;     0: SHIFT pressed
+						;     1: skip gfxboot
+						;     2: skip monitor detection
+gfx_sysconfig_size	db gfx_sysconfig_end-gfx_sysconfig	;  4: size of sysconfig data
+gfx_boot_drive		db 0			;  5: BIOS boot drive
+gfx_callback		dw gfx_cb		;  6: offset to callback handler
+gfx_bootloader_seg	dw 0			;  8: code/data segment used by bootloader; must follow gfx_callback
+gfx_reserved_1		dw 0			; 10
+gfx_user_info_0		dd 0			; 12: data for info box
+gfx_user_info_1		dd 0			; 16: data for info box
+gfx_bios_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_xmem_2		dw 0			; 28: extended mem area 2
+gfx_xmem_3		dw 0			; 20: extended mem area 3
+gfx_file		dd 0			; 32: start of gfx file
+gfx_archive_start	dd 0			; 36: start of cpio archive
+gfx_archive_end		dd 0			; 40: end of cpio archive
+gfx_mem0_start		dd 0			; 44: low free memory start
+gfx_mem0_end		dd 0			; 48: low free memory end
+gfx_sysconfig_end	equ $
+




More information about the Syslinux mailing list