forked from pool/syslinux
c9ed7a89e1
Copy from system:install:head/syslinux based on submit request 37404 from user snwint OBS-URL: https://build.opensuse.org/request/show/37404 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/syslinux?expand=0&rev=23
2845 lines
58 KiB
Diff
2845 lines
58 KiB
Diff
diff --git a/core/isolinux.asm b/core/isolinux.asm
|
|
index 23429bd..54f2e19 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/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/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 e738706..5da5bc9 100644
|
|
--- a/core/runkernel.inc
|
|
+++ b/core/runkernel.inc
|
|
@@ -233,6 +233,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
|
|
@@ -324,6 +326,9 @@ load_initrd:
|
|
;
|
|
call abort_check ; Last chance!!
|
|
|
|
+ mov al,6
|
|
+ call [comboot_hook]
|
|
+
|
|
mov si,ready_msg
|
|
call writestr_qchk
|
|
|
|
@@ -497,6 +502,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:
|
|
@@ -621,6 +628,8 @@ loadinitrd:
|
|
ret
|
|
|
|
.notthere:
|
|
+ mov al,81h
|
|
+ call [comboot_hook] ; may not return
|
|
mov si,err_noinitrd
|
|
call writestr
|
|
mov si,InitRDCName
|
|
diff --git a/core/ui.inc b/core/ui.inc
|
|
index ed96ccd..0d896fc 100644
|
|
--- a/core/ui.inc
|
|
+++ b/core/ui.inc
|
|
@@ -417,8 +417,12 @@ vk_check:
|
|
%if HAS_LOCALBOOT
|
|
; Is this a "localboot" pseudo-kernel?
|
|
cmp al,VK_LOCALBOOT ; al == KernelType
|
|
+ jne .no_local_boot
|
|
+ mov al,7
|
|
+ call [comboot_hook]
|
|
mov ax,[VKernelBuf+vk_rname] ; Possible localboot type
|
|
- je local_boot
|
|
+ jmp local_boot
|
|
+.no_local_boot:
|
|
%endif
|
|
jmp get_kernel
|
|
|
|
@@ -483,6 +487,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
|
|
@@ -525,7 +531,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
|
|
|
|
;
|
|
diff --git a/core/comboot.inc b/core/comboot.inc
|
|
index f8a7853..f6abe1b 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 19b5057..15dc8ff 100644
|
|
--- a/core/layout.inc
|
|
+++ b/core/layout.inc
|
|
@@ -141,4 +141,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 5da5bc9..033019c 100644
|
|
--- a/core/runkernel.inc
|
|
+++ b/core/runkernel.inc
|
|
@@ -168,7 +168,7 @@ opt_mem:
|
|
ret
|
|
|
|
opt_quiet:
|
|
- mov byte [QuietBoot],QUIET_FLAG
|
|
+ or byte [QuietBoot],QUIET_FLAG
|
|
ret
|
|
|
|
%if IS_PXELINUX
|
|
@@ -228,7 +228,9 @@ new_kernel:
|
|
; we were provided.
|
|
;
|
|
mov al,[es:su_loadflags]
|
|
- or al,[QuietBoot] ; Set QUIET_FLAG if needed
|
|
+ mov ah,[QuietBoot] ; Set QUIET_FLAG if needed
|
|
+ and ah,QUIET_FLAG
|
|
+ or al,ah
|
|
mov [es:su_loadflags],al
|
|
mov [LoadFlags],al
|
|
|
|
@@ -642,7 +644,7 @@ loadinitrd:
|
|
; assumes CS == DS
|
|
;
|
|
writestr_qchk:
|
|
- test byte [QuietBoot],QUIET_FLAG
|
|
+ test byte [QuietBoot],QUIET_FLAG | 2
|
|
jz writestr
|
|
ret
|
|
|
|
@@ -697,4 +699,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 0d896fc..a256ed0 100644
|
|
--- a/core/ui.inc
|
|
+++ b/core/ui.inc
|
|
@@ -616,7 +616,7 @@ kernel_good:
|
|
;
|
|
xor ax,ax
|
|
mov [InitRDPtr],ax
|
|
- mov [QuietBoot],al
|
|
+ and byte [QuietBoot],~QUIET_FLAG
|
|
%if IS_PXELINUX
|
|
mov [KeepPXE],al
|
|
%endif
|
|
diff --git a/core/runkernel.inc b/core/runkernel.inc
|
|
index 033019c..c9f37c3 100644
|
|
--- a/core/runkernel.inc
|
|
+++ b/core/runkernel.inc
|
|
@@ -266,7 +266,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
|
|
|
|
@@ -438,7 +438,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]
|
|
@@ -446,9 +446,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
|
|
|
|
@@ -702,3 +706,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 f6abe1b..8b7ee5c 100644
|
|
--- a/core/comboot.inc
|
|
+++ b/core/comboot.inc
|
|
@@ -969,6 +969,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
|
|
@@ -976,6 +1015,109 @@ 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
|
|
+; EDX memory end (sets MyHighMemSize if != 0)
|
|
+;
|
|
+comapi_run2:
|
|
+ push word P_CS
|
|
+ push word P_SI
|
|
+ pop dword [comboot_far]
|
|
+ push dword P_EDI
|
|
+ pop dword [KernelStart]
|
|
+ mov edx,P_EDX
|
|
+ or edx,edx
|
|
+ jz .nohimemsize
|
|
+%if HIGHMEM_SLOP != 0
|
|
+ sub edx,HIGHMEM_SLOP
|
|
+%endif
|
|
+.nohimemsize:
|
|
+ mov [AltHighMemSize],edx
|
|
+ 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
|
|
+
|
|
+
|
|
+;
|
|
+; INT 22h AX=0028h Get memory size
|
|
+;
|
|
+comapi_memsize:
|
|
+ push dword [HighMemSize]
|
|
+ pop dword P_EAX
|
|
+ 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
|
|
+; 7: 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
|
|
@@ -1028,8 +1170,16 @@ 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
|
|
+ dw comapi_memsize ; 0028 get memory size
|
|
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
|
|
|
|
@@ -1048,8 +1198,10 @@ 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
|
|
+AltHighMemSize resd 1
|
|
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 8b7ee5c..5adbe74 100644
|
|
--- a/core/comboot.inc
|
|
+++ b/core/comboot.inc
|
|
@@ -1050,12 +1050,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
|
|
|
|
@@ -1179,6 +1181,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
|
|
|
|
APIKeyWait db 0
|
|
APIKeyFlag db 0
|
|
diff --git a/core/ui.inc b/core/ui.inc
|
|
index a256ed0..40f7636 100644
|
|
--- a/core/ui.inc
|
|
+++ b/core/ui.inc
|
|
@@ -394,9 +394,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 5adbe74..c6bfab2 100644
|
|
--- a/core/comboot.inc
|
|
+++ b/core/comboot.inc
|
|
@@ -1095,6 +1095,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 40f7636..ef69a4d 100644
|
|
--- a/core/ui.inc
|
|
+++ b/core/ui.inc
|
|
@@ -632,7 +632,11 @@ kernel_good:
|
|
mov [KernelCNameLen],di
|
|
|
|
; Default memory limit, can be overridden by image loaders
|
|
+ mov eax,[AltHighMemSize]
|
|
+ or eax,eax
|
|
+ jnz .altsize
|
|
mov eax,[HighMemRsvd]
|
|
+.altsize:
|
|
mov [MyHighMemSize],eax
|
|
|
|
popad
|
|
@@ -653,6 +657,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 eb43708..2b1349d 100644
|
|
--- a/doc/comboot.txt
|
|
+++ b/doc/comboot.txt
|
|
@@ -949,3 +949,38 @@ 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
|
|
+ EDX if != 0: initrd load address (that is: memory end)
|
|
+ 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.
|
|
+
|
|
+AX=0028h [3.84] Get memory size
|
|
+ Input: AX 0028h
|
|
+ Output: EAX high memory size (in bytes)
|
|
+
|
|
diff --git a/modules/Makefile b/modules/Makefile
|
|
index 77020ea..e6e7905 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 int18.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..a59da40
|
|
--- /dev/null
|
|
+++ b/modules/gfxboot.c
|
|
@@ -0,0 +1,1040 @@
|
|
+/*
|
|
+ *
|
|
+ * 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 <libio.h>
|
|
+
|
|
+#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
|
|
+
|
|
+// basic memory layout in MB
|
|
+#define GFX_MEMORY_START 1
|
|
+#define GFX_MEMORY_SIZE 7
|
|
+// assume initrd needs at least that much
|
|
+#define INITRD_MIN_MEMORY 64
|
|
+
|
|
+#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;
|
|
+
|
|
+
|
|
+// e820 mem descriptor
|
|
+typedef struct __attribute__ ((packed)) {
|
|
+ uint64_t base;
|
|
+ uint64_t len;
|
|
+ uint32_t type;
|
|
+ uint32_t cont;
|
|
+} mem_info_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;
|
|
+
|
|
+unsigned initrd_end;
|
|
+unsigned kernel_start;
|
|
+
|
|
+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 get_mem_info(mem_info_t *mi);
|
|
+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);
|
|
+void show_message(char *file);
|
|
+
|
|
+
|
|
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
+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 bootlogo_file [message_file]\n");
|
|
+ if(argc > 2) show_message(argv[2]);
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if(read_config_file()) {
|
|
+ printf("Error reading config file\n");
|
|
+ if(argc > 2) show_message(argv[2]);
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if(gfx_init(argv[1])) {
|
|
+ printf("Error setting up gfxboot\n");
|
|
+ if(argc > 2) show_message(argv[2]);
|
|
+
|
|
+ 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();
|
|
+ }
|
|
+
|
|
+ if(argc > 2) show_message(argv[2]);
|
|
+
|
|
+ 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);
|
|
+ r->eax = (r->eflags & X86_CF) ? 1 : 0;
|
|
+ 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 get_mem_info(mem_info_t *mi)
|
|
+{
|
|
+ x86regs_t r;
|
|
+
|
|
+ mi->base = mi->len = mi->type = 0;
|
|
+
|
|
+ r.eax = 0xe820;
|
|
+ r.edx = 0x534d4150;
|
|
+ r.ebx = mi->cont;
|
|
+ r.ecx = 20;
|
|
+ r.es = comboot >> 4;
|
|
+ r.edi = (unsigned) mi;
|
|
+ x86int(0x15, &r);
|
|
+
|
|
+ mi->cont = 0;
|
|
+ if(r.eax != 0x534d4150 || (r.eflags & X86_CF)) return 1;
|
|
+ mi->cont = r.ebx;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
+//
|
|
+// 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;
|
|
+ unsigned start2, len2, end2;
|
|
+ mem_info_t mi;
|
|
+
|
|
+ gfx_config.mem0_start = freemem;
|
|
+ gfx_config.mem0_end = freemem + freemem_len;
|
|
+
|
|
+ kernel_start = (GFX_MEMORY_START + GFX_MEMORY_SIZE) << 20;
|
|
+ initrd_end = 0;
|
|
+
|
|
+ gfx_config.xmem_0 = (GFX_MEMORY_START << 4) + GFX_MEMORY_SIZE;
|
|
+
|
|
+ r.eax = 0x28; // Get memory size
|
|
+ x86int(0x22, &r);
|
|
+ u = (r.eflags & X86_CF) ? 0 : r.eax;
|
|
+
|
|
+ // round up
|
|
+ gfx_config.bios_mem_size = u ? ((u + 0xfffff) >> 20) << 20 : 256;
|
|
+
|
|
+ if(u > 0) {
|
|
+ // new interface
|
|
+
|
|
+ if(u < INITRD_MIN_MEMORY << 20) {
|
|
+ // ok, maybe there is a bigger block...
|
|
+
|
|
+ mi.cont = 0;
|
|
+ start2 = len2 = 0;
|
|
+ while(!get_mem_info(&mi)) {
|
|
+#if 0
|
|
+ printf(
|
|
+ "%08x%08x %08x%08x %08x %08x\n",
|
|
+ (unsigned) (mi.base >> 32), (unsigned) mi.base,
|
|
+ (unsigned) (mi.len >> 32), (unsigned) mi.len,
|
|
+ mi.type, mi.cont
|
|
+ );
|
|
+#endif
|
|
+ if(mi.type == 1) {
|
|
+ if((mi.base >> 32) || (mi.base + mi.len) >> 32) break;
|
|
+ if(mi.len > len2) {
|
|
+ start2 = mi.base;
|
|
+ len2 = mi.len;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if(!mi.cont) break;
|
|
+ }
|
|
+
|
|
+#if 0
|
|
+ printf("largest: %08x %08x\n", start2, len2);
|
|
+ getchar();
|
|
+#endif
|
|
+
|
|
+ if(len2 && len2 > 2 << 20 && len2 > u) {
|
|
+ // align to full MBs
|
|
+ end2 = (start2 + len2) & ~0xfffff;
|
|
+ start2 = (start2 + 0xfffff) & ~0xfffff;
|
|
+ len2 = end2 - start2;
|
|
+ }
|
|
+ else {
|
|
+ start2 = len2 = 0;
|
|
+ }
|
|
+
|
|
+ if(len2) {
|
|
+ u = len2;
|
|
+ initrd_end = end2;
|
|
+ // we could relocate the kernel as well...
|
|
+ // kernel_start = start2;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if(u < INITRD_MIN_MEMORY << 20) {
|
|
+ // a bit too small for us
|
|
+ printf("%u MB RAM is a bit small... - giving up\n", u >> 20);
|
|
+
|
|
+ return 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+#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 * 182 / 100;
|
|
+ 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 = kernel_start; // kernel load address
|
|
+ r.edx = initrd_end; // end of initrd load area (or 0)
|
|
+ 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->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;
|
|
+
|
|
+ case 7: // stop gfxboot
|
|
+ gfx_done();
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
+void show_message(char *file)
|
|
+{
|
|
+ int c;
|
|
+
|
|
+ if(open(file) == -1) return;
|
|
+
|
|
+ while((c = getc()) != EOF) {
|
|
+ if(c < ' ' && c != '\n' && c != '\t') continue;
|
|
+ printf("%c", c);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
diff --git a/modules/libio.asm b/modules/libio.asm
|
|
new file mode 100644
|
|
index 0000000..1f77b44
|
|
--- /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 ebx,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
|
|
+;
|
|
+; changes no regs
|
|
+;
|
|
+pf_next_arg:
|
|
+ movzx eax,word [pf_args]
|
|
+ add word [pf_args],4
|
|
+ mov eax,[eax]
|
|
+ ret
|
|
+
|
|
+
|
|
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
+; Convert string to number.
|
|
+;
|
|
+; si string
|
|
+;
|
|
+; return:
|
|
+; ecx number
|
|
+; si points past number
|
|
+; CF not a number
|
|
+;
|
|
+get_number:
|
|
+
|
|
+ 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
|
|
+
|
|
+
|
|
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
+; 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
|
|
+
|
|
+
|
|
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
+; 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
|
|
+
|
|
+
|
|
+; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
+; 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..16af520
|
|
--- /dev/null
|
|
+++ b/modules/libio.h
|
|
@@ -0,0 +1,133 @@
|
|
+/*
|
|
+ *
|
|
+ * 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 int64_t long long
|
|
+#define uint8_t unsigned char
|
|
+#define uint16_t unsigned short
|
|
+#define uint32_t unsigned
|
|
+#define uint64_t unsigned long long
|
|
+
|
|
+#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 */
|
|
+
|