summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteffen Winterfeldt <wfeldt@opensuse.org>2009-10-06 11:24:14 +0200
committerSteffen Winterfeldt <wfeldt@opensuse.org>2009-10-06 11:24:14 +0200
commit969a3ef83aa4bb31248a7a0f0039649eae94e4a4 (patch)
tree891261ba7afe46f5a57d943d9b8c6eb42cde869b
parent6d30a2ae910cc57f79d06adbc417df456f270eca (diff)
- added syslinux-3.82 patchset
-rw-r--r--VERSION2
-rw-r--r--patches/syslinux-3.82/01_isolinux_mount_chdir.diff175
-rw-r--r--patches/syslinux-3.82/02_comboot_hooks.diff103
-rw-r--r--patches/syslinux-3.82/03_comboot_ne_real_mode_seg.diff44
-rw-r--r--patches/syslinux-3.82/04_new_quiet_flag.diff43
-rw-r--r--patches/syslinux-3.82/05_variable_kernel_address.diff42
-rw-r--r--patches/syslinux-3.82/06_comboot_new_api.diff188
-rw-r--r--patches/syslinux-3.82/07_no_append.diff45
-rw-r--r--patches/syslinux-3.82/08_kernel_size.diff36
-rw-r--r--patches/syslinux-3.82/09_doc.diff43
-rw-r--r--patches/syslinux-3.82/10_gfxboot_c.diff2095
11 files changed, 2815 insertions, 1 deletions
diff --git a/VERSION b/VERSION
index d9b366b..0678bba 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-4.1.30
+4.1.31
diff --git a/patches/syslinux-3.82/01_isolinux_mount_chdir.diff b/patches/syslinux-3.82/01_isolinux_mount_chdir.diff
new file mode 100644
index 0000000..3881586
--- /dev/null
+++ b/patches/syslinux-3.82/01_isolinux_mount_chdir.diff
@@ -0,0 +1,175 @@
+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/patches/syslinux-3.82/02_comboot_hooks.diff b/patches/syslinux-3.82/02_comboot_hooks.diff
new file mode 100644
index 0000000..b2e9f8f
--- /dev/null
+++ b/patches/syslinux-3.82/02_comboot_hooks.diff
@@ -0,0 +1,103 @@
+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 8bfc8b8..f458fc7 100644
+--- a/core/runkernel.inc
++++ b/core/runkernel.inc
+@@ -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
+@@ -319,6 +321,9 @@ load_initrd:
+ ;
+ call abort_check ; Last chance!!
+
++ mov al,6
++ call [comboot_hook]
++
+ mov si,ready_msg
+ call writestr_qchk
+
+@@ -489,6 +494,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 +620,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 1b40717..be4f385 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
+
+ ;
diff --git a/patches/syslinux-3.82/03_comboot_ne_real_mode_seg.diff b/patches/syslinux-3.82/03_comboot_ne_real_mode_seg.diff
new file mode 100644
index 0000000..fe319bf
--- /dev/null
+++ b/patches/syslinux-3.82/03_comboot_ne_real_mode_seg.diff
@@ -0,0 +1,44 @@
+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/patches/syslinux-3.82/04_new_quiet_flag.diff b/patches/syslinux-3.82/04_new_quiet_flag.diff
new file mode 100644
index 0000000..d445b49
--- /dev/null
+++ b/patches/syslinux-3.82/04_new_quiet_flag.diff
@@ -0,0 +1,43 @@
+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
+- mov [QuietBoot],al
++ and byte [QuietBoot],~1
+ %if IS_PXELINUX
+ mov [KeepPXE],al
+ %endif
diff --git a/patches/syslinux-3.82/05_variable_kernel_address.diff b/patches/syslinux-3.82/05_variable_kernel_address.diff
new file mode 100644
index 0000000..a494529
--- /dev/null
+++ b/patches/syslinux-3.82/05_variable_kernel_address.diff
@@ -0,0 +1,42 @@
+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
+
+ 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/patches/syslinux-3.82/06_comboot_new_api.diff b/patches/syslinux-3.82/06_comboot_new_api.diff
new file mode 100644
index 0000000..a1db0b9
--- /dev/null
+++ b/patches/syslinux-3.82/06_comboot_new_api.diff
@@ -0,0 +1,188 @@
+diff --git a/core/comboot.inc b/core/comboot.inc
+index 1a1dbfe..1a147c9 100644
+--- a/core/comboot.inc
++++ b/core/comboot.inc
+@@ -962,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
+@@ -969,6 +1008,108 @@ 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
++;
++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
+@@ -1021,8 +1162,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
+
+@@ -1041,8 +1190,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/patches/syslinux-3.82/07_no_append.diff b/patches/syslinux-3.82/07_no_append.diff
new file mode 100644
index 0000000..d0e572e
--- /dev/null
+++ b/patches/syslinux-3.82/07_no_append.diff
@@ -0,0 +1,45 @@
+diff --git a/core/comboot.inc b/core/comboot.inc
+index 1a147c9..e5dc115 100644
+--- a/core/comboot.inc
++++ b/core/comboot.inc
+@@ -1043,12 +1043,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
+
+@@ -1171,6 +1173,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 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/patches/syslinux-3.82/08_kernel_size.diff b/patches/syslinux-3.82/08_kernel_size.diff
new file mode 100644
index 0000000..d06dfa8
--- /dev/null
+++ b/patches/syslinux-3.82/08_kernel_size.diff
@@ -0,0 +1,36 @@
+diff --git a/core/comboot.inc b/core/comboot.inc
+index e5dc115..60506ce 100644
+--- a/core/comboot.inc
++++ b/core/comboot.inc
+@@ -1087,6 +1087,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..d56c148 100644
+--- a/core/ui.inc
++++ b/core/ui.inc
+@@ -612,7 +612,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
+@@ -633,6 +637,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/patches/syslinux-3.82/09_doc.diff b/patches/syslinux-3.82/09_doc.diff
new file mode 100644
index 0000000..6f8a8cf
--- /dev/null
+++ b/patches/syslinux-3.82/09_doc.diff
@@ -0,0 +1,43 @@
+diff --git a/doc/comboot.txt b/doc/comboot.txt
+index f5fefda..1450021 100644
+--- a/doc/comboot.txt
++++ b/doc/comboot.txt
+@@ -955,3 +955,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/patches/syslinux-3.82/10_gfxboot_c.diff b/patches/syslinux-3.82/10_gfxboot_c.diff
new file mode 100644
index 0000000..168cb0e
--- /dev/null
+++ b/patches/syslinux-3.82/10_gfxboot_c.diff
@@ -0,0 +1,2095 @@
+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..b4a794c
+--- /dev/null
++++ b/modules/gfxboot.c
+@@ -0,0 +1,1036 @@
++/*
++ *
++ * 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);
++ 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;
++ 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->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;
++ }
++}
++
++
++// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
++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 */
++