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 +++ b/core/isolinux.asm @@ -1135,73 +1135,23 @@ all_read: ; (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. ; -get_fs_structures: - mov eax,[bi_pvd] - mov bx,trackbuf - call getonesec - - mov eax,[trackbuf+156+2] - mov [RootDir+dir_lba],eax - mov [CurrentDir+dir_lba],eax -%ifdef DEBUG_MESSAGES - mov si,dbg_rootdir_msg - call writemsg - call writehex8 - call crlf -%endif - mov eax,[trackbuf+156+10] - mov [RootDir+dir_len],eax - mov [CurrentDir+dir_len],eax - add eax,SECTOR_SIZE-1 - shr eax,SECTOR_SHIFT - mov [RootDir+dir_clust],eax - mov [CurrentDir+dir_clust],eax - - ; Look for an isolinux directory, and if found, - ; make it the current directory instead of the root - ; directory. - ; Also copy the name of the directory to CurrentDirName - mov word [CurrentDirName],ROOT_DIR_WORD ; Write '/',0 to the CurrentDirName + call iso_mount mov di,boot_dir ; Search for /boot/isolinux - mov al,02h - push di - call searchdir_iso - pop di - jnz .found_dir - mov di,isolinux_dir - mov al,02h ; Search for /isolinux - push di - call searchdir_iso - pop di - jz .no_isolinux_dir + call setcwd + jnc .found_dir + mov di,isolinux_dir ; Search for /isolinux + call setcwd .found_dir: - ; Copy current directory name to CurrentDirName - push si - push di - mov si,di - mov di,CurrentDirName - call strcpy - mov byte [di],0 ;done in case it's not word aligned - dec di - mov byte [di],'/' - pop di - pop si - mov [CurrentDir+dir_len],eax - mov eax,[si+file_left] - mov [CurrentDir+dir_clust],eax - xor eax,eax ; Free this file pointer entry - xchg eax,[si+file_sector] - mov [CurrentDir+dir_lba],eax %ifdef DEBUG_MESSAGES push si mov si,dbg_isodir_msg call writemsg pop si + mov eax,[CurrentDir+dir_lba] call writehex8 call crlf %endif -.no_isolinux_dir: ; ; Locate the configuration file @@ -1706,6 +1656,90 @@ getfssec: TRACER 'f' ret +; +; setcwd: Set current working directory. +; +; On entry: +; DI -> directory name +; On exit: +; CF = 1 -> error +; +; On error, the old working directory is kept. +; +setcwd: + mov al,02h + push di + call searchdir_iso + pop di + stc + jz .err + mov [CurrentDir+dir_len],eax + mov eax,[si+file_left] + mov [CurrentDir+dir_clust],eax + xor eax,eax + xchg eax,[si+file_sector] + mov [CurrentDir+dir_lba],eax + mov si,di + mov di,CurrentDirName + cmp si,di + jz .ok + mov cx,FILENAME_MAX + push ds + pop es +.copy: + lodsb + stosb + or al,al + loopnz .copy + mov byte [di-1],0 + jnz .err +.ok: + clc +.err: + ret + +; +; Read fs meta data and setup RootDir and CurrentDir. +; +; On exit: +; CF = 1 -> error +; +iso_mount: + mov eax,[bi_pvd] + mov bx,trackbuf + call getonesec + + mov eax,[trackbuf+156+10] + mov [RootDir+dir_len],eax + add eax,SECTOR_SIZE-1 + shr eax,SECTOR_SHIFT + mov [RootDir+dir_clust],eax + mov eax,[trackbuf+156+2] + mov [RootDir+dir_lba],eax + + push ds + pop es + mov si,RootDir + mov di,CurrentDir + mov cx,dir_t_size + rep movsb + +%ifdef DEBUG_MESSAGES + mov si,dbg_rootdir_msg + call writemsg + call writehex8 + call crlf +%endif + + mov di,CurrentDirName + call setcwd + jnc .ok + mov word [CurrentDirName],ROOT_DIR_WORD +.ok: + clc + ret + + ; ----------------------------------------------------------------------------- ; 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 -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 +++ b/core/loadhigh.inc @@ -101,6 +101,8 @@ load_high: ret .overflow: mov si,err_nohighmem + mov al,83h + call [comboot_hook] ; may not return jmp abort_load section .data diff --git a/core/runkernel.inc b/core/runkernel.inc index 8bfc8b8..0cd2488 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 any_kernel: + mov al,4 + call [comboot_hook] 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!! + mov al,6 + call [comboot_hook] + 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: xor ax,ax cmp word [InitRDPtr],ax ; Old kernel can't have initrd je .load + mov al,82h + call [comboot_hook] ; may not return mov si,err_oldkernel jmp abort_load .load: @@ -613,6 +624,8 @@ loadinitrd: ret .notthere: + mov al,81h + call [comboot_hook] ; may not return 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 --- a/core/ui.inc +++ b/core/ui.inc @@ -468,6 +468,8 @@ bad_kernel: .really: mov si,KernelName mov di,KernelCName + mov al,81h + call [comboot_hook] ; may not return push di call unmangle_name ; Get human form mov si,err_notfound ; Complain about missing kernel @@ -510,7 +512,10 @@ on_error: ; ; kernel_corrupt: Called if the kernel file does not seem healthy ; -kernel_corrupt: mov si,err_notkernel +kernel_corrupt: + mov al,82h + call [comboot_hook] ; may not return + mov si,err_notkernel jmp abort_load ; @@ -591,7 +596,7 @@ kernel_good: ; xor ax,ax mov [InitRDPtr],ax - mov [QuietBoot],al + and byte [QuietBoot],~1 %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 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 +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. +; +; Can modify all regs & sregs. +; +; 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 +; +syslinux_hook: + push cs + 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 ret ; Read sector @@ -334,6 +418,17 @@ cb_readsector: cb_readsector_end: ret +; Read filesystem meta data. +; +; return: +; +cb_mount: + mov ax,26h + int 22h + mov al,0 + adc al,0 + 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 + + 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 @@ -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 +