--- Makefile +++ Makefile @@ -146,15 +146,16 @@ $(PERL) genhash.pl < keywords > kwdhash.gen # Standard rule for {isolinux,isolinux-debug}.bin -iso%.bin: iso%.asm kwdhash.gen version.gen +iso%.bin: iso%.asm kwdhash.gen version.gen gfxboot.inc $(NASM) $(NASMOPT) -f bin -DDATE_STR="'$(DATE)'" -DHEXDATE="$(HEXDATE)" \ -DMAP=$(@:.bin=.map) -l $(@:.bin=.lsr) -o $@ $< $(PERL) lstadjust.pl $(@:.bin=.lsr) $(@:.bin=.map) $(@:.bin=.lst) $(PERL) checksumiso.pl $@ $(PERL) checkov.pl $(@:.bin=.map) $@ + -./add_crc $@ # Standard rule for {ldlinux,pxelinux,extlinux}.bin -%.bin: %.asm kwdhash.gen version.gen +%.bin: %.asm kwdhash.gen version.gen gfxboot.inc $(NASM) $(NASMOPT) -f bin -DDATE_STR="'$(DATE)'" -DHEXDATE="$(HEXDATE)" \ -DMAP=$(@:.bin=.map) -l $(@:.bin=.lsr) -o $@ $< $(PERL) lstadjust.pl $(@:.bin=.lsr) $(@:.bin=.map) $(@:.bin=.lst) --- 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). + + 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 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 + + 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). + --- abort.inc +++ abort.inc @@ -21,6 +21,11 @@ ; abort_check: let the user abort with or ; abort_check: +%ifdef WITH_GFX + ; don't + cmp byte [gfx_ok],0 + jnz .ret1 +%endif call pollchar jz .ret1 pusha --- 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$/.lsr/; + +open F, $list; + +while() { + 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); + +@x = 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; + --- com32/libutil/get_key.c +++ com32/libutil/get_key.c @@ -42,6 +42,10 @@ #include #include +#ifndef CLK_TCK +# define CLK_TCK __sysconf(2) +#endif + struct keycode { int code; int seqlen; --- com32/modules/cpuid.c +++ com32/modules/cpuid.c @@ -254,7 +254,7 @@ static int smp_scan_config (unsigned long base, unsigned long length) { - unsigned long *bp = base; + unsigned long *bp = (unsigned long *) base; struct intel_mp_floating *mpf; // printf("Scan SMP from %p for %ld bytes.\n", bp,length); --- com32/samples/keytest.c +++ com32/samples/keytest.c @@ -25,6 +25,10 @@ #include /* Provided by libutil */ #include +#ifndef CLK_TCK +# define CLK_TCK __sysconf(2) +#endif + static void cooked_keys(void) { int key; --- conio.inc +++ conio.inc @@ -49,6 +49,14 @@ ; Assumes CS == DS == ES. ; get_msg_file: +%ifdef WITH_GFX + ; don't load if graphics code is active + cmp byte [gfx_ok],0 + jz .nogfx + jmp close +.nogfx: +%endif + mov byte [TextAttribute],07h ; Default grey on white mov byte [DisplayMask],07h ; Display text in all modes call msg_initvars --- doc/syslinux.txt +++ doc/syslinux.txt @@ -230,7 +230,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. @@ -244,12 +244,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 --- gfxboot.inc +++ gfxboot.inc @@ -0,0 +1,1355 @@ + 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 +; +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +; != 0 -> graphics active +gfx_ok db 0 +gfx_cwritestr_old db 0c3h ; 'ret' +gfx_cpio_swab db 0 +gfx_cd_changed db 0 + +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_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 +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 (52 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 (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 $ + +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 + mov al,[DriveNumber] + 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 + + mov [gfx_bootloader_seg],cs + + 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: + + test byte [gfx_failsafe],2 + jnz gfx_init_80 + + call highmemsize + + ; setup extended memory areas + pusha + mov eax,[HighMemSize] + mov [gfx_bios_mem_size],eax + mov eax,[VKernelEnd] + 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 + + mov dword [gfx_save_area1],7f0000h ; 8MB-64k +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_mem0_start],ebx + mov dword [gfx_mem0_end],ecx + + call gfx_read_file + cmp byte [gfx_ok],0 + jz near gfx_init_90 + + 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 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 esi,cs + shl esi,4 + add esi,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 + mov byte [cwritestr],0c3h + + 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: + push ax + 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: + pop ax + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +gfx_input: + cmp byte [gfx_ok],0 + jz gfx_input_90 + cmp byte [gfx_save_area1_used],0 + jz gfx_input_10 + ; recover saved menu layout, gfxboot has references into it + pushad + mov esi,[gfx_save_area1] + mov edi,gfx_menu_seg << 4 + mov ecx,10000h + call bcopy + popad +gfx_input_10: + 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: + push es + 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 + + mov esi,[HighMemSize] + jmp gfx_setup_menu_20 +gfx_setup_menu_10: + mov di,VKernelBuf + call rllunpack + + ; count only non empty entries + cmp byte [VKernelBuf],0 + jz gfx_setup_menu_20 + + inc word [menu_desc+menu_entries] + + push esi + mov si,VKernelBuf + mov di,KernelCName + push di + call unmangle_name + pop di + pop esi + + 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 esi,[VKernelEnd] + ja 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 + + mov esi,[HighMemSize] + jmp gfx_setup_menu_60 +gfx_setup_menu_30: + mov di,VKernelBuf + call rllunpack + + ; count only non empty entries + cmp byte [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 esi + + mov si,VKernelBuf + mov di,KernelCName + 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 esi + + push ds + pop es + + mov ax,[menu_desc+menu_arg_size] + add [menu_desc+menu_arg_list],ax + +gfx_setup_menu_60: + cmp esi,[VKernelEnd] + ja 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 esi,ds + shl esi,4 + add esi,menu_desc + + call far [gfx_bc_menu_init] + + ; save menu structure, gfxboot uses references into it + mov edi,[gfx_save_area1] + or edi,edi + jz gfx_setup_menu_90 + mov esi,gfx_menu_seg << 4 + mov ecx,10000h + call bcopy + mov byte [gfx_save_area1_used],1 + +gfx_setup_menu_90: + pop es + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +gfx_infobox: + pushad + cmp byte [gfx_ok],0 + jz gfx_infobox_90 + mov ecx,ds + shl ecx,4 + movzx esi,si + movzx edi,di + or si,si + jz gfx_infobox_20 + add esi,ecx +gfx_infobox_20: + or di,di + jz gfx_infobox_30 + add edi,ecx +gfx_infobox_30: + call far [gfx_bc_infobox_init] + xor edi,edi + xor eax,eax + 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 edi,ds + shl edi,4 + add edi,gfx_password_buf + mov ecx,32 + xor eax,eax + call far [gfx_bc_input] + mov esi,ds + shl esi,4 + add esi,gfx_password_buf + call far [gfx_bc_password_done] + jnc gfx_password_90 + mov esi,ds + shl esi,4 + add esi,gfx_msg_wrong_password + xor edi,edi + mov al,0 + call far [gfx_bc_infobox_init] + xor edi,edi + xor eax,eax + 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 [gfx_archive_end],edx + mov eax,[gfx_mem0_start] + lea eax,[eax+edx+0fh] ; add space for alignment + cmp eax,[gfx_mem0_end] ; max. length + ja near gfx_read_file_90 + mov [gfx_mem0_start],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] + 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 + + 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_mem0_start] + 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 + 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 + +find_file_30: + mov ax,[es:bx+20] ; file name size + call cpio_swab + movzx esi,ax + + inc si + and si,~1 ; align + + mov eax,[es:bx+22] ; data size + call cpio_swab + rol eax,16 ; get word order right + call cpio_swab + 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_90 + + add edi,ecx + jmp find_file_20 + +find_file_90: + ret + + +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +; +; 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 +; +; 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],8 ; 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_archive_start] + neg al + and eax,byte 0fh + jz align_it_90 + add [gfx_archive_start],eax + mov esi,[gfx_mem] + mov ebx,[gfx_mem0_start] + 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_0 + call cwritestr + + mov dx,2 + mov si,failsafe_msg_1 + call ask_question + + test byte [gfx_failsafe],2 + jnz ask_user_90 + + mov dx,4 + mov si,failsafe_msg_2 + call ask_question + +ask_user_90: + + popad + ret + + +; si: text +; dh: 'yes'-mask +; dl: 'no'-mask +ask_question: + push dx + call cwritestr + mov si,failsafe_msg_q + call cwritestr + pop dx + +ask_question_20: + push dx + mov ah,0 + int 16h + pop dx + + cmp al,13 + jnz ask_question_30 + mov al,'y' +ask_question_30: + or al,20h ; force lower case + + cmp al,'y' + jz ask_question_40 + cmp al,'n' + jnz ask_question_20 + or byte [gfx_failsafe],dl + jmp ask_question_50 +ask_question_40: + or byte [gfx_failsafe],dh +ask_question_50: + + mov si,failsafe_key + mov [si],al + call cwritestr + + ret + +failsafe_msg_q db ' (y/n)? y', 8, 0 + +failsafe_msg_0 db 13, 10, 10, 10, 0 +failsafe_msg_1 db 'Load boot graphics', 0 +failsafe_msg_2 db 'Detect display size', 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,config_name - 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 + --- isolinux.asm +++ isolinux.asm @@ -19,6 +19,10 @@ ; **************************************************************************** %define IS_ISOLINUX 1 + +%define WITH_GFX 1 +; %define DEBUG_DISKIO + %include "head.inc" ; @@ -70,6 +74,8 @@ real_mode_seg equ 2000h xfer_buf_seg equ 1000h ; Bounce buffer for I/O to high mem comboot_seg equ real_mode_seg ; COMBOOT image loading zone +gfx_menu_seg equ 3000h ; temporary storage to setup menu +first_free_seg equ 4000h ; end of isolinux used memory ; ; File structure. This holds the information for each currently open file. @@ -259,6 +265,21 @@ mov [FirstSecSum],edi mov [DriveNumber],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 try a BIOS update.', 13, 10, 0 + align 4 +csum_value dd 0 +bios_ok: + %ifdef DEBUG_MESSAGES mov si,startup_msg call writemsg @@ -283,6 +304,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 @@ -303,6 +327,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 @@ -427,6 +453,9 @@ %endif jmp all_read ; Jump to main code +%if 0 + ; doesn't work anyway, see above + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -618,6 +647,7 @@ mov si,trysbm_msg call writemsg jmp .found_drive ; Pray that this works... +%endif fatal_error: mov si,nothing_msg @@ -694,10 +724,17 @@ ; getlinsec: mov si,dapa ; Load up the DAPA - mov [si+4],bx - mov bx,es - mov [si+6],bx 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 + 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] @@ -724,15 +761,78 @@ ; 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] call int13 + 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 - dec byte [RetryCount] + +%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 mov al,[RetryCount] @@ -774,6 +874,17 @@ ; kaboom: RESET_STACK_AND_SEGS AX + + 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 @@ -825,6 +936,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 MaxTransfer dw 32 ; Max sectors per transfer @@ -882,6 +996,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 @@ -907,10 +1024,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 @@ -931,6 +1053,9 @@ call crlf %endif .no_isolinux_dir: + ret + +get_fs_struct_done: ; ; Locate the configuration file @@ -1096,6 +1221,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 @@ -1113,7 +1241,7 @@ xor dh,dh push dx xor ax,ax ; Reset drive - call xint13 + int 13h ; we don't care about errors here... mov ax,0201h ; Read one sector mov cx,0001h ; C/H/S = 0/0/1 (first sector) mov bx,trackbuf @@ -1488,6 +1616,9 @@ %include "rawcon.inc" ; Console I/O w/o using the console functions %include "adv.inc" ; Auxillary Data Vector +%include "gfxboot.inc" ; add gfx things + + ; ----------------------------------------------------------------------------- ; Begin data section ; ----------------------------------------------------------------------------- @@ -1499,6 +1630,7 @@ default_len equ ($-default_str) boot_dir db '/boot' ; /boot/isolinux isolinux_dir db '/isolinux', 0 +zb 64 config_name db 'isolinux.cfg', 0 err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0 --- keywords +++ keywords @@ -42,3 +42,5 @@ f10 f11 f12 +gfxboot +disksize --- keywords.inc +++ keywords.inc @@ -90,8 +90,15 @@ %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 --- layout.inc +++ layout.inc @@ -88,7 +88,11 @@ section .uibss nobits align=16 follows=.adv ; Normal bss... +%if IS_ISOLINUX + section .bss1 nobits align=16 follows=.bss2 +%else section .bss1 nobits align=16 follows=.uibss +%endif ; Reserve space for stack section .stack nobits align=16 start=STACK_START --- ldlinux.asm +++ ldlinux.asm @@ -24,6 +24,9 @@ %ifndef IS_MDSLINUX %define IS_SYSLINUX 1 %endif + +%define WITH_GFX 1 + %include "head.inc" ; @@ -82,6 +85,8 @@ cache_seg equ 2000h ; 64K area for metadata cache xfer_buf_seg equ 1000h ; Bounce buffer for I/O to high mem comboot_seg equ real_mode_seg ; COMBOOT image loading zone +gfx_menu_seg equ 4000h ; temporary storage to setup menu +first_free_seg equ 5000h ; end of syslinux used memory ; ; File structure. This holds the information for each currently open file. @@ -357,6 +362,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 ; @@ -906,6 +913,48 @@ ; %include "ui.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: +%ifdef WITH_GFX + call gfx_done +%endif + 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... + ; ; allocate_file: Allocate a file structure ; @@ -1126,6 +1175,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 cmp byte [kaboom.again+1],18h ; INT 18h version? @@ -1530,6 +1588,8 @@ %include "cache.inc" ; Metadata disk cache %include "adv.inc" ; Auxillary Data Vector +%include "gfxboot.inc" ; add gfx things + ; ----------------------------------------------------------------------------- ; Begin data section ; ----------------------------------------------------------------------------- @@ -1539,6 +1599,8 @@ db 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 +localboot_msg db 'Booting from local disk...', CR, LF, 0 syslinux_cfg1 db '/boot' ; /boot/syslinux/syslinux.cfg syslinux_cfg2 db '/syslinux' ; /syslinux/syslinux.cfg syslinux_cfg3 db '/' ; /syslinux.cfg --- loadhigh.inc +++ loadhigh.inc @@ -47,7 +47,12 @@ .read_loop: and si,si ; If SI == 0 then we have end of file jz .eof +%ifdef WITH_GFX + cmp byte [gfx_ok],0 + jnz .no_message +%endif call bx +.no_message: push bx ; Pausebird function push eax ; Total bytes to transfer @@ -63,7 +68,15 @@ push edi ; Target buffer mov cx,ax xor bx,bx ; ES:0 + +%ifdef WITH_GFX + call gfx_progress_update +%endif + + push dx call getfssec ; Load the data into xfer_buf_seg + ; getfssec destroys dx! + pop dx pop edi ; Target buffer pop ecx ; Byte count this round push ecx ; Byte count this round --- parsecmd.inc +++ parsecmd.inc @@ -107,6 +107,14 @@ FKeyName resb MAX_FKEYS*FILENAME_MAX ; File names for F-key help KernelCNameLen resw 1 ; Length of unmangled kernel name InitRDCNameLen resw 1 ; Length of unmangled initrd name + +%if IS_ISOLINUX +%ifdef DEBUG_MESSAGES +; we need to rearrange memory a bit to make isolinux-debug.bin fit + section .bss +%endif +%endif + %if IS_SYSLINUX KernelName resb FILENAME_MAX+1 ; Mangled name for kernel KernelCName resb FILENAME_MAX+2 ; Unmangled kernel name --- parseconfig.inc +++ parseconfig.inc @@ -81,7 +81,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 @@ -286,6 +286,25 @@ 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 ; --- pxelinux.asm +++ pxelinux.asm @@ -846,6 +846,9 @@ ; AX contains the appropriate return code. ; local_boot: +%ifdef WITH_GFX + call gfx_done +%endif push cs pop ds mov [LocalBootType],ax --- runkernel.inc +++ runkernel.inc @@ -206,6 +206,15 @@ pop ds sub si,cmd_line_here mov [CmdLineLen],si ; Length including final null + +%ifdef WITH_GFX + mov eax,[KernelSects] + mov esi,ds + shl esi,4 + add esi,KernelCName + call gfx_progress_init +%endif + ; ; Now check if we have a large kernel, which needs to be loaded high ; @@ -312,6 +321,19 @@ jz nk_noinitrd call parse_load_initrd nk_noinitrd: + +%ifdef WITH_GFX + call gfx_progress_done + + cmp byte [gfx_cd_changed],0 + jz .no_cd_change + mov al,6 + xor si,si + xor di,di + call gfx_infobox +.no_cd_change: +%endif + ; ; Abandon hope, ye that enter here! We do no longer permit aborts. ; @@ -320,6 +342,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 @@ -552,6 +578,34 @@ .got_start: push si + +%ifdef WITH_GFX + cmp byte [si],'+' + jnz .got_start_10 + mov byte [cs:gfx_cd_changed],1 + inc si + push es + push ds + push si + push cs + pop es + mov cx,100h + mov di,trackbuf + push di + rep movsb + mov byte [es:di],0 + pop si + xor di,di + mov al,5 ; ask for cd change + push cs + pop ds + call gfx_infobox + pop si + pop ds + pop es +.got_start_10: +%endif + mov di,InitRD ; Target buffer for mangled name call mangle_name call loadinitrd @@ -645,6 +699,20 @@ ret .notthere: + +%ifdef WITH_GFX + cmp byte [gfx_ok],0 + jz .nogfx + mov si,InitRDCName + xor di,di + mov al,2 + call gfx_infobox + call gfx_progress_done + mov si,no_msg + jmp abort_load +.nogfx: +%endif + mov si,err_noinitrd call cwritestr mov si,InitRDCName @@ -653,7 +721,21 @@ 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,0 + call gfx_infobox + call gfx_progress_done + mov si,no_msg + jmp abort_load +.nogfx: +%endif + + mov si,err_nohighmem jmp abort_load ret @@ -666,7 +748,8 @@ ready_msg db 'ready.', CR, LF, 0 err_oldkernel db 'Cannot load a ramdisk with an old kernel image.' db 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 boot_image db 'BOOT_IMAGE=' --- ui.inc +++ ui.inc @@ -44,6 +44,11 @@ .no_bootonce: +%ifdef WITH_GFX + ; build gfx menu + call gfx_setup_menu +%endif + ; ; Check whether or not we are supposed to display the boot prompt. ; @@ -57,6 +62,21 @@ 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 edi,ds + shl edi,4 + add edi,command_line + mov ecx,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 @@ -323,9 +343,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 @@ -343,7 +375,7 @@ mov al, [VKernelBuf+vk_type] mov [KernelType], al -%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 @@ -421,6 +453,19 @@ 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 si + xor di,di + mov al,2 + call gfx_infobox + mov si,no_msg + jmp abort_load +.nogfx: +%endif + call cwritestr pop si ; KernelCName call cwritestr --- gfxboot.inc +++ gfxboot.inc @@ -417,8 +417,10 @@ 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_0], 81h ; 1MB at 8MB mov word [gfx_xmem_1],0a1h ; 1MB at 10MB + mov word [gfx_xmem_2],0c1h ; 1MB at 12MB + mov word [gfx_xmem_3],0e1h ; 1MB at 14MB mov dword [gfx_save_area1],7f0000h ; 8MB-64k gfx_init_40: --- gfxboot.inc +++ gfxboot.inc @@ -333,11 +333,12 @@ ; 0: SHIFT pressed ; 1: skip gfxboot ; 2: skip monitor detection + ; 3: leave a20 untouched 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_serial_port dw 0 ; 10: syslinux initialized serial port from 'serial' option 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) @@ -366,6 +367,8 @@ ; gfx_get_sysconfig: push ax + mov ax,[SerialPort] + mov [gfx_serial_port],ax mov al,[DriveNumber] mov [gfx_boot_drive],al @@ -407,6 +410,13 @@ test byte [gfx_failsafe],2 jnz gfx_init_80 + test byte [gfx_failsafe],8 + jnz gfx_init_20 + pushad + call enable_a20 + popad +gfx_init_20: + call highmemsize ; setup extended memory areas @@ -417,10 +427,16 @@ 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_0], 88h ; 8MB at 8MB (a20 enabled) + + test byte [gfx_failsafe],8 + jz gfx_init_30 + mov word [gfx_xmem_0], 81h ; 1MB at 8MB (a20 disabled) mov word [gfx_xmem_1],0a1h ; 1MB at 10MB mov word [gfx_xmem_2],0c1h ; 1MB at 12MB mov word [gfx_xmem_3],0e1h ; 1MB at 14MB +gfx_init_30: mov dword [gfx_save_area1],7f0000h ; 8MB-64k gfx_init_40: @@ -1103,6 +1119,10 @@ test byte [gfx_failsafe],2 jnz ask_user_90 + mov dx,8 + mov si,failsafe_msg_3 + call ask_question + mov dx,4 mov si,failsafe_msg_2 call ask_question @@ -1156,6 +1176,7 @@ failsafe_msg_0 db 13, 10, 10, 10, 0 failsafe_msg_1 db 'Load boot graphics', 0 failsafe_msg_2 db 'Detect display size', 0 +failsafe_msg_3 db 'Enable A20', 0 failsafe_key db 0, 13, 10, 0