diff --git a/syslinux-3.82-gfxboot.diff b/syslinux-3.82-gfxboot.diff index af7c54c..bb706af 100644 --- a/syslinux-3.82-gfxboot.diff +++ b/syslinux-3.82-gfxboot.diff @@ -1,223 +1,3 @@ -diff --git a/core/abort.inc b/core/abort.inc -index 5b16b9d..cc59fa7 100644 ---- a/core/abort.inc -+++ b/core/abort.inc -@@ -24,6 +24,10 @@ - ; assumes CS == DS - ; - dot_pause: -+ push ax -+ mov al,5 -+ call [comboot_hook] -+ pop ax - push si - mov si,dot_msg - call writestr_qchk -@@ -63,6 +67,8 @@ abort_check: - abort_load: - mov bx,error_or_command - abort_load_chain: -+ mov al,80h -+ call [comboot_hook] ; may not return - RESET_STACK_AND_SEGS AX - call writestr ; Expects SI -> error msg - -diff --git a/core/comboot.inc b/core/comboot.inc -index cdba16d..ee3fd77 100644 ---- a/core/comboot.inc -+++ b/core/comboot.inc -@@ -96,24 +96,23 @@ is_comboot_image: - shl ax,6 ; Kilobytes -> paragraphs - mov word [es:02h],ax - --%ifndef DEPEND --%if real_mode_seg != comboot_seg --%error "This code assumes real_mode_seg == comboot_seg" --%endif --%endif - ; Copy the command line from high memory -+ push word real_mode_seg -+ pop ds - mov si,cmd_line_here - mov cx,125 ; Max cmdline len (minus space and CR) - mov di,081h ; Offset in PSP for command line - mov al,' ' ; DOS command lines begin with a space - stosb - --.loop: es lodsb -+.loop: lodsb - and al,al - jz .done - stosb - loop .loop - .done: -+ push cs -+ pop ds - - mov al,0Dh ; CR after last character - stosb -@@ -963,6 +962,45 @@ comapi_shufraw: - mov ecx,P_ECX - jmp shuffle_and_boot_raw - -+ -+; -+; INT 22h AX=0025h Set current working directory -+; -+%if IS_ISOLINUX -+comapi_setcwd: -+ mov si,P_BX -+ mov di,TmpDirName -+ mov cx,FILENAME_MAX -+ mov ds,P_ES -+.copy: -+ lodsb -+ stosb -+ or al,al -+ loopnz .copy -+ push cs -+ pop ds -+ stc -+ jnz .err -+ mov di,TmpDirName -+ call setcwd -+.err: -+ ret -+%else -+comapi_setcwd equ comapi_err -+%endif -+ -+ -+; -+; INT 22h AX=0026h Read filesystem meta data -+; -+%if IS_ISOLINUX -+comapi_mount: -+; call iso_mount -+ ret -+%else -+comapi_mount equ comapi_err -+%endif -+ - section .data - - %macro int21 2 -@@ -970,6 +1008,88 @@ comapi_shufraw: - dw %2 - %endmacro - -+ -+; -+; INT 22h AX=0027h Run command, return on error -+; -+; Terminates the COMBOOT program and executes the command line in -+; ES:BX as if it had been entered by the user. -+; CS:SI: comboot callback (via far call) -+; EDI kernel load address -+; -+comapi_run2: -+ push word P_CS -+ push word P_SI -+ pop dword [comboot_far] -+ push dword P_EDI -+ pop dword [KernelStart] -+ mov ds,P_ES -+ mov si,P_BX -+ mov di,command_line -+ call strcpy -+ push cs -+ pop ds -+ push cs -+ pop es -+ mov [comboot_sp_save],sp ; save stack pointer -+ mov word [comboot_hook],comboot_hook_entry -+ or byte [QuietBoot],2 -+ jmp load_kernel ; Run a new kernel -+ -+comapi_run2_cont: -+ mov word [comboot_hook],comboot_hook_nop -+ mov sp,[comboot_sp_save] ; fix stack pointer -+ and byte [QuietBoot],~2 -+ clc -+ ret -+ -+; -+; Callback function used at various places during kernel/initrd loading. -+; -+; The function either returns or continues at comapi_run2_cont. -+; -+; AL: -+; bit 7: 0/1 return/don't return -+; bit 0-6: function code -+; 0: abort kernel/initrd loading -+; 1: kernel/initrd not found -+; 2: kernel corrupt -+; 3: out of memory (while initrd loading) -+; 4: progress start -+; 5: progress increment -+; 6: progress end: kernel loaded, stop gfxboot -+; -+comboot_hook_entry: -+ pushad -+ push gs -+ push fs -+ push es -+ push ds -+ call far [comboot_far] -+ pop ds -+ pop es -+ pop fs -+ pop gs -+ popad -+ pushad -+ and al,7fh -+ cmp al,6 -+ jnz .notlast -+ push es -+ mov si,DOSSaveVectors -+ mov di,4*20h -+ mov cx,20h -+ push word 0 -+ pop es -+ rep movsd ; Restore DOS-range vectors -+ pop es -+.notlast: -+ popad -+ test al,80h -+ jnz comapi_run2_cont -+comboot_hook_nop: -+ ret -+ - int21_table: - int21 00h, comboot_return - int21 01h, comboot_getkey -@@ -1022,8 +1142,15 @@ int22_table: - dw comapi_closedir ; 0022 close directory - dw comapi_shufsize ; 0023 query shuffler size - dw comapi_shufraw ; 0024 cleanup, shuffle and boot raw -+ dw comapi_setcwd ; 0025 set current working directory -+ dw comapi_mount ; 0026 read fs structures (aka mount) -+ dw comapi_run2 ; 0027 like 0003, but return on error - int22_count equ ($-int22_table)/2 - -+comboot_sp_save dw 0 -+comboot_hook dw comboot_hook_nop -+comboot_far dd 0 -+ - APIKeyWait db 0 - APIKeyFlag db 0 - -@@ -1042,8 +1169,9 @@ feature_flags_len equ ($-feature_flags) - err_notdos db ': attempted DOS system call INT ',0 - err_comlarge db 'COMBOOT image too large.', CR, LF, 0 - -- section .bss1 -+ section .bss2 - alignb 4 - DOSErrTramp resd 33 ; Error trampolines -+TmpDirName resb FILENAME_MAX - ConfigName resb FILENAME_MAX - CurrentDirName resb FILENAME_MAX diff --git a/core/isolinux.asm b/core/isolinux.asm index 2627c2d..a0910fb 100644 --- a/core/isolinux.asm @@ -393,16 +173,30 @@ index 2627c2d..a0910fb 100644 ; ----------------------------------------------------------------------------- ; Common modules ; ----------------------------------------------------------------------------- -diff --git a/core/layout.inc b/core/layout.inc -index 8c2e248..ca95d2b 100644 ---- a/core/layout.inc -+++ b/core/layout.inc -@@ -123,4 +123,4 @@ real_mode_seg equ cache_seg + 1000h - pktbuf_seg equ cache_seg ; PXELINUX packet buffers - %endif +diff --git a/core/abort.inc b/core/abort.inc +index 5b16b9d..cc59fa7 100644 +--- a/core/abort.inc ++++ b/core/abort.inc +@@ -24,6 +24,10 @@ + ; assumes CS == DS + ; + dot_pause: ++ push ax ++ mov al,5 ++ call [comboot_hook] ++ pop ax + push si + mov si,dot_msg + call writestr_qchk +@@ -63,6 +67,8 @@ abort_check: + abort_load: + mov bx,error_or_command + abort_load_chain: ++ mov al,80h ++ call [comboot_hook] ; may not return + RESET_STACK_AND_SEGS AX + call writestr ; Expects SI -> error msg --comboot_seg equ real_mode_seg ; COMBOOT image loading zone -+comboot_seg equ real_mode_seg + 1000h ; COMBOOT image loading zone diff --git a/core/loadhigh.inc b/core/loadhigh.inc index 8ff9da1..91061fc 100644 --- a/core/loadhigh.inc @@ -417,18 +211,9 @@ index 8ff9da1..91061fc 100644 section .data diff --git a/core/runkernel.inc b/core/runkernel.inc -index 8bfc8b8..0cd2488 100644 +index 8bfc8b8..f458fc7 100644 --- a/core/runkernel.inc +++ b/core/runkernel.inc -@@ -165,7 +165,7 @@ opt_mem: - ret - - opt_quiet: -- mov byte [QuietBoot],1 -+ or byte [QuietBoot],1 - ret - - %if IS_PXELINUX @@ -228,6 +228,8 @@ new_kernel: mov [LoadFlags],al @@ -438,15 +223,6 @@ index 8bfc8b8..0cd2488 100644 mov si,loading_msg call writestr_qchk mov si,KernelCName ; Print kernel name part of -@@ -257,7 +259,7 @@ read_kernel: - mov ecx,8000h ; 32K - sub ecx,esi ; Number of bytes to copy - add esi,(real_mode_seg << 4) ; Pointer to source -- mov edi,100000h ; Copy to address 100000h -+ mov edi,[KernelStart] ; Copy to kernel address - - call bcopy ; Transfer to high memory - @@ -319,6 +321,9 @@ load_initrd: ; call abort_check ; Last chance!! @@ -457,30 +233,7 @@ index 8bfc8b8..0cd2488 100644 mov si,ready_msg call writestr_qchk -@@ -426,7 +431,7 @@ setup_move: - - mov eax,10000h ; Target address of low kernel - stosd -- mov eax,100000h ; Where currently loaded -+ mov eax,[KernelStart] ; Where currently loaded - stosd - neg eax - add eax,[KernelEnd] -@@ -434,9 +439,13 @@ setup_move: - inc cx - - mov bx,9000h ; Revised real mode segment -+ jmp .loading_initrd - - .loading_high: -+ mov eax,[KernelStart] -+ mov [fs:su_code32start],eax - -+.loading_initrd: - cmp word [InitRDPtr],0 ; Did we have an initrd? - je .no_initrd - -@@ -489,6 +498,8 @@ old_kernel: +@@ -489,6 +494,8 @@ old_kernel: xor ax,ax cmp word [InitRDPtr],ax ; Old kernel can't have initrd je .load @@ -489,7 +242,7 @@ index 8bfc8b8..0cd2488 100644 mov si,err_oldkernel jmp abort_load .load: -@@ -613,6 +624,8 @@ loadinitrd: +@@ -613,6 +620,8 @@ loadinitrd: ret .notthere: @@ -498,28 +251,8 @@ index 8bfc8b8..0cd2488 100644 mov si,err_noinitrd call writestr mov si,InitRDCName -@@ -625,7 +638,7 @@ loadinitrd: - ; assumes CS == DS - ; - writestr_qchk: -- test byte [QuietBoot],01h -+ test byte [QuietBoot],03h - jz writestr - ret - -@@ -680,4 +693,9 @@ KernelVersion resw 1 ; Kernel protocol version - ; - InitRDPtr resw 1 ; Pointer to initrd= option in command line - LoadFlags resb 1 ; Loadflags from kernel --QuietBoot resb 1 ; Set if a quiet boot is requested -+ -+ section .data -+QuietBoot db 0 ; Set if a quiet boot is requested -+ alignz 4 -+KernelStart dd 100000h -+ diff --git a/core/ui.inc b/core/ui.inc -index 1b40717..2bc56a1 100644 +index 1b40717..be4f385 100644 --- a/core/ui.inc +++ b/core/ui.inc @@ -468,6 +468,8 @@ bad_kernel: @@ -543,7 +276,85 @@ index 1b40717..2bc56a1 100644 jmp abort_load ; -@@ -591,7 +596,7 @@ kernel_good: +diff --git a/core/comboot.inc b/core/comboot.inc +index cdba16d..1a1dbfe 100644 +--- a/core/comboot.inc ++++ b/core/comboot.inc +@@ -96,24 +96,23 @@ is_comboot_image: + shl ax,6 ; Kilobytes -> paragraphs + mov word [es:02h],ax + +-%ifndef DEPEND +-%if real_mode_seg != comboot_seg +-%error "This code assumes real_mode_seg == comboot_seg" +-%endif +-%endif + ; Copy the command line from high memory ++ push word real_mode_seg ++ pop ds + mov si,cmd_line_here + mov cx,125 ; Max cmdline len (minus space and CR) + mov di,081h ; Offset in PSP for command line + mov al,' ' ; DOS command lines begin with a space + stosb + +-.loop: es lodsb ++.loop: lodsb + and al,al + jz .done + stosb + loop .loop + .done: ++ push cs ++ pop ds + + mov al,0Dh ; CR after last character + stosb +diff --git a/core/layout.inc b/core/layout.inc +index 8c2e248..ca95d2b 100644 +--- a/core/layout.inc ++++ b/core/layout.inc +@@ -123,4 +123,4 @@ real_mode_seg equ cache_seg + 1000h + pktbuf_seg equ cache_seg ; PXELINUX packet buffers + %endif + +-comboot_seg equ real_mode_seg ; COMBOOT image loading zone ++comboot_seg equ real_mode_seg + 1000h ; COMBOOT image loading zone +diff --git a/core/runkernel.inc b/core/runkernel.inc +index f458fc7..f6ed644 100644 +--- a/core/runkernel.inc ++++ b/core/runkernel.inc +@@ -165,7 +165,7 @@ opt_mem: + ret + + opt_quiet: +- mov byte [QuietBoot],1 ++ or byte [QuietBoot],1 + ret + + %if IS_PXELINUX +@@ -634,7 +634,7 @@ loadinitrd: + ; assumes CS == DS + ; + writestr_qchk: +- test byte [QuietBoot],01h ++ test byte [QuietBoot],03h + jz writestr + ret + +@@ -689,4 +689,6 @@ KernelVersion resw 1 ; Kernel protocol version + ; + InitRDPtr resw 1 ; Pointer to initrd= option in command line + LoadFlags resb 1 ; Loadflags from kernel +-QuietBoot resb 1 ; Set if a quiet boot is requested ++ ++ section .data ++QuietBoot db 0 ; Set if a quiet boot is requested +diff --git a/core/ui.inc b/core/ui.inc +index be4f385..2bc56a1 100644 +--- a/core/ui.inc ++++ b/core/ui.inc +@@ -596,7 +596,7 @@ kernel_good: ; xor ax,ax mov [InitRDPtr],ax @@ -552,61 +363,141 @@ index 1b40717..2bc56a1 100644 %if IS_PXELINUX mov [KeepPXE],al %endif -diff --git a/doc/comboot.txt b/doc/comboot.txt -index f5fefda..9fe7f28 100644 ---- a/doc/comboot.txt -+++ b/doc/comboot.txt -@@ -955,3 +955,12 @@ AX=0024h [3.80] Cleanup, shuffle and boot, raw version - with read/write data segments, matching the respective code - segment. For mode 0, B=0 and the limits will be 64K, for mode - 1, B=1 and the limits will be 4 GB. -+ -+ -+AX=0025h [3.84] Set current working directory -+ Input: AX 00025h -+ ES:BX null-terminated directory name string -+ Output: None -+ -+ Sets the current working directory. For SYSLINUX, ISOLINUX, -+ and PXELINUX, this will be an absolute path. -diff --git a/modules/gfxboot.asm b/modules/gfxboot.asm -index 5c7b118..7d1693f 100644 ---- a/modules/gfxboot.asm -+++ b/modules/gfxboot.asm -@@ -179,6 +179,16 @@ input: - jmp input +diff --git a/core/runkernel.inc b/core/runkernel.inc +index f6ed644..286c9c8 100644 +--- a/core/runkernel.inc ++++ b/core/runkernel.inc +@@ -259,7 +259,7 @@ read_kernel: + mov ecx,8000h ; 32K + sub ecx,esi ; Number of bytes to copy + add esi,(real_mode_seg << 4) ; Pointer to source +- mov edi,100000h ; Copy to address 100000h ++ mov edi,[KernelStart] ; Copy to kernel address - boot: -+ mov ax,cs -+ mov es,ax -+ mov bx,command_line -+ mov si,syslinux_hook -+ mov edi,8 << 20 ; at 8MB -+ mov ax,27h -+ int 22h -+ jnc input -+ -+ ; syslinux variant without function 27h - call far [gfx_bc_done] - mov ax,cs - mov es,ax -@@ -190,12 +200,77 @@ exit: - error: - ret + call bcopy ; Transfer to high memory + +@@ -431,7 +431,7 @@ setup_move: + + mov eax,10000h ; Target address of low kernel + stosd +- mov eax,100000h ; Where currently loaded ++ mov eax,[KernelStart] ; Where currently loaded + stosd + neg eax + add eax,[KernelEnd] +@@ -439,9 +439,13 @@ setup_move: + inc cx + + mov bx,9000h ; Revised real mode segment ++ jmp .loading_initrd + + .loading_high: ++ mov eax,[KernelStart] ++ mov [fs:su_code32start],eax + ++.loading_initrd: + cmp word [InitRDPtr],0 ; Did we have an initrd? + je .no_initrd + +@@ -692,3 +696,5 @@ LoadFlags resb 1 ; Loadflags from kernel + + section .data + QuietBoot db 0 ; Set if a quiet boot is requested ++ alignz 4 ++KernelStart dd 100000h +diff --git a/core/comboot.inc b/core/comboot.inc +index 1a1dbfe..ee3fd77 100644 +--- a/core/comboot.inc ++++ b/core/comboot.inc +@@ -962,6 +962,45 @@ comapi_shufraw: + mov ecx,P_ECX + jmp shuffle_and_boot_raw -+sh_table: dw sh_abort ; 0 -+ dw sh_not_found ; 1 -+ dw sh_broken ; 2 -+ dw sh_out_of_mem ; 3 -+ dw sh_progress_start ; 4 -+ dw sh_progress_inc ; 5 -+ dw sh_progress_end ; 6 -+sh_len equ ($-sh_table)/2 + +; -+; Callback function used at various places in syslinux. ++; INT 22h AX=0025h Set current working directory +; -+; Can modify all regs & sregs. ++%if IS_ISOLINUX ++comapi_setcwd: ++ mov si,P_BX ++ mov di,TmpDirName ++ mov cx,FILENAME_MAX ++ mov ds,P_ES ++.copy: ++ lodsb ++ stosb ++ or al,al ++ loopnz .copy ++ push cs ++ pop ds ++ stc ++ jnz .err ++ mov di,TmpDirName ++ call setcwd ++.err: ++ ret ++%else ++comapi_setcwd equ comapi_err ++%endif ++ ++ ++; ++; INT 22h AX=0026h Read filesystem meta data ++; ++%if IS_ISOLINUX ++comapi_mount: ++; call iso_mount ++ ret ++%else ++comapi_mount equ comapi_err ++%endif ++ + section .data + + %macro int21 2 +@@ -969,6 +1008,88 @@ comapi_shufraw: + dw %2 + %endmacro + ++ ++; ++; INT 22h AX=0027h Run command, return on error ++; ++; Terminates the COMBOOT program and executes the command line in ++; ES:BX as if it had been entered by the user. ++; CS:SI: comboot callback (via far call) ++; EDI kernel load address ++; ++comapi_run2: ++ push word P_CS ++ push word P_SI ++ pop dword [comboot_far] ++ push dword P_EDI ++ pop dword [KernelStart] ++ mov ds,P_ES ++ mov si,P_BX ++ mov di,command_line ++ call strcpy ++ push cs ++ pop ds ++ push cs ++ pop es ++ mov [comboot_sp_save],sp ; save stack pointer ++ mov word [comboot_hook],comboot_hook_entry ++ or byte [QuietBoot],2 ++ jmp load_kernel ; Run a new kernel ++ ++comapi_run2_cont: ++ mov word [comboot_hook],comboot_hook_nop ++ mov sp,[comboot_sp_save] ; fix stack pointer ++ and byte [QuietBoot],~2 ++ clc ++ ret ++ ++; ++; Callback function used at various places during kernel/initrd loading. ++; ++; The function either returns or continues at comapi_run2_cont. +; +; AL: +; bit 7: 0/1 return/don't return @@ -619,183 +510,2125 @@ index 5c7b118..7d1693f 100644 +; 5: progress increment +; 6: progress end: kernel loaded, stop gfxboot +; -+syslinux_hook: -+ push cs ++comboot_hook_entry: ++ pushad ++ push gs ++ push fs ++ push es ++ push ds ++ call far [comboot_far] + pop ds -+ and al,7fh -+ cmp al,sh_len -+ jae .end -+ movzx bx,al -+ add bx,bx -+ call word [bx+sh_table] -+.end: -+ retf -+ -+sh_abort: -+ ret -+ -+sh_not_found: -+ ret -+ -+sh_broken: -+ ret -+ -+sh_out_of_mem: -+ ret -+ -+sh_progress_start: -+ call far [gfx_bc_progress_init] -+ ret -+ -+sh_progress_inc: -+ mov eax,10000h ; chunk size -+ call far [gfx_bc_progress_update] -+ ret -+ -+sh_progress_end: -+ call far [gfx_bc_progress_done] -+ call far [gfx_bc_done] -+ 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 -+ dw cb_mount ; 6 - cb_len equ ($-cb_table)/2 - - gfx_cb: -@@ -291,16 +366,25 @@ cb_fread_end: - ; edx filename - ; - cb_getcwd: -- mov edx,cs -+ mov ax,1fh -+ int 22h -+ mov edx,es -+ movzx ebx,bx - shl edx,4 -- add edx,gfx_slash -+ add edx,ebx - xor al,al - ret - - ; Set current working directory - ; - cb_chdir: -- xor al,al -+ push cs + pop es -+ mov bx,fname_buf -+ mov ax,25h -+ int 22h -+ mov al,0 -+ adc al,0 ++ pop fs ++ pop gs ++ popad ++ pushad ++ and al,7fh ++ cmp al,6 ++ jnz .notlast ++ push es ++ mov si,DOSSaveVectors ++ mov di,4*20h ++ mov cx,20h ++ push word 0 ++ pop es ++ rep movsd ; Restore DOS-range vectors ++ pop es ++.notlast: ++ popad ++ test al,80h ++ jnz comapi_run2_cont ++comboot_hook_nop: ++ ret ++ + int21_table: + int21 00h, comboot_return + int21 01h, comboot_getkey +@@ -1021,8 +1142,15 @@ int22_table: + dw comapi_closedir ; 0022 close directory + dw comapi_shufsize ; 0023 query shuffler size + dw comapi_shufraw ; 0024 cleanup, shuffle and boot raw ++ dw comapi_setcwd ; 0025 set current working directory ++ dw comapi_mount ; 0026 read fs structures (aka mount) ++ dw comapi_run2 ; 0027 like 0003, but return on error + int22_count equ ($-int22_table)/2 + ++comboot_sp_save dw 0 ++comboot_hook dw comboot_hook_nop ++comboot_far dd 0 ++ + APIKeyWait db 0 + APIKeyFlag db 0 + +@@ -1041,8 +1169,9 @@ feature_flags_len equ ($-feature_flags) + err_notdos db ': attempted DOS system call INT ',0 + err_comlarge db 'COMBOOT image too large.', CR, LF, 0 + +- section .bss1 ++ section .bss2 + alignb 4 + DOSErrTramp resd 33 ; Error trampolines ++TmpDirName resb FILENAME_MAX + ConfigName resb FILENAME_MAX + CurrentDirName resb FILENAME_MAX +diff --git a/core/comboot.inc b/core/comboot.inc +index ee3fd77..a11b15b 100644 +--- a/core/comboot.inc ++++ b/core/comboot.inc +@@ -1034,12 +1034,14 @@ comapi_run2: + mov [comboot_sp_save],sp ; save stack pointer + mov word [comboot_hook],comboot_hook_entry + or byte [QuietBoot],2 ++ mov byte [comboot_run2_active],1 + jmp load_kernel ; Run a new kernel + + comapi_run2_cont: + mov word [comboot_hook],comboot_hook_nop + mov sp,[comboot_sp_save] ; fix stack pointer + and byte [QuietBoot],~2 ++ mov byte [comboot_run2_active],0 + clc ret - ; Read sector -@@ -334,6 +418,17 @@ cb_readsector: - cb_readsector_end: - ret +@@ -1150,6 +1152,7 @@ int22_count equ ($-int22_table)/2 + comboot_sp_save dw 0 + comboot_hook dw comboot_hook_nop + comboot_far dd 0 ++comboot_run2_active db 0 -+; Read filesystem meta data. + APIKeyWait db 0 + APIKeyFlag db 0 +diff --git a/core/ui.inc b/core/ui.inc +index 2bc56a1..59b5724 100644 +--- a/core/ui.inc ++++ b/core/ui.inc +@@ -379,9 +379,13 @@ vk_check: + push word real_mode_seg + pop es + mov di,cmd_line_here ++ ; append line already included in this case ++ cmp byte [comboot_run2_active],0 ++ jnz .no_append_copy + mov si,VKernelBuf+vk_append + mov cx,[VKernelBuf+vk_appendlen] + rep movsb ++.no_append_copy: + mov [CmdLinePtr],di ; Where to add rest of cmd + pop es + mov di,KernelName +diff --git a/core/comboot.inc b/core/comboot.inc +index a11b15b..b40c4ae 100644 +--- a/core/comboot.inc ++++ b/core/comboot.inc +@@ -1067,6 +1067,7 @@ comboot_hook_entry: + push fs + push es + push ds ++ mov ecx,[KernelSize] + call far [comboot_far] + pop ds + pop es +diff --git a/core/ui.inc b/core/ui.inc +index 59b5724..02c17ff 100644 +--- a/core/ui.inc ++++ b/core/ui.inc +@@ -633,6 +633,7 @@ kernel_good: + ; At this point, EAX contains the size of the kernel, SI contains + ; the file handle/cluster pointer, and ECX contains the extension (if any.) + ; ++ mov [KernelSize],eax + movzx di,byte [KernelType] + add di,di + jmp [kerneltype_table+di] +diff --git a/doc/comboot.txt b/doc/comboot.txt +index f5fefda..f4ea31b 100644 +--- a/doc/comboot.txt ++++ b/doc/comboot.txt +@@ -955,3 +955,32 @@ AX=0024h [3.80] Cleanup, shuffle and boot, raw version + with read/write data segments, matching the respective code + segment. For mode 0, B=0 and the limits will be 64K, for mode + 1, B=1 and the limits will be 4 GB. ++ ++ ++AX=0025h [3.84] Set current working directory ++ Input: AX 00025h ++ ES:BX null-terminated directory name string ++ Output: None ++ ++ Sets the current working directory. For SYSLINUX, ISOLINUX, ++ and PXELINUX, this will be an absolute path. ++ ++ ++AX=0026h [3.84] Read file system metadata [ISOLINUX] ++ Input: AX 00026h ++ Output: None ++ ++ Reads filesystem data (e.g. after a CDROM change). ++ ++ ++AX=0027h [3.84] Run command ++ Input: AX 0027h ++ ES:BX null-terminated command string ++ SI comboot callback function (called via far call) ++ EDI kernel load address ++ Output: Does not return if the kernel loads correctly. ++ ++ Executes the command line as if it had been entered by the user. ++ Note that this function does return (with CF = 0) if there are ++ problems or the user aborted the load. Else it terminates the ++ COMBOOT program and starts the kernel. +diff --git a/modules/Makefile b/modules/Makefile +index 80eb995..65661a4 100644 +--- a/modules/Makefile ++++ b/modules/Makefile +@@ -19,6 +19,11 @@ include $(topdir)/MCONFIG.embedded + + INCLUDES = -I$(com32)/include + ++CFLAGS_COM = -O2 -Wall -Wno-pointer-sign -fomit-frame-pointer -m32 -march=i386 \ ++ -fno-align-functions -fno-align-labels -fno-align-jumps -fno-align-loops \ ++ -fno-builtin -nostdinc -I . ++ASMFLAGS_COM = -O99 -felf ++ + BINS = pxechain.com gfxboot.com poweroff.com + + all: $(BINS) +@@ -49,6 +54,15 @@ $(LIB): $(LIBOBJS) + %.ppm.gz: %.png + $(PNGTOPNM) $< | gzip -9 > $@ + ++libio.o: libio.asm ++ nasm $(ASMFLAGS_COM) -o $@ -l $*.lst $< ++ ++gfxboot.o: gfxboot.c libio.h ++ $(CC) -g $(CFLAGS_COM) -c -o $@ $< ++ ++gfxboot.com: gfxboot.o libio.o ++ ld -M -Tcom.ld -o $@ $^ >$*.map ++ + tidy dist: + rm -f *.o *.a *.lst *.elf *.map .*.d + +diff --git a/modules/com.ld b/modules/com.ld +new file mode 100644 +index 0000000..a98f9aa +--- /dev/null ++++ b/modules/com.ld +@@ -0,0 +1,16 @@ ++/* ++ linker script for DOS program (.COM) ++ */ ++ ++OUTPUT_FORMAT("binary") ++OUTPUT_ARCH(i386) ++SEARCH_DIR(".") ++ENTRY(_start) ++SECTIONS ++{ ++ .init 0x100 : { *(.init) } ++ .text : { *(.text) } ++ .rodata : { *(.rodata*) } ++ .data : { *(.data) } ++ .bss : { __bss_start = .; *(.bss) } ++} +diff --git a/modules/gfxboot.c b/modules/gfxboot.c +new file mode 100644 +index 0000000..6b0d300 +--- /dev/null ++++ b/modules/gfxboot.c +@@ -0,0 +1,898 @@ ++/* ++ * ++ * gfxboot.c ++ * ++ * A comboot program to load gfxboot graphics. ++ * ++ * It is based on work done by Sebastian Herbszt in gfxboot.asm. ++ * ++ * Copyright (c) 2009 Steffen Winterfeldt. ++ * ++ * 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. ++ * ++ */ ++ ++#include ++ ++#define ID_SYSLINUX 0x31 ++#define ID_PXELINUX 0x32 ++#define ID_ISOLINUX 0x33 ++#define ID_EXTLINUX 0x34 ++ ++#define MAX_CONFIG_LINE_LEN 2048 ++#define MAX_CMDLINE_LEN 1024 ++ ++#define GFX_BC_INIT 0 ++#define GFX_BC_DONE 1 ++#define GFX_BC_INPUT 2 ++#define GFX_BC_MENU_INIT 3 ++#define GFX_BC_INFOBOX_INIT 4 ++#define GFX_BC_INFOBOX_DONE 5 ++#define GFX_BC_PROGRESS_INIT 6 ++#define GFX_BC_PROGRESS_DONE 7 ++#define GFX_BC_PROGRESS_UPDATE 8 ++#define GFX_BC_PROGRESS_LIMIT 9 // unused ++#define GFX_BC_PASSWORD_INIT 10 ++#define GFX_BC_PASSWORD_DONE 11 ++ ++// for now, static values ++#define MENU_LABEL_SIZE 128 ++#define MENU_ARG_SIZE 512 ++#define MENU_ENTRY_SIZE (MENU_LABEL_SIZE + MENU_ARG_SIZE) ++// entry 0 is reserved for the default entry ++#define MAX_MENU_ENTRIES (0x10000 / MENU_ENTRY_SIZE) ++ ++ ++typedef struct { ++ uint16_t handle; ++ uint16_t block_size; ++ int file_size; // file size (-1: unknown) ++ uint32_t buf; // must be block_size ++ unsigned buf_size; // in block_size units ++ unsigned data_len; // valid bytes in buf ++ unsigned buf_idx; // read pos in buffer ++} fd_t; ++ ++ ++// gfx config data (52 bytes) ++typedef struct __attribute__ ((packed)) { ++ uint8_t bootloader; // 0: boot loader type (0: lilo, 1: syslinux, 2: grub) ++ uint8_t sector_shift; // 1: sector shift ++ uint8_t media_type; // 2: media type (0: disk, 1: floppy, 2: cdrom) ++ uint8_t failsafe; // 3: turn on failsafe mode (bitmask) ++ // 0: SHIFT pressed ++ // 1: skip gfxboot ++ // 2: skip monitor detection ++ uint8_t sysconfig_size; // 4: size of sysconfig data ++ uint8_t boot_drive; // 5: BIOS boot drive ++ uint16_t callback; // 6: offset to callback handler ++ uint16_t bootloader_seg; // 8: code/data segment used by bootloader; must follow gfx_callback ++ uint16_t reserved_1; // 10 ++ uint32_t user_info_0; // 12: data for info box ++ uint32_t user_info_1; // 16: data for info box ++ uint32_t bios_mem_size; // 20: BIOS memory size (in bytes) ++ uint16_t xmem_0; // 24: extended mem area 0 (start:size in MB; 12:4 bits) ++ uint16_t xmem_1; // 26: extended mem area 1 ++ uint16_t xmem_2; // 28: extended mem area 2 ++ uint16_t xmem_3; // 30: extended mem area 3 ++ uint32_t file; // 32: start of gfx file ++ uint32_t archive_start; // 36: start of cpio archive ++ uint32_t archive_end; // 40: end of cpio archive ++ uint32_t mem0_start; // 44: low free memory start ++ uint32_t mem0_end; // 48: low free memory end ++} gfx_config_t; ++ ++ ++// menu description (18 bytes) ++typedef struct __attribute__ ((packed)) { ++ uint16_t entries; ++ uint32_t default_entry; // seg:ofs ++ uint32_t label_list; // seg:ofs ++ uint16_t label_size; ++ uint32_t arg_list; // seg:ofs ++ uint16_t arg_size; ++} menu_t; ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++// global file descriptor, implicitly used by read(), getc(), fgets() ++fd_t fd; ++ ++gfx_config_t gfx_config; ++menu_t menu; ++ ++struct { ++ uint32_t jmp_table[12]; ++ uint16_t code_seg; ++ char fname_buf[64]; ++} gfx; ++ ++unsigned comboot, comboot_len; ++unsigned io_buf, io_buf_len; ++unsigned menu_buf, menu_buf_len; ++unsigned freemem, freemem_len; ++ ++int timeout; ++ ++char cmdline[MAX_CMDLINE_LEN]; ++char current_label[64]; ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ ++int open(char *name); ++int open32(uint32_t name); ++int read(void *buf, int size); ++int read32(uint32_t buf, int size); ++int getc(void); ++char *fgets(char *s, int size); ++ ++int strlen(char *s); ++int strcmp(char *s1, char *s2); ++char *skip_spaces(char *s); ++char *skip_nonspaces(char *s); ++void chop_line(char *s); ++ ++int atoi(char *s); ++ ++uint32_t get_config_file_name32(void); ++int read_config_file(void); ++ ++unsigned magic_ok(uint32_t buf); ++unsigned find_file(uint32_t buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len); ++ ++int gfx_init(char *file); ++void gfx_done(void); ++int gfx_input(void); ++int gfx_menu_init(void); ++ ++void gfx_infobox32(int type, uint32_t str1, uint32_t str2); ++void gfx_infobox(int type, char *str1, char *str2); ++ ++void boot(void); ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++int main(int argc, char **argv) ++{ ++ x86regs_t r; ++ uint8_t syslinux_id; ++ int menu_index; ++ ++ r.eax = 0x0a; // Get Derivative-Specific Information ++ r.ecx = 9; ++ x86int(0x22, &r); ++ syslinux_id = (uint8_t) r.eax; ++ gfx_config.sector_shift = (uint8_t) r.ecx; ++ gfx_config.boot_drive = (uint8_t) r.edx; ++ ++ // define our memory layout ++ // all must be at least 16 bytes aligned ++ ++ // 64k comboot code ++ comboot = comboot_seg() << 4; ++ comboot_len = 0x10000; ++ ++ // 16k file io buffer ++ io_buf = comboot + comboot_len; ++ io_buf_len = 0x4000; ++ ++ // 64k for parsed menu data ++ menu_buf = io_buf + io_buf_len; ++ menu_buf_len = 0x10000; ++ ++ // use remaining mem for gfx core ++ freemem = menu_buf + menu_buf_len; ++ // comboot api passes low memory end at address 2 ++ freemem_len = ((*(uint16_t *) 2) << 4) - freemem; ++ ++ ++ gfx_config.bootloader = 1; ++ gfx_config.sysconfig_size = sizeof gfx_config; ++ gfx_config.bootloader_seg = comboot >> 4; ++ ++ // not gfx_cb() directly, we need a wrapper ++ gfx_config.callback = (uint32_t) _gfx_cb; ++ ++ if(syslinux_id == ID_PXELINUX) { ++ gfx_config.sector_shift = 11; ++ gfx_config.boot_drive = 0; ++ } ++ ++ if(argc != 2) { ++ printf("Usage: gfxboot.com \n"); ++ return 0; ++ } ++ ++ if(read_config_file()) { ++ printf("Error reading config file\n"); ++ return 0; ++ } ++ ++ if(gfx_init(argv[1])) { ++ printf("Error setting up gfxboot\n"); ++ return 0; ++ } ++ ++ gfx_menu_init(); ++ ++ for(;;) { ++ menu_index = gfx_input(); ++ ++ // abort gfx, return to text mode prompt ++ if(menu_index == -1) { ++ gfx_done(); ++ break; ++ } ++ ++ // get label name, is needed later for messages etc. ++ memcpy(current_label, cmdline, sizeof current_label); ++ current_label[sizeof current_label - 1] = 0; ++ *skip_nonspaces(current_label) = 0; ++ ++ // does not return if it succeeds ++ boot(); ++ } ++ ++ return 0; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++// ++// return: ++// 0: ok, -1: error ++// ++int open32(uint32_t name) ++{ ++ x86regs_t r; ++ ++ fd.handle = 0; ++ fd.data_len = fd.buf_idx = 0; ++ ++ r.esi = name & 0xf; ++ r.eax = 0x06; // Open file ++ r.es = name >> 4; ++ x86int(0x22, &r); ++ ++ fd.block_size = r.ecx; ++ fd.file_size = r.eax; ++ ++ if( ++ (r.eflags & X86_CF) || ++ !fd.file_size || !fd.block_size || fd.block_size > io_buf_len ++ ) return -1; ++ ++ fd.handle = r.esi; ++ ++ fd.buf = io_buf; ++ fd.buf_size = io_buf_len / fd.block_size; ++ ++ // printf("block size = 0x%x, file size = %d\n", fd.block_size, fd.file_size); ++ ++ return 0; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++// ++// return: ++// 0: ok, -1: error ++// ++int open(char *name) ++{ ++ return open32((uint32_t) name + comboot); ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++// ++// Note: buf is 32bit address ++// ++int read32(uint32_t buf, int size) ++{ ++ x86regs_t r; ++ int i, len = 0; ++ ++ while(size) { ++ i = fd.data_len - fd.buf_idx; ++ ++ if(i > 0) { ++ i = i < size ? i : size; ++ memcpy32(buf, fd.buf + fd.buf_idx, i); ++ len += i; ++ buf += i; ++ size -= i; ++ fd.buf_idx += i; ++ } ++ ++ if(!size || !fd.handle) break; ++ ++ r.eax = 0x07; // Read file ++ r.ecx = fd.buf_size; ++ r.ebx = 0; ++ r.es = fd.buf >> 4; ++ r.esi = fd.handle; ++ x86int(0x22, &r); ++ fd.handle = r.esi; ++ fd.data_len = r.ecx; ++ fd.buf_idx = 0; ++ } ++ ++ return len; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++int read(void *buf, int size) ++{ ++ return read32((uint32_t) buf + comboot, size); ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++int getc() ++{ ++ char buf[1]; ++ ++ return read(buf, 1) ? *buf : EOF; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++char *fgets(char *s, int size) ++{ ++ char *buf = s; ++ int c = EOF; ++ ++ while(size--) { ++ c = getc(); ++ if(c == EOF) break; ++ *buf++ = c; ++ if(c == 0x0a) break; ++ } ++ ++ *buf = 0; ++ ++ return c == EOF && s == buf ? 0 : s; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++int strlen(char *s) ++{ ++ char *s0 = s + 1; ++ ++ while(*s++); ++ ++ return s - s0; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++int strcmp(char *s1, char *s2) ++{ ++ while(*s1 && *s1 == *s2) s1++, s2++; ++ ++ return (uint8_t) *s1 - (uint8_t) *s2; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++char *skip_spaces(char *s) ++{ ++ while(*s && (*s == ' ' || *s == '\t')) s++; ++ ++ return s; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++char *skip_nonspaces(char *s) ++{ ++ while(*s && *s != ' ' && *s != '\t') s++; ++ ++ return s; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++void chop_line(char *s) ++{ ++ int i = strlen(s); ++ ++ if(!i) return; ++ ++ while(--i >= 0) { ++ if(s[i] == ' ' || s[i] == '\t' || s[i] == '\n') { ++ s[i] = 0; ++ } ++ else { ++ break; ++ } ++ } ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++int atoi(char *s) ++{ ++ int i = 0, sign = 1; ++ ++ if(*s == '-') s++, sign = -1; ++ if(*s == '+') s++; ++ ++ while(*s >= '0' && *s <= '9') { ++ i = 10 * i + *s++ - '0'; ++ } ++ ++ return sign * i; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++// ++// return: ++// config file name (32 bit address) ++// ++uint32_t get_config_file_name32() ++{ ++ x86regs_t r; ++ ++ r.eax = 0x0e; // Get configuration file name ++ x86int(0x22, &r); ++ ++ return (r.es << 4) + (uint16_t) r.ebx; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++// Read and parse syslinux config file. ++// ++// return: ++// 0: ok, 1: error ++// ++int read_config_file(void) ++{ ++ char *s, *t, buf[MAX_CONFIG_LINE_LEN]; ++ unsigned u; ++ int menu_idx = 0; ++ ++ // clear memory before we start ++ memset32(menu_buf, 0, menu_buf_len); ++ ++ if(open32(get_config_file_name32()) == -1) return 1; ++ ++ while((s = fgets(buf, sizeof buf))) { ++ chop_line(s); ++ s = skip_spaces(s); ++ if(!*s || *s == '#') continue; ++ t = skip_nonspaces(s); ++ if(*t) *t++ = 0; ++ t = skip_spaces(t); ++ ++ if(!strcmp(s, "timeout")) { ++ timeout = atoi(t); ++ } ++ ++ if(!strcmp(s, "default")) { ++ u = strlen(t); ++ if(u > MENU_LABEL_SIZE - 1) u = MENU_LABEL_SIZE - 1; ++ memcpy32(menu_buf, comboot + (uint32_t) t, u); ++ } ++ ++ if(!strcmp(s, "label")) { ++ menu_idx++; ++ if(menu_idx < MAX_MENU_ENTRIES) { ++ u = strlen(t); ++ if(u > MENU_LABEL_SIZE - 1) u = MENU_LABEL_SIZE - 1; ++ memcpy32( ++ menu_buf + menu_idx * MENU_LABEL_SIZE, ++ comboot + (uint32_t) t, ++ u ++ ); ++ } ++ } ++ ++ if(!strcmp(s, "append")) { ++ if(menu_idx < MAX_MENU_ENTRIES) { ++ u = strlen(t); ++ if(u > MENU_ARG_SIZE - 1) u = MENU_ARG_SIZE - 1; ++ memcpy32( ++ menu_buf + menu_idx * MENU_ARG_SIZE + MAX_MENU_ENTRIES * MENU_LABEL_SIZE, ++ comboot + (uint32_t) t, ++ u ++ ); ++ } ++ } ++ } ++ ++ menu.entries = menu_idx; ++ menu.label_size = MENU_LABEL_SIZE; ++ menu.arg_size = MENU_ARG_SIZE; ++ menu.default_entry = ((menu_buf >> 4) << 16) + (menu_buf & 0xf); ++ u = menu_buf + MENU_LABEL_SIZE; ++ menu.label_list = ((u >> 4) << 16) + (u & 0xf); ++ u = menu_buf + MAX_MENU_ENTRIES * MENU_LABEL_SIZE + MENU_ARG_SIZE; ++ menu.arg_list = ((u >> 4) << 16) + (u & 0xf); ++ ++ return 0; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++// Check header and return code start offset. ++// ++// Note: buf is 32bit address ++// ++unsigned magic_ok(uint32_t buf) ++{ ++ if( ++ _mem32(buf) == 0x0b2d97f00 && /* magic id */ ++ (_mem8(buf + 4) == 8) /* version 8 */ ++ ) { ++ return _mem32(buf + 8); ++ } ++ ++ return 0; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++// ++// Search cpio archive for gfx file. ++// ++// Note: buf is 32bit address ++// ++unsigned find_file(uint32_t buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len) ++{ ++ unsigned i, fname_len, code_start = 0; ++ ++ *gfx_file_start = 0; ++ ++ for(i = 0; i < len;) { ++ if((len - i) >= 0x1a && _mem16(buf + i) == 0x71c7) { ++ fname_len = _mem16(buf + i + 20); ++ *file_len = _mem16(buf + i + 24) + (_mem16(buf + i + 22) << 16); ++ i += 26 + fname_len; ++ i = ((i + 1) & ~1); ++ if((code_start = magic_ok(buf + i))) { ++ *gfx_file_start = i; ++ return code_start; ++ } ++ i += *file_len; ++ i = ((i + 1) & ~1); ++ } ++ else { ++ break; ++ } ++ } ++ ++ return code_start; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++void gfx_cb(x86regs_t *r) ++{ ++ uint8_t f_nr = r->eax; ++ ++ switch(f_nr) { ++ case 0: // cb_status ++ // edx = filename buffer (64 bytes) ++ r->edx = comboot + (uint32_t) gfx.fname_buf; ++ r->eax = 0; ++ // printf("<0x%x, %p + 0x%x>", r->edx, gfx.fname_buf, comboot); ++ break; ++ ++ case 1: // cb_fopen ++ // file name in gfx.fname_buf ++ // al = 0: ok, 1: file not found ++ // ecx = file length (al = 0) ++ if(open(gfx.fname_buf) == -1) { ++ r->eax = 1; ++ } ++ else { ++ r->eax = 0; ++ r->ecx = fd.file_size; ++ } ++ break; ++ ++ case 2: // cb_fread ++ // edx = buffer address (linear) ++ // ecx = data length (< 64k) ++ if(!fd.handle) { ++ r->eax = r->ecx = 0; ++ break; ++ } ++ r->esi = fd.handle; ++ r->ebx = 0; ++ r->es = io_buf >> 4; ++ r->ecx = io_buf_len / fd.block_size; ++ r->eax = 7; ++ x86int(0x22, r); ++ fd.handle = r->esi; ++ if((r->eflags & X86_CF)) { ++ r->eax = 1; ++ } ++ else { ++ r->edx = io_buf; ++ r->eax = 0; ++ } ++ break; ++ ++ case 3: // cb_getcwd ++ // edx filename ++ r->eax = 0x1f; // Get current working directory ++ x86int(0x22, r); ++ r->edx = (r->es << 4) + (uint16_t) r->ebx; ++ r->eax = 0; ++ break; ++ ++ case 4: // cb_chdir ++ r->es = comboot >> 4; ++ r->ebx = (uint32_t) gfx.fname_buf; ++ r->eax = 0x25; // Get current working directory ++ x86int(0x22, r); ++ break; ++ ++ case 5: // cb_readsector ++ // in: edx = sector ++ // out: edx = buffer (linear address) ++ r->esi = r->edi = 0; ++ r->ebx = 0; ++ r->es = io_buf >> 4; ++ r->ecx = 1; ++ r->eax = 0x19; // Read disk ++ x86int(0x22, r); ++ r->eax = 0; ++ r->edx = io_buf; ++ break; ++ ++ case 6: // cb_mount ++ r->eax = 0x26; ++ x86int(0x22, r); ++ r->eax = (r->eflags & X86_CF) ? 1 : 0; ++ break; ++ ++ default: ++ r->eax = 0xff; ++ } ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++// ++// return: ++// 0: ok, 1: error ++// ++int gfx_init(char *file) ++{ ++ x86regs_t r; ++ ++ int file_max, file_size, ofs; ++ unsigned u, code_start, file_start = 0, file_len = 0; ++ ++ gfx_config.mem0_start = freemem; ++ gfx_config.mem0_end = freemem + freemem_len; ++ ++ gfx_config.bios_mem_size = 256 << 20; // fake ++ ++ gfx_config.xmem_0 = 0x17; // 7MB starting at 16MB ++ ++#if 0 ++ printf("mem = 0x%05x, mem0_start = 0x%05x, mem0_end = 0x%05x\n", ++ gfx.mem, gfx_config.mem0_start, gfx_config.mem0_end ++ ); ++#endif ++ ++ if(open(file) == -1) return 1; ++ ++ // leave room for later alignment ++ gfx_config.archive_start = gfx_config.mem0_start + 0x10; ++ ++ // read at most that much ++ file_size = file_max = gfx_config.mem0_end - gfx_config.archive_start; ++ ++ if(fd.file_size != -1 && fd.file_size > file_size) return 1; ++ ++ // if we have the real size, use it ++ if(fd.file_size != -1) file_size = fd.file_size; ++ ++ file_size = read32(gfx_config.archive_start, file_size); ++ ++ if(!file_size || file_size == file_max) return 1; ++ ++ gfx_config.archive_end = gfx_config.archive_start + file_size; ++ ++ // update free mem pointer & align it a bit ++ gfx_config.mem0_start = (gfx_config.archive_end + 3) & ~3; ++ ++ // locate file inside cpio archive ++ if(!(code_start = find_file(gfx_config.archive_start, file_size, &file_start, &file_len))) { ++ printf("%s: invalid file format\n", file); ++ ++ return 1; ++ } ++ ++#if 0 ++ printf("code_start = 0x%x, archive_start = 0x%x, file size = 0x%x, file_start = 0x%x, file_len = 0x%x\n", ++ code_start, gfx_config.archive_start, file_size, file_start, file_len ++ ); ++#endif ++ ++ if((ofs = (gfx_config.archive_start + file_start + code_start) & 0xf)) { ++ printf("oops: needs to be aligned!\n"); ++ ++ memcpy32(gfx_config.archive_start - ofs, gfx_config.archive_start, file_size); ++ gfx_config.archive_start -= ofs; ++ gfx_config.archive_end -= ofs; ++ ++ return 1; ++ } ++ ++ gfx_config.file = gfx_config.archive_start + file_start; ++ gfx.code_seg = (gfx_config.file + code_start) >> 4; ++ ++ for(u = 0; u < sizeof gfx.jmp_table / sizeof *gfx.jmp_table; u++) { ++ gfx.jmp_table[u] = (gfx.code_seg << 16) + _mem16(gfx_config.file + code_start + 2 * u); ++ } ++ ++#if 0 ++ for(u = 0; u < sizeof gfx.jmp_table / sizeof *gfx.jmp_table; u++) { ++ printf("%d: 0x%08x\n", u, gfx.jmp_table[u]); ++ } ++#endif ++ ++ // we are ready to start ++ ++ r.esi = comboot + (uint32_t) &gfx_config; ++ farcall(gfx.jmp_table[GFX_BC_INIT], &r); ++ ++ if((r.eflags & X86_CF)) { ++ printf("graphics initialization failed\n"); ++ ++ return 1; ++ } ++ ++ return 0; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++void gfx_done() ++{ ++ x86regs_t r; ++ ++ farcall(gfx.jmp_table[GFX_BC_DONE], &r); ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++// ++// return: ++// boot menu index (-1: go to text mode prompt) ++// ++int gfx_input() ++{ ++ x86regs_t r; ++ ++ r.edi = comboot + (uint32_t) cmdline; ++ r.ecx = sizeof cmdline; ++ r.eax = timeout; ++ timeout = 0; // use timeout only first time ++ farcall(gfx.jmp_table[GFX_BC_INPUT], &r); ++ if((r.eflags & X86_CF)) r.eax = 1; ++ ++ if(r.eax == 1) return -1; ++ ++ return r.ebx; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++int gfx_menu_init() ++{ ++ x86regs_t r; ++ ++ r.esi = comboot + (uint32_t) &menu; ++ farcall(gfx.jmp_table[GFX_BC_MENU_INIT], &r); ++ ++ return 0; ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++void gfx_infobox(int type, char *str1, char *str2) ++{ ++ gfx_infobox32(type, comboot + (uint32_t) str1, str2 ? comboot + (uint32_t) str2 : 0); ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++void gfx_infobox32(int type, uint32_t str1, uint32_t str2) ++{ ++ x86regs_t r; ++ ++ r.eax = type; ++ r.esi = str1; ++ r.edi = str2; ++ farcall(gfx.jmp_table[GFX_BC_INFOBOX_INIT], &r); ++ r.edi = r.eax = 0; ++ farcall(gfx.jmp_table[GFX_BC_INPUT], &r); ++ farcall(gfx.jmp_table[GFX_BC_INFOBOX_DONE], &r); ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++// Load & run kernel. ++// ++// Returns only on error. ++// ++void boot() ++{ ++ x86regs_t r; ++ ++ r.es = comboot >> 4; ++ r.ebx = (uint32_t) cmdline; ++ r.edi = 8 << 20; // kernel load address: 8MB ++ r.esi = (uint32_t) _syslinux_hook; // cs:si = syslinux callbacks ++ r.eax = 0x27; // Load & run kernel (extended API) ++ x86int(0x22, &r); ++ if(!(r.eflags & X86_CF)) return; ++ ++ r.es = comboot >> 4; ++ r.ebx = (uint32_t) cmdline; ++ r.eax = 3; // Run command ++ x86int(0x22, &r); ++} ++ ++ ++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++void syslinux_hook(x86regs_t *r) ++{ ++ uint8_t f_nr = r->eax; ++ ++ // bit 7: 0/1 continue/don't continue kernel loading in syslinux ++ ++ switch(f_nr & 0x7f) { ++ case 0: // abort kernel/initrd loading ++ gfx_infobox(0, "abort kernel loading", 0); ++ break; ++ ++ case 1: // kernel/initrd not found ++ gfx_infobox(0, "kernel not found: ", current_label); ++ break; ++ ++ case 2: // kernel corrupt ++ gfx_infobox(0, "kernel broken", 0); ++ break; ++ ++ case 3: // out of memory (while initrd loading) ++ gfx_infobox(0, "out of memory", 0); ++ break; ++ ++ case 4: // progress start ++ r->eax = r->ecx >> gfx_config.sector_shift; // kernel size in sectors ++ r->eax = 0; ++ r->esi = comboot + (uint32_t) current_label; ++ farcall(gfx.jmp_table[GFX_BC_PROGRESS_INIT], r); ++ break; ++ ++ case 5: // progress increment ++ // always 64k ++ r->eax = 0x10000 >> gfx_config.sector_shift; ++ farcall(gfx.jmp_table[GFX_BC_PROGRESS_UPDATE], r); ++ break; ++ ++ case 6: // progress end: kernel loaded, stop gfxboot ++ farcall(gfx.jmp_table[GFX_BC_PROGRESS_DONE], r); ++ gfx_done(); ++ break; ++ } ++} ++ ++ +diff --git a/modules/libio.asm b/modules/libio.asm +new file mode 100644 +index 0000000..57bcde3 +--- /dev/null ++++ b/modules/libio.asm +@@ -0,0 +1,854 @@ ++; ++; libio.asm ++; ++; A very minimalistic libc fragment. ++; ++; Copyright (c) 2009 Steffen Winterfeldt. ++; ++; 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. ++; ++ ++ ++; max argv elements passed to main() ++%define MAX_ARGS 8 ++ ++ ++ bits 16 ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; interface functions ++; ++; Make sure not to modify registers! ++; ++ ++ global printf ++ global getchar ++ global clrscr ++ global memcpy ++ global memcpy32 ++ global memset ++ global memset32 ++ global x86int ++ global farcall ++ global reboot ++ ++ global _gfx_cb ++ extern gfx_cb ++ global _syslinux_hook ++ extern syslinux_hook ++ ++ global _start ++ extern _main ++ ++ extern __bss_start ++ ++ section .init ++ ++_start: ++ cld ++ ++ ; clear static memory ++ mov di,__bss_start ++ mov cx,sp ++ sub cx,di ++ xor ax,ax ++ rep stosb ++ ++ ; parse args ++ mov bx,80h ++ movzx si,byte [bx] ++ mov byte [si+81h],0dh ; just make sure ++ xor ecx,ecx ++ sub sp,MAX_ARGS * 4 ++ mov ebp,esp ++ inc cx ++cmd_10: ++ inc bx ++ call skip_spaces ++ cmp al,0dh ++ jz cmd_60 ++ imul si,cx,4 ++ mov [bp+si],ebx ++ call skip_nonspaces ++ mov byte [bx],0 ++ inc cx ++ cmp cx,MAX_ARGS ++ jae cmd_60 ++ cmp al,0dh ++ jnz cmd_10 ++cmd_60: ++ mov byte [bx],0 ++ ++ mov [bp],ebx ; argv[0] = "" ++ ++ push ebp ++ push ecx ++ ++ call dword _main ++ ++ add sp,MAX_ARGS * 4 + 8 ++ ++ ret ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++skip_spaces: ++ mov al,[bx] ++ cmp al,0dh ++ jz skip_spaces_90 ++ cmp al,' ' ++ jz skip_spaces_10 ++ cmp al,9 ++ jnz skip_spaces_90 ++skip_spaces_10: ++ inc bx ++ jmp skip_spaces ++skip_spaces_90: ++ ret ++ ++skip_nonspaces: ++ mov al,[bx] ++ cmp al,0dh ++ jz skip_nonspaces_90 ++ cmp al,' ' ++ jz skip_nonspaces_90 ++ cmp al,9 ++ jz skip_nonspaces_90 ++ inc bx ++ jmp skip_nonspaces ++skip_nonspaces_90: ++ ret ++ ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ section .text ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; Write text to console. ++; ++; args on stack ++; ++; Note: 32 bit call/ret! ++; ++printf: ++ mov [pf_args],sp ++ ++ pushad ++ ++ call pf_next_arg ++ call pf_next_arg ++ mov si,ax ++printf_10: ++ lodsb ++ or al,al ++ jz printf_90 ++ cmp al,'%' ++ jnz printf_70 ++ mov byte [pf_pad],' ' ++ lodsb ++ dec si ++ cmp al,'0' ++ jnz printf_20 ++ mov [pf_pad],al ++printf_20: ++ call get_number ++ mov [pf_num],ecx ++ lodsb ++ or al,al ++ jz printf_90 ++ cmp al,'%' ++ jz printf_70 ++ ++ cmp al,'S' ++ jnz printf_23 ++ mov byte [pf_raw_char],1 ++ jmp printf_24 ++printf_23: ++ cmp al,'s' ++ jnz printf_30 ++printf_24: ++ push si ++ ++ call pf_next_arg ++ mov si,ax ++ call puts ++ ++ sub ecx,[pf_num] ++ neg ecx ++ mov al,' ' ++ call putc_n ++ ++ pop si ++ ++ mov byte [pf_raw_char],0 ++ jmp printf_10 ++ ++printf_30: ++ cmp al,'u' ++ jnz printf_35 ++ ++ mov dx,10 ++printf_31: ++ push si ++ ++ call pf_next_arg ++ or dh,dh ++ jz printf_34 ++ test eax,eax ++ jns printf_34 ++ neg eax ++ push eax ++ mov al,'-' ++ call putc ++ pop eax ++printf_34: ++ mov cl,[pf_num] ++ mov ch,[pf_pad] ++ call number ++ call puts ++ ++ pop si ++ ++ jmp printf_10 ++ ++printf_35: ++ cmp al,'x' ++ jnz printf_36 ++ ++printf_35a: ++ mov dx,10h ++ jmp printf_31 ++ ++printf_36: ++ cmp al,'d' ++ jnz printf_37 ++printf_36a: ++ mov dx,10ah ++ jmp printf_31 ++ ++printf_37: ++ cmp al,'i' ++ jz printf_36a ++ ++ cmp al,'p' ++ jnz printf_40 ++ mov al,'0' ++ call putc ++ mov al,'x' ++ call putc ++ jmp printf_35a ++ ++printf_40: ++ cmp al,'c' ++ jnz printf_45 ++ ++ push si ++ call pf_next_arg ++ call putc ++ pop si ++ jmp printf_10 ++printf_45: ++ ++ ; more ... ++ ++ ++printf_70: ++ call putc ++ jmp printf_10 ++printf_90: ++ popad ++ ++ o32 ret ++ ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; Get next printf arg from [pf_args]. +; +; return: ++; eax arg +; -+cb_mount: -+ mov ax,26h -+ int 22h -+ mov al,0 -+ adc al,0 ++; changes no regs ++; ++pf_next_arg: ++ movzx eax,word [pf_args] ++ add word [pf_args],4 ++ mov eax,[eax] + ret + - gfx_init: - mov ax,0e801h - xor bx,bx -@@ -358,11 +453,10 @@ mem_below_16mb: - shl eax,10 - mov [gfx_bios_mem_size],eax - shr eax,20 -- cmp ax,16 -+ cmp ax,32 - jb skip_extended - -- mov word [gfx_xmem_0],88h ; 8MB at 8MB -- mov dword [gfx_save_area1],7f0000h ; 8MB-64k -+ mov word [gfx_xmem_0],017h ; 3MB at 16MB - - skip_extended: - movzx ebx,word [gfx_mem_start_seg] -@@ -405,7 +499,37 @@ skip_extended: - 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 ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; Convert string to number. ++; ++; si string ++; ++; return: ++; ecx number ++; si points past number ++; CF not a number ++; ++get_number: + -+ mov ax,[es:bx+12] -+ mov [gfx_bc_progress_init],ax -+ mov [gfx_bc_progress_init+2],es ++ xor ecx,ecx ++ mov ah,1 ++get_number_10: ++ lodsb ++ or al,al ++ jz get_number_90 ++ sub al,'0' ++ jb get_number_90 ++ cmp al,9 ++ ja get_number_90 ++ movzx eax,al ++ imul ecx,ecx,10 ++ add ecx,eax ++ jmp get_number_10 ++get_number_90: ++ dec si ++ shr ah,1 ++ ret + -+ 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 ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; Convert a number to string. ++; ++; eax number ++; cl field size ++; ch padding char ++; dl base ++; ++; return: ++; si string ++; ++number: ++ mov di,num_buf ++ push ax ++ push cx ++ mov al,ch ++ mov cx,num_buf_end - num_buf ++ rep stosb ++ pop cx ++ pop ax ++ movzx cx,cl ++ movzx ebx,dl ++number_10: ++ xor edx,edx ++ div ebx ++ cmp dl,9 ++ jbe number_20 ++ add dl,27h ++number_20: ++ add dl,'0' ++ dec edi ++ mov [di],dl ++ or eax,eax ++ jz number_30 ++ cmp di,num_buf ++ ja number_10 ++number_30: ++ mov si,di ++ or cx,cx ++ jz number_90 ++ cmp cx,num_buf_end - num_buf ++ jae number_90 ++ mov si,num_buf_end ++ sub si,cx ++number_90: ++ ret + -+ 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 ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; Write string. ++; ++; si text ++; ++; return: ++; cx length ++; ++puts: ++ xor cx,cx ++puts_10: ++ lodsb ++ or al,al ++ jz puts_90 ++ call putc ++ inc cx ++ jmp puts_10 ++puts_90: ++ ret + -+ mov ax,[es:bx+22] -+ mov [gfx_bc_password_done],ax -+ mov [gfx_bc_password_done+2],es - - mov esi,cs - shl esi,4 -@@ -974,8 +1098,6 @@ msg_no_labels_defined db 'No labels defined in config file',0dh,0ah,0 - msg_space db ' ',0 - msg_crlf db 0dh,0ah,0 - --gfx_slash db '/', 0 --db0 db 0 - menu_timeout dd 100 - - keyword_text_label db 6,'label',0 -@@ -1071,8 +1193,6 @@ gfx_mem_end_seg resw 1 - - alignb 4 - gfx_mem resd 1 ; linear address --gfx_save_area1 resd 1 ; 64k --gfx_save_area1_used resb 1 ; != 0 if area1 is in use - - alignb 4 - ; interface to loadable gfx extension (seg:ofs values) -@@ -1082,3 +1202,12 @@ gfx_bc_init resd 1 - gfx_bc_done resd 1 - gfx_bc_input resd 1 - gfx_bc_menu_init resd 1 -+gfx_bc_infobox_init resd 1 -+gfx_bc_infobox_done resd 1 -+gfx_bc_progress_init resd 1 -+gfx_bc_progress_done resd 1 -+gfx_bc_progress_update resd 1 -+gfx_bc_progress_limit resd 1 -+gfx_bc_password_init resd 1 -+gfx_bc_password_done resd 1 ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; Write char multiple times. ++; ++; al char ++; cx count (does nothing if count <= 0) ++; ++putc_n: ++ cmp cx,0 ++ jle putc_n_90 ++ call putc ++ dec cx ++ jmp putc_n ++putc_n_90: ++ ret ++ ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; Print char. ++; ++; al char ++; ++putc: ++ pusha ++ cmp al,0ah ++ jnz putc_30 ++ push ax ++ mov al,0dh ++ call putc_50 ++ pop ax ++putc_30: ++ call putc_50 ++ popa ++ ret ++putc_50: ++ mov bx,7 ++ mov ah,0eh ++ int 10h ++ ret ++ ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; Read char from stdin. ++; ++; return: ++; eax char ++; ++; Note: 32 bit call/ret! ++; ++getchar: ++ pushad ++ mov ah,10h ++ int 16h ++ mov [gc_tmp],al ++ popad ++ movzx eax,byte [gc_tmp] ++ o32 ret ++ ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; Clear screen. ++; ++; Note: 32 bit call/ret! ++; ++clrscr: ++ pushad ++ push es ++ push word 40h ++ pop es ++ mov ax,600h ++ mov bh,7 ++ xor cx,cx ++ mov dl,[es:4ah] ++ or dl,dl ++ jnz clrscr_20 ++ mov dl,80 ++clrscr_20: ++ dec dl ++ mov dh,[es:84h] ++ or dh,dh ++ jnz clrscr_30 ++ mov dh,24 ++clrscr_30: ++ int 10h ++ mov ah,2 ++ mov bh,[es:62h] ++ xor dx,dx ++ int 10h ++ pop es ++ popad ++ o32 ret ++ ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; dst = memcpy(dst, src, size). ++; ++; args on stack ++; ++; return: ++; eax dst ++; ++; Note: 32 bit call/ret! ++; ++memcpy: ++ pushad ++ ++ mov edi,[esp+0x20+4] ++ mov esi,[esp+0x20+8] ++ mov ecx,[esp+0x20+12] ++ ++ rep movsb ++ ++ popad ++ ++ mov eax,[esp+4] ++ ++ o32 ret ++ ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; dst = memset(dst, val, size). ++; ++; args on stack ++; ++; return: ++; eax dst ++; ++; Note: 32 bit call/ret! ++; ++memset: ++ pushad ++ ++ mov edi,[esp+0x20+4] ++ mov al,[esp+0x20+8] ++ mov ecx,[esp+0x20+12] ++ ++ rep stosb ++ ++ popad ++ ++ mov eax,[esp+4] ++ ++ o32 ret ++ ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; dst = memset32(dst, val, size). ++; ++; args on stack ++; ++; return: ++; eax dst ++; ++; Note: 32 bit call/ret! ++; ++memset32: ++ pushad ++ ++ push es ++ ++ mov ebx,[esp+0x22+4] ; edi ++ mov al,[esp+0x22+8] ++ mov edx,[esp+0x22+12] ++ ++memset32_20: ++ mov edi,ebx ++ mov ecx,ebx ++ and di,0fh ++ shr ecx,4 ++ mov es,cx ++ ++ mov ecx,0fff0h ++ cmp edx,ecx ++ ja memset32_40 ++ mov ecx,edx ++memset32_40: ++ add ebx,ecx ++ sub edx,ecx ++ ++ rep stosb ++ ++ jnz memset32_20 ++ ++ pop es ++ ++ popad ++ ++ mov eax,[esp+4] ++ ++ o32 ret ++ ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; dst = memcpy32(dst, src, size). ++; ++; dst, src are 32bit linear addresses ++; ++; args on stack ++; ++; return: ++; eax dst ++; ++; Note: 32 bit call/ret! ++; ++memcpy32: ++ pushad ++ ++ push ds ++ push es ++ ++ mov ebx,[esp+0x24+4] ; edi ++ mov eax,[esp+0x24+8] ; esi ++ mov edx,[esp+0x24+12] ++ ++memcpy32_20: ++ mov edi,ebx ++ mov ecx,ebx ++ and di,0fh ++ shr ecx,4 ++ mov es,cx ++ ++ mov esi,eax ++ mov ecx,eax ++ and si,0fh ++ shr ecx,4 ++ mov ds,cx ++ ++ mov ecx,0fff0h ++ cmp edx,ecx ++ ja memcpy32_40 ++ mov ecx,edx ++memcpy32_40: ++ add ebx,ecx ++ add eax,ecx ++ sub edx,ecx ++ ++ rep movsb ++ ++ jnz memcpy32_20 ++ ++ pop es ++ pop ds ++ ++ popad ++ ++ mov eax,[esp+4] ++ ++ o32 ret ++ ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; x86int(int, *regs). ++; ++; args on stack ++; ++; Note: 32 bit call/ret! ++; ++x86int: ++ pushad ++ ++ mov al,[esp+0x20+4] ++ mov [x86int_p],al ++ mov ebx,[esp+0x20+8] ++ ++ mov ecx,[bx+8] ++ mov edx,[bx+0ch] ++ mov esi,[bx+10h] ++ mov edi,[bx+14h] ++ mov ebp,[bx+18h] ++ mov ah,[bx+1ch] ; eflags ++ sahf ++ mov eax,[bx] ++ ++ mov es,[bx+22h] ++ mov fs,[bx+24h] ++ mov gs,[bx+26h] ++ mov ds,[bx+20h] ++ ++ mov ebx,[cs:bx+4] ++ ++ int 0h ++x86int_p equ $-1 ++ ++ push ebx ++ mov ebx,[esp+0x24+8] ++ pop dword [cs:bx+4] ++ ++ mov [cs:bx],eax ++ mov [cs:bx+20h],ds ++ ++ mov ax,cs ++ mov ds,ax ++ ++ mov [cs:bx+22h],es ++ mov [cs:bx+24h],fs ++ mov [cs:bx+26h],gs ++ ++ mov es,ax ++ mov fs,ax ++ mov gs,ax ++ ++ mov [bx+8],ecx ++ mov [bx+0ch],edx ++ mov [bx+10h],esi ++ mov [bx+14h],edi ++ mov [bx+18h],ebp ++ pushfd ++ pop dword [bx+1ch] ++ ++ popad ++ ++ o32 ret ++ ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; farcall(addr, *regs). ++; ++; args on stack ++; ++; Note: 32 bit call/ret! ++; ++farcall: ++ pushad ++ ++ mov ebx,[esp+0x20+8] ++ ++ mov ecx,[bx+8] ++ mov edx,[bx+0ch] ++ mov esi,[bx+10h] ++ mov edi,[bx+14h] ++ mov ebp,[bx+18h] ++ mov ah,[bx+1ch] ; eflags ++ sahf ++ mov eax,[bx] ++ ++ mov [farcall_stack],sp ++ sub word [farcall_stack],1000h ; 4k stack should be enough for gfxboot ++ mov [farcall_stack+2],ss ++ ++ mov es,[bx+22h] ++ mov fs,[bx+24h] ++ mov gs,[bx+26h] ++ mov ds,[bx+20h] ++ ++ mov ebx,[cs:bx+4] ++ ++ call far [esp+0x20+4] ++ ++ push ebx ++ mov ebx,[esp+0x24+8] ++ pop dword [cs:bx+4] ++ ++ mov [cs:bx],eax ++ mov [cs:bx+20h],ds ++ ++ mov ax,cs ++ mov ds,ax ++ ++ mov [cs:bx+22h],es ++ mov [cs:bx+24h],fs ++ mov [cs:bx+26h],gs ++ ++ mov es,ax ++ mov fs,ax ++ mov gs,ax ++ ++ mov [bx+8],ecx ++ mov [bx+0ch],edx ++ mov [bx+10h],esi ++ mov [bx+14h],edi ++ mov [bx+18h],ebp ++ pushfd ++ pop dword [bx+1ch] ++ ++ popad ++ ++ o32 ret ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; wrapper around gfx_cb() ++; ++; we need to switch stack to ensure ss = cs = ds = es for gcc ++; ++_gfx_cb: ++ push cs ++ pop ds ++ push cs ++ pop es ++ mov [cb_stack],sp ++ mov [cb_stack+2],ss ++ lss sp,[farcall_stack] ++ sub sp,28h ; sizeof x86regs_t ++ mov [esp+18h],ebp ++ mov ebp,esp ++ push ebp ++ mov [bp],eax ++ mov [bp+4],ebx ++ mov [bp+8],ecx ++ mov [bp+0ch],edx ++ mov [bp+10h],esi ++ mov [bp+14h],edi ++ call dword gfx_cb ++ lea ebp,[esp+4] ++ mov eax,[bp] ++ mov ebx,[bp+4] ++ mov ecx,[bp+8] ++ mov edx,[bp+0ch] ++ mov esi,[bp+10h] ++ mov edi,[bp+14h] ++ mov ebp,[bp+18h] ++ lss sp,[cb_stack] ++ retf ++ ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++; wrapper around syslinux_hook() ++; ++; ensure cs = ds = es for gcc ++; ++_syslinux_hook: ++ push cs ++ pop ds ++ push cs ++ pop es ++ sub sp,28h ; sizeof x86regs_t ++ mov [esp+18h],ebp ++ mov ebp,esp ++ push ebp ++ mov [bp],eax ++ mov [bp+4],ebx ++ mov [bp+8],ecx ++ mov [bp+0ch],edx ++ mov [bp+10h],esi ++ mov [bp+14h],edi ++ call dword syslinux_hook ++ lea ebp,[esp+4] ++ mov eax,[bp] ++ mov ebx,[bp+4] ++ mov ecx,[bp+8] ++ mov edx,[bp+0ch] ++ mov esi,[bp+10h] ++ mov edi,[bp+14h] ++ mov ebp,[bp+18h] ++ add sp,28h+4 ++ retf ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++reboot: ++ mov word [472h],1234h ++ jmp 0ffffh:0 ++ int 19h ++ jmp $ ++ ++ ++; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ++ section .data ++ ++farcall_stack dd 0 ++cb_stack dd 0 ++ ++; buffer for number conversions ++; must be large enough for ps_status_info() ++num_buf times 23h db 0 ++num_buf_end db 0 ++ ++; temp data for printf ++pf_args dw 0 ++pf_num dd 0 ++pf_sig db 0 ++pf_pad db 0 ++pf_raw_char db 0 ++gc_tmp db 0 ++ +diff --git a/modules/libio.h b/modules/libio.h +new file mode 100644 +index 0000000..b7a3dc6 +--- /dev/null ++++ b/modules/libio.h +@@ -0,0 +1,131 @@ ++/* ++ * ++ * libio.h include file for libio ++ * ++ * Copyright (c) 2009 Steffen Winterfeldt. ++ * ++ * 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. ++ * ++ */ ++ ++#ifndef _LIBIO_H ++#define _LIBIO_H ++ ++ ++asm(".code16gcc\n"); ++ ++ ++#define int8_t char ++#define int16_t short ++#define int32_t int ++#define uint8_t unsigned char ++#define uint16_t unsigned short ++#define uint32_t unsigned ++ ++#define X86_CF 0x0001 ++#define X86_PF 0x0004 ++#define X86_AF 0x0010 ++#define X86_ZF 0x0040 ++#define X86_SF 0x0080 ++#define X86_TF 0x0100 ++#define X86_IF 0x0200 ++#define X86_DF 0x0400 ++#define X86_OF 0x0800 ++ ++#define EOF -1 ++ ++#define main _main ++ ++ ++typedef struct __attribute ((packed)) { ++ uint32_t eax, ebx, ecx, edx, esi, edi, ebp, eflags; ++ uint16_t ds, es, fs, gs; ++} x86regs_t; ++ ++ ++static inline uint16_t comboot_seg(void) ++{ ++ uint16_t u; ++ ++ asm("mov %%cs, %0" : "=r" (u)); ++ ++ return u; ++} ++ ++ ++static inline uint8_t _mem8(uint32_t p) ++{ ++ uint8_t u; ++ ++ asm( ++ "movl %1,%%esi\n" ++ "shrl $4,%%esi\n" ++ "mov %%si,%%fs\n" ++ "movl %1,%%esi\n" ++ "and $15, %%si\n" ++ "movb %%fs:(%%si),%0\n" ++ : "=abcd" (u) : "r" (p) : "si" ++ ); ++ ++ return u; ++} ++ ++ ++static inline uint16_t _mem16(uint32_t p) ++{ ++ uint16_t u; ++ ++ asm( ++ "movl %1,%%esi\n" ++ "shrl $4,%%esi\n" ++ "mov %%si,%%fs\n" ++ "movl %1,%%esi\n" ++ "and $15, %%si\n" ++ "movw %%fs:(%%si),%0\n" ++ : "=r" (u) : "r" (p) : "si" ++ ); ++ ++ return u; ++} ++ ++ ++static inline uint32_t _mem32(uint32_t p) ++{ ++ uint32_t u; ++ ++ asm( ++ "movl %1,%%esi\n" ++ "shrl $4,%%esi\n" ++ "mov %%si,%%fs\n" ++ "movl %1,%%esi\n" ++ "and $15, %%si\n" ++ "movl %%fs:(%%si),%0\n" ++ : "=r" (u) : "r" (p) : "si" ++ ); ++ ++ return u; ++} ++ ++ ++int _main(int argc, char **argv); ++void printf(char *format, ...) __attribute__ ((format (printf, 1, 2))); ++int getchar(void); ++void clrscr(void); ++void *memcpy(void *dest, const void *src, int n); ++uint32_t memcpy32(uint32_t dest, uint32_t src, int n); ++void *memset(void *dest, int c, int n); ++uint32_t memset32(uint32_t dest, int c, int n); ++void x86int(unsigned intr, x86regs_t *regs); ++void farcall(uint32_t seg_ofs, x86regs_t *regs); ++void gfx_cb(x86regs_t *r); ++void _gfx_cb(void); ++void syslinux_hook(x86regs_t *r); ++void _syslinux_hook(void); ++void reboot(void); ++ ++#endif /* _LIBIO_H */ + diff --git a/syslinux-3.82-s_herbst.diff b/syslinux-3.82-s_herbst.diff deleted file mode 100644 index 68783cc..0000000 --- a/syslinux-3.82-s_herbst.diff +++ /dev/null @@ -1,237 +0,0 @@ -diff --git a/modules/gfxboot.asm b/modules/gfxboot.asm -index c9fdd1b..5c7b118 100644 ---- a/modules/gfxboot.asm -+++ b/modules/gfxboot.asm -@@ -144,7 +144,15 @@ got_config_file: - push cs - pop es - call parse_config -+ cmp word [label_cnt],0 -+ ja labels_defined - -+ mov bx,msg_no_labels_defined -+ mov ax,2 -+ int 22h -+ ret -+ -+labels_defined: - ; get_gfx_file - mov ax,cs - add ax,2000h -@@ -417,6 +425,14 @@ gfx_read_file: - mov si,pspCmdArg+1 - int 22h - jnc gfx_file_read -+ -+ mov ax,2 -+ mov bx,pspCmdArg+1 -+ int 22h -+ -+ mov ax,2 -+ mov bx,msg_not_found -+ int 22h - stc - ret - -@@ -641,8 +657,7 @@ gfx_input: - 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) -+ mov eax,[menu_timeout] ; timeout value (0: no timeout) - - call far [gfx_bc_input] - ret -@@ -699,33 +714,39 @@ parse_config: - mov bx, msg_crlf - int 22h - %endif -+ mov bx,keywords -+ mov cx,[keyword_cnt] -+.keywords_loop: -+ push cx - push si - push di -- xor ecx,ecx -+ xor cx,cx - mov si,configbuf -- mov di,label_keyword+1 -- mov cl, byte [label_keyword] -+ mov di,[bx] -+ mov cl,byte [di] -+ inc di - call memcmp - pop di - pop si -- jz .do_label -+ jnz .not_found -+ pop cx -+ call [bx+2] ; call keyword handler -+ jmp .read - -- push si -- push di -- xor ecx,ecx -- mov si,configbuf -- mov di,default_keyword+1 -- mov cl, byte [default_keyword] -- call memcmp -- pop di -- pop si -- jz .do_default -+.not_found: -+ add bx,4 -+ pop cx -+ loop .keywords_loop - - .nextline: - call skipline - jmp .read - --.do_label: -+.eof: -+.noparm: -+ ret -+ -+do_label: - call skipspace - jz .eof - jc .noparm -@@ -742,10 +763,11 @@ parse_config: - pop di - pop es - inc word [label_cnt] -+.eof: -+.noparm: -+ ret - -- jmp .read -- --.do_default: -+do_default: - call skipspace - jz .eof - jc .noparm -@@ -759,8 +781,42 @@ parse_config: - pop di - pop es - -- jmp .read -+.eof: -+.noparm: -+ ret - -+do_timeout: -+ call skipspace -+ jz .eof -+ jc .noparm -+ call ungetc -+ push es -+ push di -+ push cs -+ pop es -+ mov di,NumBuf -+.getnum: -+ cmp di,NumBufEnd -+ jae .loaded -+ call getc -+ stosb -+ cmp al,'-' -+ jnb .getnum -+ call ungetc -+ dec di -+.loaded: -+ mov byte [di],0 -+ pop di -+ pop es -+ push cs -+ pop ds -+ mov si,NumBuf -+ push ebx -+ call parseint -+ jc .err -+ mov [menu_timeout],ebx -+.err: -+ pop ebx - .eof: - .noparm: - ret -@@ -876,23 +932,63 @@ memcmp: - pop si - ret - -- section .data --label_keyword db 6,'label',0 --default_keyword db 7,'default',0 -+parseint: -+ push eax -+ push ecx -+ xor eax,eax -+ xor ebx,ebx -+ xor ecx,ecx -+ mov cl,10 -+.loop: -+ lodsb -+ and al,al -+ jz .done -+ cmp al,'0' -+ jb .err -+ cmp al,'9' -+ ja .err -+ sub al,'0' -+ imul ebx,ecx -+ add ebx,eax -+ jmp short .loop -+.done: -+ clc -+.ret: -+ pop ecx -+ pop eax -+ ret -+.err: -+ stc -+ jmp short .ret - -+ section .data - msg_progname db 'gfxboot: ',0 - msg_config_file db 'Configuration file',0 - msg_missing db 'missing',0 - msg_usage db 'Usage: gfxboot.com ',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_not_found db ' not found',0dh,0ah,0 -+msg_no_labels_defined db 'No labels defined in config file',0dh,0ah,0 - msg_space db ' ',0 - msg_crlf db 0dh,0ah,0 - - gfx_slash db '/', 0 - db0 db 0 -+menu_timeout dd 100 -+ -+keyword_text_label db 6,'label',0 -+keyword_text_default db 7,'default',0 -+keyword_text_timeout db 7,'timeout',0 -+keywords equ $ -+ dw keyword_text_label -+ dw do_label -+ dw keyword_text_default -+ dw do_default -+ dw keyword_text_timeout -+ dw do_timeout -+keyword_cnt dw ($-keywords)/4 - - ; menu entry descriptor - menu_entries equ 0 -@@ -942,6 +1038,9 @@ dentry_buf_len equ $ - dentry_buf - max_cmd_len equ 2047 - command_line resb max_cmd_len+2 - -+NumBuf resb 15 -+NumBufEnd resb 1 -+ - alignb 4 - derivative_id resb 1 - drivenumber resb 1 diff --git a/syslinux.changes b/syslinux.changes index de5650f..96bbef2 100644 --- a/syslinux.changes +++ b/syslinux.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Fri Aug 7 13:47:54 CEST 2009 - snwint@suse.de + +- replaced gfxboot.com with an enhanced version + ------------------------------------------------------------------- Tue Aug 4 10:49:19 CEST 2009 - snwint@suse.de diff --git a/syslinux.spec b/syslinux.spec index c1eb282..ff3e9fc 100644 --- a/syslinux.spec +++ b/syslinux.spec @@ -20,9 +20,6 @@ Name: syslinux ExclusiveArch: %ix86 x86_64 BuildRequires: libpng-devel nasm netpbm python -%ifarch x86_64 -BuildRequires: gcc-32bit glibc-devel-32bit -%endif Url: http://syslinux.zytor.com/ License: GPL v2 or later Group: System/Boot @@ -30,15 +27,14 @@ Requires: mtools AutoReqProv: on Summary: Boot Loader for Linux Version: 3.82 -Release: 2 +Release: 3 Source: %{name}-%{version}.tar.bz2 Source1: isolinux-config Source2: README.gfxboot -Patch0: %{name}-%{version}-s_herbst.diff -Patch1: %{name}-%{version}-gfxboot.diff -Patch2: %{name}-%{version}-suse.diff -Patch3: %{name}-%{version}-compat.diff -Patch4: %{name}-%{version}-isohybrid.diff +Patch0: %{name}-%{version}-gfxboot.diff +Patch1: %{name}-%{version}-suse.diff +Patch2: %{name}-%{version}-compat.diff +Patch3: %{name}-%{version}-isohybrid.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@ -59,7 +55,6 @@ Authors: %patch1 -p1 %patch2 -p1 %patch3 -p1 -%patch4 -p1 %build cp %{SOURCE2} .