diff --git a/README.gfxboot b/README.gfxboot index 3e9feae..13f9e21 100644 --- a/README.gfxboot +++ b/README.gfxboot @@ -1,4 +1,4 @@ -gfxboot is now loaded via a COM module. If you used a line like +gfxboot is now loaded via a COM32 module. If you used a line like gfxboot bootlogo @@ -6,7 +6,7 @@ before in isolinux.cfg or syslinux.cfg, change this to ui gfxboot bootlogo -and add /usr/share/syslinux/gfxboot.com to your boot directory (the one +and add /usr/share/syslinux/gfxboot.c32 to your boot directory (the one where the config file is). You can also use diff --git a/syslinux-3.86-compat.diff b/syslinux-3.86-compat.diff index 4bb5741..f4f2a88 100644 --- a/syslinux-3.86-compat.diff +++ b/syslinux-3.86-compat.diff @@ -30,7 +30,7 @@ index 65d71c9..2302536 100644 ret ; -+; "gfxboot" command; Shorthand for "ui gfxboot.com" ++; "gfxboot" command; Shorthand for "ui gfxboot.c32" +; +pc_gfxboot: + mov ax,2 @@ -51,7 +51,7 @@ index 65d71c9..2302536 100644 section .data vk_overflow_msg db 'Out of memory parsing config file', CR, LF, 0 SerialNotice db 1 ; Only print this once -+gfxboot_cmd db 'gfxboot.com ', 0 ++gfxboot_cmd db 'gfxboot.c32 ', 0 section .bss alignb 4 diff --git a/syslinux-3.86-gfxboot.diff b/syslinux-3.86-gfxboot.diff index d4c2b47..5117482 100644 --- a/syslinux-3.86-gfxboot.diff +++ b/syslinux-3.86-gfxboot.diff @@ -173,268 +173,11 @@ index 23429bd..54f2e19 100644 ; ----------------------------------------------------------------------------- ; 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 +index f8a7853..37bd0f2 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: +@@ -970,6 +970,45 @@ comapi_shufraw: mov ecx,P_ECX jmp shuffle_and_boot_raw @@ -480,231 +223,31 @@ index f6abe1b..8b7ee5c 100644 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: +@@ -1029,6 +1068,8 @@ 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) +@@ -1049,8 +1090,9 @@ feature_flags_len equ ($-feature_flags) err_notdos db ': attempted DOS system call INT ',0 err_comlarge db 'COMBOOT image too large.', CR, LF, 0 - section .bss1 + section .bss2 alignb 4 -+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 +index eb43708..13d18f6 100644 --- a/doc/comboot.txt +++ b/doc/comboot.txt -@@ -949,3 +949,38 @@ AX=0024h [3.80] Cleanup, shuffle and boot, raw version +@@ -949,3 +949,20 @@ 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. @@ -725,2120 +268,16 @@ index eb43708..2b1349d 100644 + + 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 +index 77020ea..f318364 100644 --- a/modules/Makefile +++ b/modules/Makefile -@@ -19,6 +19,11 @@ include $(topdir)/MCONFIG.embedded +@@ -19,7 +19,7 @@ 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 +-BINS = pxechain.com gfxboot.com poweroff.com int18.com ++BINS = pxechain.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 -+ -+#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 */ -+ diff --git a/syslinux.changes b/syslinux.changes index b2626c7..7289329 100644 --- a/syslinux.changes +++ b/syslinux.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Tue Apr 27 17:33:10 CEST 2010 - snwint@suse.de + +- drop obsolete gfxboot.com + ------------------------------------------------------------------- Mon Apr 19 15:41:01 CEST 2010 - snwint@suse.de diff --git a/syslinux.spec b/syslinux.spec index 1b2ed91..75905ee 100644 --- a/syslinux.spec +++ b/syslinux.spec @@ -60,6 +60,7 @@ Authors: cp %{SOURCE2} . export CFLAGS="$RPM_OPT_FLAGS" chmod +x core/add_crc +rm -f modules/gfxboot.com make spotless make