diff options
-rw-r--r-- | modules/Makefile | 2 | ||||
-rw-r--r-- | modules/gfxboot.asm | 929 |
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 $ |