diff options
author | hpa <hpa> | 2002-06-11 05:48:29 +0000 |
---|---|---|
committer | hpa <hpa> | 2002-06-11 05:48:29 +0000 |
commit | abac6f53695c0b99e0235ca3da81ab3cd822f475 (patch) | |
tree | 42c9c90abcb685ec654b25e680f6a0e272d1fe52 | |
parent | 73d0682dcdd250939e560d333b591d7a5a8299ca (diff) | |
download | syslinux-abac6f53695c0b99e0235ca3da81ab3cd822f475.tar.gz |
Add an API for COMBOOT images, and add support for "COM32" -- 32-bit
linear .com files.
-rw-r--r-- | Makefile | 29 | ||||
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | bcopy32.inc | 5 | ||||
-rw-r--r-- | com32.inc | 319 | ||||
-rw-r--r-- | comboot.doc | 266 | ||||
-rw-r--r-- | comboot.inc | 277 | ||||
-rw-r--r-- | config.inc | 7 | ||||
-rw-r--r-- | conio.inc | 2 | ||||
-rw-r--r-- | cpuinit.inc | 38 | ||||
-rw-r--r-- | highmem.inc | 107 | ||||
-rw-r--r-- | isolinux.asm | 15 | ||||
-rw-r--r-- | ldlinux.asm | 18 | ||||
-rw-r--r-- | pxelinux.asm | 21 | ||||
-rw-r--r-- | runkernel.inc | 82 | ||||
-rw-r--r-- | sample/Makefile | 18 | ||||
-rw-r--r-- | sample/hello.c | 47 | ||||
-rw-r--r-- | version | 2 | ||||
-rwxr-xr-x | version.pl | 25 |
18 files changed, 1102 insertions, 181 deletions
@@ -41,12 +41,13 @@ CSRC = syslinux.c gethostip.c NASMSRC = ldlinux.asm syslinux.asm copybs.asm \ pxelinux.asm mbr.asm isolinux.asm isolinux-debug.asm SOURCES = $(CSRC) $(NASMSRC) *.inc -BTARGET = kwdhash.gen ldlinux.bss ldlinux.sys ldlinux.bin \ +BTARGET = kwdhash.gen version.gen ldlinux.bss ldlinux.sys ldlinux.bin \ pxelinux.0 mbr.bin isolinux.bin isolinux-debug.bin ITARGET = syslinux.com syslinux copybs.com gethostip DOCS = COPYING NEWS README TODO *.doc sample OTHER = Makefile bin2c.pl now.pl genhash.pl keywords findpatch.pl \ - keytab-lilo.pl version sys2ansi.pl ppmtolss16 lss16toppm memdisk + keytab-lilo.pl version version.pl sys2ansi.pl \ + ppmtolss16 lss16toppm memdisk OBSOLETE = pxelinux.bin # Things to install in /usr/bin @@ -79,22 +80,22 @@ samples: memdisk: $(MAKE) -C memdisk all +version.gen: version version.pl + $(PERL) version.pl version + kwdhash.gen: keywords genhash.pl $(PERL) genhash.pl < keywords > kwdhash.gen -ldlinux.bin: ldlinux.asm kwdhash.gen - $(NASM) -f bin -dVERSION="'$(VERSION)'" -dDATE_STR="'$(DATE)'" \ - -dHEXDATE="$(HEXDATE)" \ +ldlinux.bin: ldlinux.asm kwdhash.gen version.gen + $(NASM) -f bin -DDATE_STR="'$(DATE)'" -DHEXDATE="$(HEXDATE)" \ -l ldlinux.lst -o ldlinux.bin ldlinux.asm -pxelinux.bin: pxelinux.asm kwdhash.gen - $(NASM) -f bin -dVERSION="'$(VERSION)'" -dDATE_STR="'$(DATE)'" \ - -dHEXDATE="$(HEXDATE)" \ +pxelinux.bin: pxelinux.asm kwdhash.gen version.gen + $(NASM) -f bin -DDATE_STR="'$(DATE)'" -DHEXDATE="$(HEXDATE)" \ -l pxelinux.lst -o pxelinux.bin pxelinux.asm -isolinux.bin: isolinux.asm kwdhash.gen - $(NASM) -f bin -dVERSION="'$(VERSION)'" -dDATE_STR="'$(DATE)'" \ - -dHEXDATE="$(HEXDATE)" \ +isolinux.bin: isolinux.asm kwdhash.gen version.gen + $(NASM) -f bin -DDATE_STR="'$(DATE)'" -DHEXDATE="$(HEXDATE)" \ -l isolinux.lst -o isolinux.bin isolinux.asm pxelinux.0: pxelinux.bin @@ -102,8 +103,7 @@ pxelinux.0: pxelinux.bin # Special verbose version of isolinux.bin isolinux-debug.bin: isolinux-debug.asm kwdhash.gen - $(NASM) -f bin -dVERSION="'$(VERSION)'" -dDATE_STR="'$(DATE)'" \ - -dHEXDATE="$(HEXDATE)" \ + $(NASM) -f bin -DDATE_STR="'$(DATE)'" -DHEXDATE="$(HEXDATE)" \ -l isolinux-debug.lst -o isolinux-debug.bin isolinux-debug.asm ldlinux.bss: ldlinux.bin @@ -136,7 +136,8 @@ syslinux: syslinux.o bootsect_bin.o ldlinux_bin.o syslinux.o bootsect_bin.o ldlinux_bin.o syslinux.o: syslinux.c patch.offset - $(CC) $(INCLUDE) $(CFLAGS) -DPATCH_OFFSET=`cat patch.offset` -c -o $@ $< + $(CC) $(INCLUDE) $(CFLAGS) -DPATCH_OFFSET=`cat patch.offset` \ + -c -o $@ $< gethostip.o: gethostip.c @@ -1,6 +1,11 @@ Starting with 1.47, changes marked with SYSLINUX/PXELINUX/ISOLINUX apply to that specific program only; other changes apply to both. +Changes in 2.00: + * ALL: Add support for "COM32" (32-bit COMBOOT) images. + * ALL: Add an API for COMBOOT/COM32 images. See comboot.doc + for details. + Changes in 1.75: * ALL: NASM 0.98.32 or later is now required to build SYSLINUX from sources. diff --git a/bcopy32.inc b/bcopy32.inc index d81f00b7..c3be39a9 100644 --- a/bcopy32.inc +++ b/bcopy32.inc @@ -43,6 +43,11 @@ bcopy_gdt: dw bcopy_gdt_size-1 ; Null descriptor - contains GDT dd 008f9300h ; present, dpl 0, cover all 4G dd 0000ffffh ; Data segment, use16, read/write, dd 00009300h ; present, dpl 0, cover 64K + ; The rest are used for COM32 only + dd 0000ffffh ; Code segment, use32, readable, + dd 00cf9b00h ; present, dpl 0, cover all 4G + dd 0000ffffh ; Data segment, use32, read/write, + dd 00cf9300h ; present, dpl 0, cover all 4G bcopy_gdt_size: equ $-bcopy_gdt ; diff --git a/com32.inc b/com32.inc new file mode 100644 index 00000000..ac0440f8 --- /dev/null +++ b/com32.inc @@ -0,0 +1,319 @@ +;; $Id$ +;; ----------------------------------------------------------------------- +;; +;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved +;; +;; 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, +;; Bostom MA 02111-1307, USA; either version 2 of the License, or +;; (at your option) any later version; incorporated herein by reference. +;; +;; ----------------------------------------------------------------------- + +;; +;; com32.inc +;; +;; Common code for running a COM32 image +;; + +; +; Load a COM32 image. A COM32 image is the 32-bit analogue to a DOS +; .com file. A COM32 image is loaded at address 0x101000, with %esp +; set to the high end of usable memory. +; +; A COM32 image should begin with the magic bytes: +; B8 FF 4C CD 21, which is "mov eax,0x21cd4cff" in 32-bit mode and +; "mov ax,0x4cff; int 0x21" in 16-bit mode. This will abort the +; program with an error if run in 16-bit mode. +; +pm_idt: equ 0x100000 +pm_entry: equ 0x101000 + + bits 16 + align 2 +com32_pmidt: + dw 8*256 ; Limit + dd pm_idt ; Address + +com32_rmidt: + dw 0ffffh ; Limit + dd 0 ; Address + +is_com32_image: + call highmemsize ; We need the high memory size... + call comboot_setup_api ; Set up the COMBOOT-style API + + mov edi,pm_entry ; Load address + xchg eax,edx ; Gotta fix this insanity... + shl eax,16 + mov ax,dx + call load_high + call crlf + +com32_start: + mov ebx,com32_call_start ; Where to go in PM + +com32_enter_pm: + mov [SavedSSSP],sp + mov [SavedSSSP+2],ss + + cli + cld + call a20_test + jnz .a20ok + call enable_a20 + +.a20ok: + lgdt [bcopy_gdt] ; We can use the same GDT just fine + lidt [com32_pmidt] ; Set up the IDT + mov eax,cr0 + or al,1 + mov cr0,eax ; Enter protected mode + jmp 20h:.in_pm + + bits 32 +.in_pm: + xor eax,eax ; Available for future use... + mov fs,eax + mov gs,eax + + mov al,28h ; Set up data segments + mov es,eax + mov ds,eax + mov ss,eax + + mov esp,[PMESP] ; Load protmode %esp if available + jmp ebx ; Go to where we need to go + +; +; This is invoked right before the actually starting the COM32 +; progam, in 32-bit mode... +; +com32_call_start: + ; + ; Point the stack to the end of high memory + ; + mov esp,[word HighMemSize] + + ; + ; Set up the protmode IDT and the interrupt jump buffers + ; We set these up in the system area at 0x100000, + ; but we could also put them beyond the stack. + ; + mov edi,pm_idt + + ; Form an interrupt gate descriptor + mov eax,0x00200000+((pm_idt+8*256)&0x0000ffff) + mov ebx,0x0000ee00+((pm_idt+8*256)&0xffff0000) + xor ecx,ecx + inc ch ; ecx <- 256 + + push ecx +.make_idt: + stosd + add eax,8 + xchg eax,ebx + stosd + xchg eax,ebx + loop .make_idt + + pop ecx + + ; Each entry in the interrupt jump buffer contains + ; the following instructions: + ; + ; 00000000 60 pushad + ; 00000001 B0xx mov al,<interrupt#> + ; 00000003 E9xxxxxxxx jmp com32_handle_interrupt + + mov eax,0e900b060h + mov ebx,com32_handle_interrupt-(pm_idt+8*256+8) + +.make_ijb: + stosd + sub [edi-2],cl ; Interrupt # + xchg eax,ebx + stosd + sub eax,8 + xchg eax,ebx + loop .make_ijb + + ; Now everything is set up for interrupts... + + push dword (1 << 16) ; 64K bounce buffer + push dword (comboot_seg << 4) ; Bounce buffer address + push dword com32_syscall ; Syscall entry point + movzx esi,word [word CmdOptPtr] + push esi ; Command line pointer + push dword 4 ; Argument count + sti ; Interrupts OK now + call pm_entry ; Run the program... + ; ... on return, fall through to com32_exit ... + +com32_exit: + mov bx,com32_done ; Return to command loop + +com32_enter_rm: + cli + cld + mov [PMESP],esp ; Save exit %esp + xor esp,esp ; Make sure the high bits are zero + jmp 08h:.in_pm16 ; Return to 16-bit mode first + + bits 16 +.in_pm16: + mov ax,18h ; Real-mode-like segment + mov es,ax + mov ds,ax + mov ss,ax + mov fs,ax + mov gs,ax + + lidt [com32_rmidt] ; Real-mode IDT (rm needs no GDT) + mov eax,cr0 + and al,~1 + mov cr0,eax + jmp 0:.in_rm + +.in_rm: ; Back in real mode + mov ax,cs ; Set up sane segments + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + lss sp,[SavedSSSP] ; Restore stack + jmp bx ; Go to whereever we need to go... + +com32_done: + call disable_a20 + sti + jmp enter_command + +; +; 16-bit support code +; + bits 16 + +; +; 16-bit interrupt-handling code +; +com32_int_rm: + pushf ; Flags on stack + push cs ; Return segment + push word .cont ; Return address + push dword edx ; Segment:offset of IVT entry + retf ; Invoke IVT routine +.cont: ; ... on resume ... + mov ebx,com32_int_resume + jmp com32_enter_pm ; Go back to PM + +; +; 16-bit system call handling code +; +com32_sys_rm: + pop gs + pop fs + pop es + pop ds + popad + popfd + retf ; Invoke routine +.return: + pushfd + pushad + push ds + push es + push fs + push gs + mov ebx,com32_sys_resume + jmp com32_enter_pm + +; +; 32-bit support code +; + bits 32 + +; +; This is invoked on getting an interrupt in protected mode. At +; this point, we need to context-switch to real mode and invoke +; the interrupt routine. +; +; When this gets invoked, the registers are saved on the stack and +; AL contains the register number. +; +com32_handle_interrupt: + movzx eax,al + xor ebx,ebx ; Actually makes the code smaller + mov edx,[ebx+eax*4] ; Get the segment:offset of the routine + mov bx,com32_int_rm + jmp com32_enter_rm ; Go to real mode + +com32_int_resume: + popad + iret + +; +; Syscall invocation. We manifest a structure on the real-mode stack, +; containing the com32sys_t structure from <com32.h> as well as +; the following entries (from low to high address): +; - Target offset +; - Target segment +; - Return offset +; - Return segment (== real mode cs == 0) +; - Return flags +; +com32_syscall: + pushfd ; Save IF among other things... + pushad ; We only need to save some, but... + cld + + movzx edi,word [word SavedSSSP] + movzx eax,word [word SavedSSSP+2] + sub edi,54 ; Allocate 54 bytes + mov [word SavedSSSP],di + shl eax,4 + add edi,eax ; Create linear address + + mov esi,[esp+11*4] ; Source regs + xor ecx,ecx + mov cl,11 ; 44 bytes to copy + rep movsd + + movzx eax,byte [esp+10*4] ; Interrupt number + ; ecx == 0 here; adding it to the EA makes the + ; encoding smaller + mov eax,[ecx+eax*4] ; Get IVT entry + stosd ; Save in stack frame + mov eax,com32_sys_rm.return ; Return seg:offs + stosd ; Save in stack frame + mov eax,[edi-12] ; Return flags + and eax,0x200cd7 ; Mask (potentially) unsafe flags + mov [edi-12],eax ; Primary flags entry + stosw ; Return flags + + mov bx,com32_sys_rm + jmp com32_enter_rm ; Go to real mode + + ; On return, the 44-byte return structure is on the + ; real-mode stack. +com32_sys_resume: + movzx esi,word [word SavedSSSP] + movzx eax,word [word SavedSSSP+2] + mov edi,[esp+12*4] ; Dest regs + shl eax,4 + add esi,eax ; Create linear address + and edi,edi ; NULL pointer? + jnz .do_copy +.no_copy: mov edi,esi ; Do a dummy copy-to-self +.do_copy: xor ecx,ecx + mov cl,11 ; 44 bytes + rep movsd ; Copy register block + + add dword [word SavedSSSP],44 ; Remove from stack + + popad + popfd + ret ; Return to 32-bit program + + bits 16 diff --git a/comboot.doc b/comboot.doc new file mode 100644 index 00000000..db9203ac --- /dev/null +++ b/comboot.doc @@ -0,0 +1,266 @@ +$Id$ + + COMBOOT and COM32 files + + +SYSLINUX supports simple standalone programs, using a file format +similar to DOS ".com" files. A 32-bit version, called COM32, is also +provided. A simple API provides access to a limited set of filesystem +and console functions. + + + ++++ COMBOOT file format ++++ + +A COMBOOT file is a raw binary file containing 16-bit code. It should +be linked to run at offset 0x100, and contain no absolute segment +references. It is run in 16-bit real mode. + +A COMBOOT image can be written to be compatible with MS-DOS. Such a +file will usually have extension ".com". A COMBOOT file which is not +compatible with MS-DOS will usually have extension ".cbt". + +Before running the program, SYSLINUX sets up the following fields in +the Program Segment Prefix (PSP), a structure at offset 0 in the +program segment: + + Offset Size Meaning + 0 word Contains an INT 20h instruction + 2 word Contains the paragraph (16-byte "segment" address) at + the end of memory available to the program. + 128 byte Length of the command line arguments, including the leading + space but not including the final CR character. + 129 127b Command line arguments, starting with a space and ending + with a CR character (ASCII 13). + +The program is allowed to use memory between the PSP paragraph (which +all the CS, DS, ES and SS registers point to at program start) and the +paragraph value given at offset 2. + +On startup, SP is set up to point to the end of the 64K segment, at +0xfffe. Under DOS it is possible for SP to contain a smaller +value if memory is very tight; this is never the case under SYSLINUX. + +The program should make no assumptions about what segment address it +will be loaded at; instead it should look at the segment registers on +program startup. Both DOS and SYSLINUX will guarantee CS == DS == ES +== SS on program start; the program should not assume anything about +the values of FS or GS. + +To exit, a program can either execute a near RET (which will jump to +offset 0 which contains an INT 20h instruction, terminating the +program), or execute INT 20h or INT 21h AH=00h or INT 21h AH=4Ch. +If compatiblity with SYSLINUX 1.xx is desired, use INT 20h. + + + ++++ COM32 file format ++++ + +A COM32 file is a raw binary file containing 32-bit code. It should +be linked to run at address 0x101000, and should not contain any +segment references. It will be run in flat-memory 32-bit protected +mode. Under SYSLINUX, it will be run in CPL 0, however, since it may +be possible to create a COM32 execution engine that would run under +something like Linux DOSEMU, it is recommended that the code does not +assume CPL 0 unless absolutely necessary. + +A COM32 file should have extension ".c32". + +On startup, CS will be set up as a flat 32-bit code segment, and DS == +ES == SS will be set up as the equivalent flat 32-bit data segment. +FS and GS are reserved for future use and are currently initialized to +zero. A COM32 image should not assume any particular values of +segment selectors. + +ESP is set up at the end of available memory and also serves as +notification to the program how much memory is available. + +The following arguments are passed to the program on the stack: + + Address Size Meaning + [ESP+4] dword Number of additional arguments (currently 4) + [ESP+8] dword Pointer to the command line arguments (null-terminated string) + [ESP+12] dword Pointer to system call helper function + [ESP+16] dword Pointer to low memory bounce buffer + [ESP+20] dword Size of low memory bounce buffer + +This corresponds to the following C prototype, available in the file com32.h: + +/* The standard prototype for _start() */ +int _start(unsigned int __nargs, + char *__cmdline, + void (*__syscall)(unsigned char, com32sys_t *, com32sys_t *), + void *__bounce_ptr, + unsigned int __bounce_len); + +The system call helper function can be used to issue BIOS or SYSLINUX +API calls, and takes the interrupt number as first argument. The +second argument is a pointer to the input register definition, an +instance of the following structure (also available in com32.h): + +typedef struct { + unsigned short gs; /* Offset 0 */ + unsigned short fs; /* Offset 2 */ + unsigned short es; /* Offset 4 */ + unsigned short ds; /* Offset 6 */ + + unsigned int edi; /* Offset 8 */ + unsigned int esi; /* Offset 12 */ + unsigned int ebp; /* Offset 16 */ + unsigned int _unused; /* Offset 20 */ + unsigned int ebx; /* Offset 24 */ + unsigned int edx; /* Offset 28 */ + unsigned int ecx; /* Offset 32 */ + unsigned int eax; /* Offset 36 */ + + unsigned int eflags; /* Offset 40 */ +} com32sys_t; + +The third argument is a pointer to the output register definition, an +instance of the same structure. The third argument can also be zero +(NULL). + +Since BIOS or SYSLINUX API calls can generally only manipulate data +below address 0x100000, a "bounce buffer" in low memory, at least 64K +in size, is available, to copy data in and out. + + + ++++ SYSLINUX API CALLS +++ + +SYSLINUX provides the following API calls. SYSLINUX 1.xx only +supported INT 20h - terminate program. + + + ++++ DOS-COMPATIBLE API CALLS ++++ + +INT 20h: Terminate program +INT 21h AH=00h Terminate program + + ++++ SYSLINUX-SPECIFIC API CALLS ++++ + +SYSLINUX-specific API calls are executed using INT 22h, with a +function number in AX. INT 22h is used by DOS for internal purposes; +do not execute INT 22h under DOS. + +DOS-compatible function INT 21h, AH=30h can be used to detect if the +SYSLINUX API calls are available. + +All INT 22h API calls may clobber the general-purpose registers (EAX, +EBX, ECX, EDX, EBP, ESI and EDI). Segment registers are left +unchanged unless otherwise noted. + +All calls return CF=0 on success, CF=1 on failure. The noted outputs +apply if CF=0 only unless otherwise noted. + + +AX=0000h No Operation + + Input: AX 0000h + Output: None + + This API call does nothing. + + +AX=0001h Get Version + + Input: AX 0001h + Output: AX number of INT 22h API functions available + CH SYSLINUX major version number + CL SYSLINUX minor version number + DL SYSLINUX derivative ID (e.g. 32h = PXELINUX) + ES:SI SYSLINUX version string + ES:DI SYSLINUX copyright string + + This API call returns the SYSLINUX version and API + information. + + +AX=0002h Write String + + Input: AX 0002h + ES:BX null-terminated string + Output: None + + Writes a null-terminated string on the console. + + +AX=0003h Run command + + Input: AX 0003h + ES:BX null-terminated command string + Output: None + + This API call terminates the program and executes the command + string as if the user had entered it at the SYSLINUX command + line. This API call does not return. + + +AX=0004h Run default command + + Input: AX 0004h + Output: None + + This API call terminates the program and executes the default + command string as if the user had pressed Enter alone on the + SYSLINUX command line. This API call does not return. + + +AX=0005h Force text mode + + Input: AX 0005h + Output: None + + If the screen was in graphics mode (due to displaying a splash + screen using the <Ctrl-X> command in a message file, or + similar), return to text mode. + + +AX=0006h Open file + + Input: AX 0006h + ES:SI null-terminated filename + Output: SI file handle + EAX length of file in bytes + CX file block size + + Open a file for reading. The exact syntax of the filenames + allowed depends on the particular SYSLINUX derivative. + + The SYSLINUX file system is block-oriented. The size of a + block will always be a power of two and no greater than 16K. + + Note: SYSLINUX considers a zero-length file to be nonexistent. + + +AX=0007h Read file + + Input: AX 0007h + SI file handle + ES:BX buffer + CX number of blocks to read + Output: SI file handle, or 0 if EOF was reached + + Read blocks from a file. Note that the file handle that is + returned in SI may not be the same value that was passed in. + + If end of file was reached (SI=0), the file was automatically + closed. + + The address of the buffer (ES:BX) should be at least 512-byte + aligned. SYSLINUX guarantees at least this alignment for the + COMBOOT load segment or the COM32 bounce buffer. + + WARNING: Calling this function with an invalid file handle + will probably crash the system. + + +AX=0008h Close file + + Input: AX 0008h + SI file handle + Output: None + + Close a file before reaching the end of file. + + WARNING: Calling this function with an invalid file handle + will probably crash the system. + + diff --git a/comboot.inc b/comboot.inc index 5d7019ed..319e5005 100644 --- a/comboot.inc +++ b/comboot.inc @@ -21,7 +21,7 @@ comboot_too_large: mov si,err_comlarge call cwritestr -cb_enter: jmp enter_command + jmp enter_command ; ; Load a COMBOOT image. A COMBOOT image is basically a DOS .COM file, @@ -34,17 +34,7 @@ is_comboot_image: cmp ax,0ff00h ; Max size in bytes jae comboot_too_large - ; - ; Set up the DOS vectors in the IVT (INT 20h-3fh) - ; - mov di,4*0x20 ; DOS interrupt vectors - mov eax,comboot_return - stosd - mov ax,comboot_int21 - stosd - mov ax,comboot_bogus - mov cx,30 ; All remaining DOS vectors - rep stosd + call comboot_setup_api mov cx,comboot_seg mov es,cx @@ -84,8 +74,6 @@ comboot_end_cmd: mov al,0Dh ; CR after last character mov [SavedSSSP],sp mov [SavedSSSP+2],ss ; Save away SS:SP - call vgaclearmode ; Reset video - mov ax,es mov ds,ax mov ss,ax @@ -99,9 +87,40 @@ comboot_return: cli ; Don't trust anyone xor ax,ax jmp comboot_exit +; +; Set up the COMBOOT API interrupt vectors. This is also used +; by the COM32 code. +; +comboot_setup_api: + mov di,4*0x20 ; DOS interrupt vectors + mov eax,comboot_return ; INT 20h = exit + stosd + mov ax,comboot_int21 ; INT 21h = DOS-compatible syscalls + stosd + mov ax,comboot_int22 ; INT 22h = proprietary syscalls + stosd + mov ax,comboot_bogus + mov cx,29 ; All remaining DOS vectors + rep stosd + ret + ; INT 21h: generic DOS system call -comboot_int21: and ah,ah ; 00 = return +comboot_int21: push ds + push cs + pop ds ; Set DS <- CS + and ah,ah ; 00 = return je comboot_return + cmp ah,02h + jb comboot_getkeyecho ; 01 = get key with echo + je comboot_writechr ; 02 = writechr + cmp ah,08h ; 08 = get key w/o echo + je comboot_getkey + cmp ah,09h ; 09 = writestr + je comboot_writestr + cmp ah,0Bh ; 0B = check keyboard + je comboot_checkkey + cmp ah,30h ; 30 = check version + je comboot_checkver cmp ah,4Ch ; 4C = return with status je comboot_return @@ -110,15 +129,18 @@ comboot_int21: and ah,ah ; 00 = return ; Attempted to execute non-21h DOS system call comboot_bogus: cli ; Don't trust anyone mov ax,err_notdos - ; ; Generic COMBOOT return to command line code +; AX -> message (if any) +; BX -> where to go next ; comboot_exit: - lss sp,[cs:SavedSSSP] + mov bx,enter_command ; Normal return to command prompt +comboot_exit_special: xor dx,dx mov ds,dx mov es,dx + lss sp,[SavedSSSP] sti cld and ax,ax @@ -127,5 +149,224 @@ comboot_exit: call cwritestr xchg si,ax call cwritestr -.nomsg: jmp cb_enter +.nomsg: jmp bx + +; +; INT 21h system calls +; +comboot_getkeyecho: ; 01 = get key with echo + call vgashowcursor + call getchar + call vgahidecursor + call writechr + jmp comboot_resume_ok + +comboot_writechr: ; 02 = writechr + xchg ax,dx + call writechr + xchg ax,dx + jmp comboot_resume_ok + +comboot_getkey: ; 08 = get key w/o echo + call vgashowcursor + call getchar + call vgahidecursor + jmp comboot_resume_ok + +comboot_writestr: ; 09 = write string + pusha + push es + mov bp,sp + mov es,[bp-20] ; Old DS + mov si,dx +.loop: es lodsb + cmp al,'$' ; End string with $ - bizarre + je .done + call writechr + jmp short .loop +.done: pop es + popa + jmp comboot_resume_ok + +comboot_checkkey: ; 0B = check keyboard status + call pollchar + setz al + dec al ; AL = 0FFh if present, 0 if not + jmp comboot_resume_ok + +comboot_checkver: ; 30 = check DOS version + ; We return 0 in all DOS-compatible version registers, + ; but the high part of eax-ebx-ecx-edx spell "SYSLINUX" + mov eax,'SY' << 16 + mov ebx,'SL' << 16 + mov ecx,'IN' << 16 + mov edx,'UX' << 16 + ;jmp comboot_resume_ok + +; +; Resume comboot execution +; +comboot_resume_ok: + clc +comboot_resume: + pop ds + iret + +comboot_apierr: + stc + jmp comboot_resume + +; +; INT 22h - SYSLINUX-specific system calls +; System call number in ax +; +comboot_int22: + push ds + push cs + pop ds + + cmp ax,int22_count + jae comboot_apierr + + xchg ax,bx + add bx,bx + call [bx+int22_table] + jmp comboot_resume ; On return + +; +; INT 22h AX=0000h Null system call +; INT 22h AX=0001h Get SYSLINUX version +; +comapi_get_version: + ; Number of API functions supported + mov ax,int22_count + ; SYSLINUX version + mov cx,(VER_MAJOR << 8)+VER_MINOR + ; SYSLINUX derivative ID byte + mov dx,my_id + ; For future use + xor bx,bx + + push cs + pop es + ; ES:SI -> version banner + mov si,syslinux_banner + ; ES:DI -> copyright string + mov di,copyright_str + +comapi_nop: + clc + ret + +; +; INT 22h AX=0002h Write string +; +; Write null-terminated string in ES:BX +; +comapi_writestr: + push es + pop ds + mov si,ax + jmp writestr ; Write string from ES:BX + +; +; INT 22h AX=0003h Run command +; +; Terminates the COMBOOT program and executes the command line in +; ES:BX as if it had been entered by the user. +; +comapi_run: + push es + push ds + pop es + pop ds + mov si,ax + mov di,command_line +.copyloop: + lodsb + stosb + and al,al + jnz .copyloop + xor ax,ax + mov bx,load_kernel ; Run a new kernel + jmp comboot_exit_special ; Terminate task, clean up + +; +; INT 22h AX=0004h Run default command +; +; Terminates the COMBOOT program and executes the default command line +; as if a timeout had happened or the user pressed <Enter>. +; +comapi_run_default: + mov bx,auto_boot + jmp comboot_exit_special + +; +; INT 22h AX=0005h Force text mode +; +; Puts the video in standard text mode +; +comapi_textmode: + call vgaclearmode + clc + ret + +; +; INT 22h AX=0006h Open file +; +comapi_open: + push ds + push ds + push es + pop ds + pop es + mov di,InitRD + push di + call mangle_name + pop di + pop ds + call searchdir + jz .err + xchg eax,edx + shr eax,16 + xchg ax,dx + mov cx,[SecPerClust] + clc + ret +.err: + stc + ret + + +; +; INT 22h AX=0007h Read file +; +comapi_read: + xchg ax,bx + call getfssec + jnc .noteof + xor si,si ; SI <- 0 on EOF, CF <- 0 +.noteof: ret + +; +; INT 22h AX=0008h Close file +; +comapi_close: + ; Do nothing for now. Eventually implement + ; an internal API for this. + clc + ret + + align 2, db 0 +int22_table: + dw comapi_nop ; 0000 null syscall + dw comapi_get_version ; 0001 get SYSLINUX version + dw comapi_writestr ; 0002 write string + dw comapi_run ; 0003 run specified command + dw comapi_run_default ; 0004 run default command + dw comapi_textmode ; 0005 force text mode + dw comapi_open ; 0006 open file + dw comapi_read ; 0007 read file + dw comapi_close ; 0008 close file +int22_count equ ($-int22_table)/2 @@ -28,6 +28,13 @@ BAUD_DIVISOR equ 115200 ; Serial port parameter %assign DO_WBINVD 0 ; Should we use WBINVD or not? ; +; Version number definitinons +; +%ifndef DEPEND ; Generated file +%include "version.gen" +%endif + +; ; Should be updated with every release to avoid bootsector/SYS file mismatch ; %define version_str VERSION ; Must be 4 characters long! @@ -158,7 +158,7 @@ msg_formfeed: ; Form feed character mov bh,[TextAttribute] mov ax,0600h ; Clear screen region int 10h - jmp short msg_gotoxy + jmp msg_gotoxy msg_setbg: ; Color background character call unhexchar jc msg_color_bad diff --git a/cpuinit.inc b/cpuinit.inc index a6923b54..b63ae64d 100644 --- a/cpuinit.inc +++ b/cpuinit.inc @@ -17,49 +17,13 @@ ;; CPU-dependent initialization and related checks. ;; -; -; Check that no moron is trying to boot Linux on a 286 or so. According -; to Intel, the way to check is to see if the high 4 bits of the FLAGS -; register are either all stuck at 1 (8086/8088) or all stuck at 0 -; (286 in real mode), if not it is a 386 or higher. They didn't -; say how to check for a 186/188, so I *hope* it falls out as a 8086 -; or 286 in this test. -; -; Also, provide an escape route in case it doesn't work. -; check_escapes: mov ah,02h ; Check keyboard flags int 16h mov [KbdFlags],al ; Save for boot prompt check test al,04h ; Ctrl->skip 386 check jnz skip_checks -test_8086: - pushf ; Get flags - pop ax - and ax,0FFFh ; Clear top 4 bits - push ax ; Load into FLAGS - popf - pushf ; And load back - pop ax - and ax,0F000h ; Get top 4 bits - cmp ax,0F000h ; If set -> 8086/8088 - je not_386 -test_286: - pushf ; Get flags - pop ax - or ax,0F000h ; Set top 4 bits - push ax - popf - pushf - pop ax - and ax,0F000h ; Get top 4 bits - jnz is_386 ; If not clear -> 386 -not_386: - mov si,err_not386 - call writestr - jmp kaboom -is_386: - ; Now we know it's a 386 or higher + ; ; Now check that there is sufficient low (DOS) memory ; diff --git a/highmem.inc b/highmem.inc new file mode 100644 index 00000000..e3a830b7 --- /dev/null +++ b/highmem.inc @@ -0,0 +1,107 @@ +;; $Id$ +;; ----------------------------------------------------------------------- +;; +;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved +;; +;; 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, +;; Bostom MA 02111-1307, USA; either version 2 of the License, or +;; (at your option) any later version; incorporated herein by reference. +;; +;; ----------------------------------------------------------------------- + +;; +;; highmem.inc +;; +;; Probe for the size of high memory. This can be overridden by a +;; mem= command on the command line while booting a new kernel. +;; + +; +; This is set up as a subroutine; it will set up the global variable +; HighMemSize. All registers are preserved. Assumes DS == CS. +; +highmemsize: + push es + pushad + +; +; First, try INT 15:E820 (get BIOS memory map) +; +get_e820: + xor ebx,ebx ; Start with first record + mov es,bx ; Need ES = DS = 0 for now + jmp short .do_e820 ; Skip "at end" check first time! +.int_loop: and ebx,ebx ; If we're back at beginning... + jz no_e820 ; ... bail; nothing found +.do_e820: mov eax,0000E820h + mov edx,534D4150h ; "SMAP" backwards + xor ecx,ecx + mov cl,20 ; ECX <- 20 + mov di,E820Buf + int 15h + jc no_e820 + cmp eax,534D4150h + jne no_e820 +; +; Look for a memory block starting at <= 1 MB and continuing upward +; + cmp dword [E820Buf+4], byte 0 + ja .int_loop ; Start >= 4 GB? + mov edx, (1 << 20) + sub edx, [E820Buf] + jb .int_loop ; Start >= 1 MB? + stc + sbb eax,eax ; eax <- 0xFFFFFFFF + cmp dword [E820Buf+12], byte 0 + ja .huge ; Size >= 4 GB + mov eax, [E820Buf+8] +.huge: sub eax, edx ; Adjust size to start at 1 MB + jbe .int_loop ; Completely below 1 MB? + + ; Now EAX contains the size of memory 1 MB...up + cmp dword [E820Buf+16], byte 1 + jne near err_nohighmem ; High memory isn't usable memory!!!! + + ; We're good! + jmp short got_highmem_add1mb ; Still need to add low 1 MB + +; +; INT 15:E820 failed. Try INT 15:E801. +; +no_e820: + mov ax,0e801h ; Query high memory (semi-recent) + int 15h + jc no_e801 + cmp ax,3c00h + ja no_e801 ; > 3C00h something's wrong with this call + jb e801_hole ; If memory hole we can only use low part + + mov ax,bx + shl eax,16 ; 64K chunks + add eax,(16 << 20) ; Add first 16M + jmp short got_highmem + +; +; INT 15:E801 failed. Try INT 15:88. +; +no_e801: + mov ah,88h ; Query high memory (oldest) + int 15h + cmp ax,14*1024 ; Don't trust memory >15M + jna e801_hole + mov ax,14*1024 +e801_hole: + and eax,0ffffh + shl eax,10 ; Convert from kilobytes +got_highmem_add1mb: + add eax,(1 << 20) ; First megabyte +got_highmem: +%if HIGHMEM_SLOP != 0 + sub eax,HIGHMEM_SLOP +%endif + mov [HighMemSize],eax + popad + pop es + ret ; Done! diff --git a/isolinux.asm b/isolinux.asm index 6c847736..5d5e4185 100644 --- a/isolinux.asm +++ b/isolinux.asm @@ -145,6 +145,7 @@ HighMemSize resd 1 ; End of memory pointer (bytes) RamdiskMax resd 1 ; Highest address for a ramdisk KernelSize resd 1 ; Size of kernel (bytes) SavedSSSP resd 1 ; Our SS:SP while running a COMBOOT image +PMESP resd 1 ; Protected-mode ESP RootDir resb dir_t_size ; Root directory CurDir resb dir_t_size ; Current directory KernelClust resd 1 ; Kernel size in clusters @@ -1163,6 +1164,7 @@ kernel_corrupt: mov si,err_notkernel ; ; .com - COMBOOT image ; .cbt - COMBOOT image +; .c32 - COM32 image ; .bs - Boot sector ; .0 - PXE bootstrap program (PXELINUX only) ; .bin - Boot sector @@ -1202,6 +1204,8 @@ kernel_good: je is_comboot_image cmp ecx,'.cbt' je is_comboot_image + cmp ecx,'.c32' + je is_com32_image cmp ecx,'.img' je is_disk_image cmp ecx,'.bss' @@ -1225,6 +1229,7 @@ kernel_good: ; COMBOOT-loading code ; %include "comboot.inc" +%include "com32.inc" ; ; Boot sector loading code @@ -1845,6 +1850,7 @@ getfssec: %include "loadhigh.inc" ; Load a file into high memory %include "font.inc" ; VGA font stuff %include "graphics.inc" ; VGA graphics +%include "highmem.inc" ; High memory sizing ; ----------------------------------------------------------------------------- ; Begin data section @@ -1859,15 +1865,6 @@ boot_prompt db 'boot: ', 0 wipe_char db BS, ' ', BS, 0 err_notfound db 'Could not find kernel image: ',0 err_notkernel db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0 -err_not386 db 'It appears your computer uses a 286 or lower CPU.' - db CR, LF - db 'You cannot run Linux unless you have a 386 or higher CPU' - db CR, LF - db 'in your machine. If you get this message in error, hold' - db CR, LF - db 'down the Ctrl key while booting, and I will take your' - db CR, LF - db 'word for it.', CR, LF, 0 err_noram db 'It appears your computer has less than 360K of low ("DOS")' db 0Dh, 0Ah db 'RAM. Linux needs at least this amount to boot. If you get' diff --git a/ldlinux.asm b/ldlinux.asm index bf8ebbc2..f35deb6b 100644 --- a/ldlinux.asm +++ b/ldlinux.asm @@ -139,6 +139,7 @@ HighMemSize resd 1 ; End of memory pointer (bytes) RamdiskMax resd 1 ; Highest address for a ramdisk KernelSize resd 1 ; Size of kernel (bytes) SavedSSSP resd 1 ; Our SS:SP while running a COMBOOT image +PMESP resd 1 ; Protected-mode ESP ClustPerMoby resd 1 ; Clusters per 64K ClustSize resd 1 ; Bytes/cluster KernelName resb 12 ; Mangled name for kernel @@ -793,7 +794,8 @@ all_read_jmp: ; SI -> Starting cluster number (2-based) ; CX -> Cluster count (0FFFFh = until end of file) ; - ; 386 check +; Returns CF=1 on EOF +; getfssec: getfragment: xor ebp,ebp ; Fragment sector count movzx eax,si ; Get sector address @@ -1311,6 +1313,7 @@ kernel_corrupt: mov si,err_notkernel ; ; .com - COMBOOT image ; .cbt - COMBOOT image +; .c32 - COM32 image ; .bs - Boot sector ; .0 - PXE bootstrap program (PXELINUX only) ; .bin - Boot sector @@ -1334,6 +1337,8 @@ kernel_good: je is_comboot_image cmp ecx,'CBT' je is_comboot_image + cmp ecx,'C32' + je is_com32_image cmp ecx,'BS ' je is_bootsector cmp ecx,'BIN' @@ -1351,6 +1356,7 @@ kernel_good: ; COMBOOT-loading code ; %include "comboot.inc" +%include "com32.inc" ; ; Boot sector loading code @@ -1625,6 +1631,7 @@ lc_ret: ret %include "loadhigh.inc" ; Load a file into high memory %include "font.inc" ; VGA font stuff %include "graphics.inc" ; VGA graphics +%include "highmem.inc" ; High memory sizing ; ----------------------------------------------------------------------------- ; Begin data section @@ -1651,15 +1658,6 @@ boot_prompt db 'boot: ', 0 wipe_char db BS, ' ', BS, 0 err_notfound db 'Could not find kernel image: ',0 err_notkernel db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0 -err_not386 db 'It appears your computer uses a 286 or lower CPU.' - db CR, LF - db 'You cannot run Linux unless you have a 386 or higher CPU' - db CR, LF - db 'in your machine. If you get this message in error, hold' - db CR, LF - db 'down the Ctrl key while booting, and I will take your' - db CR, LF - db 'word for it.', CR, LF, 0 err_noram db 'It appears your computer has less than 488K of low ("DOS")' db CR, LF db 'RAM. Linux needs at least this amount to boot. If you get' diff --git a/pxelinux.asm b/pxelinux.asm index bb08d6e2..67894fa1 100644 --- a/pxelinux.asm +++ b/pxelinux.asm @@ -193,6 +193,7 @@ HighMemSize resd 1 ; End of memory pointer (bytes) RamdiskMax resd 1 ; Highest address for a ramdisk KernelSize resd 1 ; Size of kernel (bytes) SavedSSSP resd 1 ; Our SS:SP while running a COMBOOT image +PMESP resd 1 ; Protected-mode ESP Stack resd 1 ; Pointer to reset stack PXEEntry resd 1 ; !PXE API entry point RebootTime resd 1 ; Reboot timeout, if set by option @@ -1037,6 +1038,7 @@ kernel_corrupt: mov si,err_notkernel ; ; .com - COMBOOT image ; .cbt - COMBOOT image +; .c32 - COM32 image ; .bs - Boot sector ; .0 - PXE bootstrap program (PXELINUX only) ; .bin - Boot sector @@ -1078,6 +1080,8 @@ kernel_good: je is_comboot_image cmp ecx,'.cbt' je is_comboot_image + cmp ecx,'.c32' + je is_com32_image cmp ecx,'.bss' je is_bss_image cmp ecx,'.bin' @@ -1124,6 +1128,7 @@ kernel_good: ; COMBOOT-loading code ; %include "comboot.inc" +%include "com32.inc" ; ; Boot sector loading code @@ -2099,21 +2104,21 @@ parse_dhcp_options: jne .not_subnet mov edx,[si] mov [Netmask],edx - jmp short .opt_done + jmp .opt_done .not_subnet: cmp dl,3 ; ROUTER option jne .not_router mov edx,[si] mov [Gateway],edx - jmp short .opt_done + jmp .opt_done .not_router: cmp dl,52 ; OPTION OVERLOAD option jne .not_overload mov dl,[si] mov [OverLoad],dl - jmp short .opt_done + jmp .opt_done .not_overload: cmp dl,67 ; BOOTFILE NAME option @@ -2222,6 +2227,7 @@ writestr equ cwritestr %include "loadhigh.inc" ; Load a file into high memory %include "font.inc" ; VGA font stuff %include "graphics.inc" ; VGA graphics +%include "highmem.inc" ; High memory sizing ; ----------------------------------------------------------------------------- ; Begin data section @@ -2238,15 +2244,6 @@ boot_prompt db 'boot: ', 0 wipe_char db BS, ' ', BS, 0 err_notfound db 'Could not find kernel image: ',0 err_notkernel db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0 -err_not386 db 'It appears your computer uses a 286 or lower CPU.' - db CR, LF - db 'You cannot run Linux unless you have a 386 or higher CPU' - db CR, LF - db 'in your machine. If you get this message in error, hold' - db CR, LF - db 'down the Ctrl key while booting, and I will take your' - db CR, LF - db 'word for it.', CR, LF, 0 err_noram db 'It appears your computer has less than 384K of low ("DOS")' db 0Dh, 0Ah db 'RAM. Linux needs at least this amount to boot. If you get' diff --git a/runkernel.inc b/runkernel.inc index eabb792b..3ee28f9b 100644 --- a/runkernel.inc +++ b/runkernel.inc @@ -96,89 +96,15 @@ kernel_sane: push ax call getfssec cmp word [es:bs_bootsign],0AA55h jne kernel_corrupt ; Boot sec signature missing -; -; Get the BIOS' idea of what the size of high memory is. -; - push si ; Save our cluster pointer! -; -; First, try INT 15:E820 (get BIOS memory map) -; -get_e820: - push es - xor ebx,ebx ; Start with first record - mov es,bx ; Need ES = DS = 0 for now - jmp short .do_e820 ; Skip "at end" check first time! -.int_loop: and ebx,ebx ; If we're back at beginning... - jz no_e820 ; ... bail; nothing found -.do_e820: mov eax,0000E820h - mov edx,534D4150h ; "SMAP" backwards - mov ecx,20 - mov di,E820Buf - int 15h - jc no_e820 - cmp eax,534D4150h - jne no_e820 -; -; Look for a memory block starting at <= 1 MB and continuing upward -; - cmp dword [E820Buf+4], byte 0 - ja .int_loop ; Start >= 4 GB? - mov edx, (1 << 20) - sub edx, [E820Buf] - jb .int_loop ; Start >= 1 MB? - stc - sbb eax,eax ; eax <- 0xFFFFFFFF - cmp dword [E820Buf+12], byte 0 - ja .huge ; Size >= 4 GB - mov eax, [E820Buf+8] -.huge: sub eax, edx ; Adjust size to start at 1 MB - jbe .int_loop ; Completely below 1 MB? - - ; Now EAX contains the size of memory 1 MB...up - cmp dword [E820Buf+16], byte 1 - jne err_nohighmem ; High memory isn't usable memory!!!! - - ; We're good! - pop es - jmp short got_highmem_add1mb ; Still need to add low 1 MB ; -; INT 15:E820 failed. Try INT 15:E801. +; Save the cluster pointer for later... ; -no_e820: pop es - - mov ax,0e801h ; Query high memory (semi-recent) - int 15h - jc no_e801 - cmp ax,3c00h - ja no_e801 ; > 3C00h something's wrong with this call - jb e801_hole ; If memory hole we can only use low part - - mov ax,bx - shl eax,16 ; 64K chunks - add eax,(16 << 20) ; Add first 16M - jmp short got_highmem - + push si ; -; INT 15:E801 failed. Try INT 15:88. +; Get the BIOS' idea of what the size of high memory is. ; -no_e801: - mov ah,88h ; Query high memory (oldest) - int 15h - cmp ax,14*1024 ; Don't trust memory >15M - jna e801_hole - mov ax,14*1024 -e801_hole: - and eax,0ffffh - shl eax,10 ; Convert from kilobytes -got_highmem_add1mb: - add eax,(1 << 20) ; First megabyte -got_highmem: -%if HIGHMEM_SLOP != 0 - sub eax,HIGHMEM_SLOP -%endif - mov [HighMemSize],eax - + call highmemsize ; ; Construct the command line (append options have already been copied) ; diff --git a/sample/Makefile b/sample/Makefile index f4ad1bcf..e6b648a0 100644 --- a/sample/Makefile +++ b/sample/Makefile @@ -15,15 +15,31 @@ ## samples for syslinux users ## +CC = gcc +LD = ld +CFLAGS = -O2 -fomit-frame-pointer -I.. +LDFLAGS = -s +OBJCOPY = objcopy PPMTOLSS16 = ../ppmtolss16 -all: syslogo.lss +.SUFFIXES: .lss .c .o .elf .c32 + +all: syslogo.lss hello.c32 + +.c.o: + $(CC) $(CFLAGS) -c -o $@ $< + +.elf.c32: + $(OBJCOPY) -O binary $< $@ syslogo.lss: syslogo.png $(PPMTOLSS16) pngtopnm syslogo.png | \ $(PPMTOLSS16) \#000000=0 \#d0d0d0=7 \#f6f6f6=15 \ > syslogo.lss +hello.elf: hello.o + $(LD) -Ttext 0x101000 -e _start -o $@ $< + clean: rm -f *.lss diff --git a/sample/hello.c b/sample/hello.c new file mode 100644 index 00000000..194092e3 --- /dev/null +++ b/sample/hello.c @@ -0,0 +1,47 @@ +#ident "$Id$" +/* ----------------------------------------------------------------------- * + * + * Copyright 2002 H. Peter Anvin - All Rights Reserved + * + * 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, + * Bostom MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * hello.c + * + * Simple COM32 image + */ + +#include <com32.h> + +#define NULL ((void *)0) + +static inline void memset(void *buf, int ch, unsigned int len) +{ + asm volatile("cld; rep; stosb" + : "+D" (buf), "+c" (len) : "a" (ch) : "memory"); +} + +int _start(unsigned int nargs, char *cmdline, + void (*syscall)(unsigned char, com32sys_t *, com32sys_t *), + void *bounce_ptr, unsigned int bounce_len) +{ + const char *msg = "Hello, World!\r\n"; + com32sys_t inreg, outreg; + const char *p; + + memset(&inreg, 0, sizeof inreg); + + for ( p = msg ; *p ; p++ ) { + inreg.edx = *p; + inreg.eax = 0x0200; + syscall(0x21, &inreg, NULL); + } + + return 0; +} @@ -1 +1 @@ -1.75 +2.00 diff --git a/version.pl b/version.pl new file mode 100755 index 00000000..fa09e40d --- /dev/null +++ b/version.pl @@ -0,0 +1,25 @@ +#!/usr/bin/perl +# +# Read the "version" file and produce some macro declarations +# + +use Fcntl; + +$vfile = $ARGV[0]; +sysopen(VERSION, $vfile, O_RDONLY) or die "$0: Cannot open $vfile\n"; +$version = <VERSION>; +chomp $version; +close(VERSION); + +unless ( $version =~ /^([0-9]+)\.([0-9]+)$/ ) { + die "$0: Cannot parse version format\n"; +} +$vma = $1+0; $vmi = $2+0; + +open(VI, "> version.gen") or die "$0: Cannot create version.gen\n"; +print VI "%define VERSION \"$version\"\n"; +print VI "%define VER_MAJOR $vma\n"; +print VI "%define VER_MINOR $vmi\n"; +close(VI); + + |