summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/Makefile2
-rw-r--r--modules/gfxboot.asm929
2 files changed, 930 insertions, 1 deletions
diff --git a/modules/Makefile b/modules/Makefile
index 1ffe9ef3..a3af7b70 100644
--- a/modules/Makefile
+++ b/modules/Makefile
@@ -19,7 +19,7 @@ include $(topdir)/MCONFIG.embedded
INCLUDES = -I$(com32)/include
-BINS = pxechain.com
+BINS = pxechain.com gfxboot.com
all: $(BINS)
diff --git a/modules/gfxboot.asm b/modules/gfxboot.asm
new file mode 100644
index 00000000..464200b8
--- /dev/null
+++ b/modules/gfxboot.asm
@@ -0,0 +1,929 @@
+; ****************************************************************************
+;
+; 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 $