diff options
Diffstat (limited to 'core')
53 files changed, 1469 insertions, 1187 deletions
diff --git a/core/Makefile b/core/Makefile index 65418c48..e9aec68f 100644 --- a/core/Makefile +++ b/core/Makefile @@ -24,7 +24,7 @@ include $(topdir)/MCONFIG.embedded -include $(topdir)/version.mk OPTFLAGS = -INCLUDES = +INCLUDES = -I./include -I$(com32)/include # This is very similar to cp437; technically it's for Norway and Denmark, # but it's unlikely the characters that are different will be used in @@ -38,12 +38,21 @@ BTARGET = kwdhash.gen \ extlinux.bin extlinux.bss extlinux.sys # All primary source files for the main syslinux files -NASMSRC = $(wildcard *.asm) -NASMHDR = $(wildcard *.inc) -CSRC = $(wildcard *.c) -CHDR = $(wildcard *.h) -OTHERSRC = keywords -ALLSRC = $(NASMSRC) $(NASMHDR) $(CSRC) $(CHDR) $(OTHERSRC) +NASMSRC := $(wildcard *.asm) +NASMHDR := $(wildcard *.inc) +CSRC := $(wildcard *.c) +CHDR := $(wildcard *.h) +OTHERSRC := keywords +ALLSRC = $(NASMSRC) $(NASMHDR) $(CSRC) $(CHDR) $(OTHERSRC) + +COBJ := $(patsubst %.c,%.o,$(CSRC)) + +LIB = libcore.a +LIBS = $(LIB) $(com32)/lib/libcom32.a $(LIBGCC) +LIBOBJS = $(COBJ) + +NASMDEBUG = -g -F stabs +NASMOPT += $(NASMDEBUG) # The DATE is set on the make command line when building binaries for # official release. Otherwise, substitute a hex string that is pretty much @@ -72,16 +81,22 @@ iso%.bin: iso%.elf checksumiso.pl $(OBJCOPY) -O binary $< $@ %.o: %.asm kwdhash.gen ../version.gen - ( $(NASM) -M -DDEPEND $(NINCLUDE) -o $@ $< ; echo '' ) > .$@.d; true - $(NASM) $(NASMOPT) -f elf -g -F stabs -DDATE_STR="'$(DATE)'" \ + ( $(NASM) -f elf $(NASMOPT) -M -DDEPEND $(NINCLUDE) \ + -o $@ $< ; echo '' ) > .$@.d; true + $(NASM) -f elf $(NASMOPT) -DDATE_STR="'$(DATE)'" \ -DHEXDATE="$(HEXDATE)" \ -l $(@:.o=.lsr) -o $@ $< -%.elf: %.o syslinux.ld - $(LD) $(LDFLAGS) -T syslinux.ld -M -o $@ $< > $(@:.elf=.map) +%.elf: %.o $(LIBS) syslinux.ld + $(LD) $(LDFLAGS) -T syslinux.ld -M -o $@ $< $(LIBS) > $(@:.elf=.map) $(OBJDUMP) -h $@ > $(@:.elf=.sec) $(PERL) lstadjust.pl $(@:.elf=.lsr) $(@:.elf=.sec) $(@:.elf=.lst) +$(LIB): $(LIBOBJS) + rm -f $@ + $(AR) cq $@ $^ + $(RANLIB) $@ + pxelinux.0: pxelinux.bin cp -f $< $@ @@ -112,7 +127,7 @@ install-all: install install-lib netinstall: installer tidy dist: - rm -f codepage.cp *.o *.elf stupid.* patch.offset .depend .*.d + rm -f codepage.cp *.o *.elf *.a stupid.* patch.offset .depend .*.d rm -f *.lsr *.lst *.map *.sec rm -f $(OBSOLETE) diff --git a/core/abort.inc b/core/abort.inc index d8cd7f24..d8a18883 100644 --- a/core/abort.inc +++ b/core/abort.inc @@ -17,7 +17,7 @@ ; Code to terminate a kernel load ; - section .text + section .text16 ; ; dot_pause: same as abort_check, except prints a dot, too @@ -77,7 +77,7 @@ error_or_command: jnz on_error jmp enter_command - section .data + section .data16 aborted_msg db ' aborted.', CR, LF, 0 - section .text + section .text16 diff --git a/core/adv.inc b/core/adv.inc index d856a1a2..2dc16339 100644 --- a/core/adv.inc +++ b/core/adv.inc @@ -57,7 +57,7 @@ adv1: .data resb ADV_LEN .tail resd 1 .end equ $ - section .text + section .text16 ; ; This is called after config file parsing, so we know @@ -67,24 +67,26 @@ adv_init: cmp byte [ADVDrive],-1 jne adv_read -;%if IS_SYSLINUX || IS_MDSLINUX || IS_EXTLINUX -%if IS_EXTLINUX ; Not yet implemented for the other derivatives +%if IS_SYSLINUX || IS_EXTLINUX + cmp word [ADVSectors],2 ; Not present? + jb adv_verify + ; ; Update pointers to default ADVs... ; - mov bx,[LDLSectors] + mov bx,[DataSectors] shl bx,2 mov ecx,[bsHidden] - mov eax,[bx+SectorPtrs-8] - mov edx,[bx+SectorPtrs-4] + mov eax,[bx+SectorPtrs] ; First ADV sector + mov edx,[bx+SectorPtrs+4] ; Second ADV sector add eax,ecx add edx,ecx mov [ADVSec0],eax mov [ADVSec1],edx mov al,[DriveNumber] mov [ADVDrive],al + jmp adv_read %endif - ; ** fall through to adv_verify ** ; ; Initialize the ADV data structure in memory @@ -492,12 +494,14 @@ adv_read_write: stc jmp .cb_done - section .data + section .data16 alignz 4 ADVSec0 dd 0 ; Not specified ADVSec1 dd 0 ; Not specified ADVDrive db -1 ; No ADV defined ADVCHSInfo db -1 ; We have CHS info for this drive - section .bss + section .bss16 ADVOp resb 1 + + section .text16 diff --git a/core/bcopy32.inc b/core/bcopy32.inc index c7155574..6537546b 100644 --- a/core/bcopy32.inc +++ b/core/bcopy32.inc @@ -29,7 +29,7 @@ ; bits 16 - section .text + section .text16 ; ; bcopy: @@ -39,17 +39,13 @@ ; ESI - source pointer (-1 means do bzero rather than bcopy) ; EDI - target pointer ; ECX - byte count -; DF - zero ; ; Outputs: ; ESI - first byte after source (garbage if ESI == -1 on entry) ; EDI - first byte after target ; bcopy: jecxz .ret - pushad - push word pm_bcopy - call simple_pm_call - popad + pm_call pm_bcopy add edi,ecx add esi,ecx .ret: ret @@ -70,303 +66,8 @@ bcopy: jecxz .ret ; the entry point and src the mode (0 = pm, 1 = rm) ; shuffle_and_boot_raw: - push word pm_shuffle - call simple_pm_call - ; Never returns... - jmp kaboom - -; -; This routine is used to invoke a simple routine in 32-bit protected -; mode (with 32-bit zero-based CS, DS, ES, and SS, with ESP pointing to the -; real-mode stack even if the real-mode stack was in a nonzero SS.) -; -; No interrupt thunking services are provided; interrupts are disabled -; for the duration of the routine. Don't run for too long at a time -; unless you really mean it. -; -; Inputs: -; On stack - pm entrypoint (IP only) -; EAX, EBP preserved until real-mode exit -; EBX, ECX, EDX, ESI and EDI passed to the called routine -; -; Outputs: -; EAX, EBP restored from real-mode entry -; All other registers as returned from called function -; PM entrypoint cleaned off stack -; -simple_pm_call: - push eax - push ebp - movzx ebp,sp ; BP is used as frame pointer - pushfd ; Saves, among others, the IF flag - push ds - push es - push fs - push gs - - cli - call enable_a20 - - mov byte [cs:bcopy_gdt.TSS+5],89h ; Mark TSS unbusy - - ; Convert the stack segment to a base - xor eax,eax - mov ax,ss - shl eax,4 - add ebp,eax ; EBP is now an absolute frame ptr - - ; Save the old segmented stack pointer - mov [cs:.rm_esp],esp - mov [cs:.rm_ss],ss - - o32 lgdt [cs:bcopy_gdt] - mov eax,cr0 - or al,1 - mov cr0,eax ; Enter protected mode - jmp PM_CS32:.in_pm - - bits 32 -.in_pm: - mov ax,PM_DS32 - mov ss,eax - lea esp,[ebp-8*4-2*4] ; Flat mode stack - mov es,eax - mov ds,eax - - ; Set fs, gs, tr, and ldtr in case we're on a virtual - ; machine running on Intel VT hardware -- it can't - ; deal with a partial transition, for no good reason. - - mov al,PM_DS16 ; Real-mode-like segment - mov fs,eax - mov gs,eax - mov al,PM_TSS ; Intel VT really doesn't want - ltr ax ; an invalid TR and LDTR, so give - xor eax,eax ; it something that it can use... - lldt ax ; (sigh) - - movzx eax,word [ebp+2*4+2] - call eax ; Call actual routine - - jmp PM_CS16:.exit - bits 16 -.exit: - mov ax,PM_DS16 ; "Real-mode-like" data segment - mov es,eax - mov ds,eax - mov ss,eax - - mov eax,cr0 - and al,~1 - mov cr0,eax ; Disable protected mode - jmp 0:.in_rm - -.in_rm: ; Back in real mode - lss esp,[cs:.rm_esp] ; Restore the stack - pop gs - pop fs - pop es - pop ds - - popfd ; Re-enables interrupts - pop ebp - pop eax - ret 2 ; Drops the pm entry - - section .bss - alignb 4 -.rm_esp resd 1 -.rm_ss resw 1 - - - section .text -; -; Routines to enable and disable (yuck) A20. These routines are gathered -; from tips from a couple of sources, including the Linux kernel and -; http://www.x86.org/. The need for the delay to be as large as given here -; is indicated by Donnie Barnes of RedHat, the problematic system being an -; IBM ThinkPad 760EL. -; -; We typically toggle A20 twice for every 64K transferred. -; -%define IO_DELAY_PORT 80h ; Invalid port (we hope!) - -slow_out: out dx, al ; Fall through - -%macro io_delay 0 - out IO_DELAY_PORT,al - out IO_DELAY_PORT,al -%endmacro - - section .data - alignz 2 -A20Ptr dw a20_dunno - - section .bss - alignb 4 -A20Test resd 1 ; Counter for testing A20 status -A20Tries resb 1 ; Times until giving up on A20 - - section .text -enable_a20: - pushad - mov byte [cs:A20Tries],255 ; Times to try to make this work - -try_enable_a20: - -; -; First, see if we are on a system with no A20 gate, or the A20 gate -; is already enabled for us... -; -a20_none: - call a20_test - jnz a20_done - ; Otherwise, see if we had something memorized... - jmp word [cs:A20Ptr] - -; -; Next, try the BIOS (INT 15h AX=2401h) -; -a20_dunno: -a20_bios: - mov word [cs:A20Ptr], a20_bios - mov ax,2401h - pushf ; Some BIOSes muck with IF - int 15h - popf - - call a20_test - jnz a20_done - -; -; Enable the keyboard controller A20 gate -; -a20_kbc: - mov dl, 1 ; Allow early exit - call empty_8042 - jnz a20_done ; A20 live, no need to use KBC - - mov word [cs:A20Ptr], a20_kbc ; Starting KBC command sequence - - mov al,0D1h ; Write output port - out 064h, al - call empty_8042_uncond - - mov al,0DFh ; A20 on - out 060h, al - call empty_8042_uncond - - ; Apparently the UHCI spec assumes that A20 toggle - ; ends with a null command (assumed to be for sychronization?) - ; Put it here to see if it helps anything... - mov al,0FFh ; Null command - out 064h, al - call empty_8042_uncond - - ; Verify that A20 actually is enabled. Do that by - ; observing a word in low memory and the same word in - ; the HMA until they are no longer coherent. Note that - ; we don't do the same check in the disable case, because - ; we don't want to *require* A20 masking (SYSLINUX should - ; work fine without it, if the BIOS does.) -.kbc_wait: push cx - xor cx,cx -.kbc_wait_loop: - call a20_test - jnz a20_done_pop - loop .kbc_wait_loop - - pop cx -; -; Running out of options here. Final attempt: enable the "fast A20 gate" -; -a20_fast: - mov word [cs:A20Ptr], a20_fast - in al, 092h - or al,02h - and al,~01h ; Don't accidentally reset the machine! - out 092h, al - -.fast_wait: push cx - xor cx,cx -.fast_wait_loop: - call a20_test - jnz a20_done_pop - loop .fast_wait_loop - - pop cx - -; -; Oh bugger. A20 is not responding. Try frobbing it again; eventually give up -; and report failure to the user. -; - dec byte [cs:A20Tries] - jnz a20_dunno ; Did we get the wrong type? - - mov si, err_a20 - jmp abort_load - - section .data -err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0 - section .text - -; -; A20 unmasked, proceed... -; -a20_done_pop: pop cx -a20_done: popad - ret - -; -; This routine tests if A20 is enabled (ZF = 0). This routine -; must not destroy any register contents. -; -; The no-write early out avoids the io_delay in the (presumably common) -; case of A20 already enabled (e.g. from a previous call.) -; -a20_test: - push es - push cx - push eax - mov cx,0FFFFh ; HMA = segment 0FFFFh - mov es,cx - mov eax,[cs:A20Test] - mov cx,32 ; Loop count - jmp .test ; First iteration = early out -.wait: add eax,0x430aea41 ; A large prime number - mov [cs:A20Test],eax - io_delay ; Serialize, and fix delay -.test: cmp eax,[es:A20Test+10h] - loopz .wait -.done: pop eax - pop cx - pop es - ret - -; -; Routine to empty the 8042 KBC controller. If dl != 0 -; then we will test A20 in the loop and exit if A20 is -; suddenly enabled. -; -empty_8042_uncond: - xor dl,dl -empty_8042: - call a20_test - jz .a20_on - and dl,dl - jnz .done -.a20_on: io_delay - in al, 064h ; Status port - test al,1 - jz .no_output - io_delay - in al, 060h ; Read input - jmp short empty_8042 -.no_output: - test al,2 - jnz empty_8042 - io_delay -.done: ret + mov bx,pm_shuffle + jmp enter_pm ; ; The 32-bit copy and shuffle code is "special", so it is in its own file diff --git a/core/bcopyxx.inc b/core/bcopyxx.inc index 89ae4f40..823662b4 100644 --- a/core/bcopyxx.inc +++ b/core/bcopyxx.inc @@ -204,6 +204,7 @@ pm_bcopy: ; the entry point and src the mode (0 = pm, 1 = rm) ; pm_shuffle: + cli ; End interrupt service (for good) mov ebx,edi ; EBX <- descriptor list lea edx,[edi+ecx+15] ; EDX <- where to relocate our code to and edx,~15 ; Align 16 to benefit the GDT @@ -232,15 +233,16 @@ pm_shuffle: call pm_bcopy jmp .loop .done: + lidt [edx+RM_IDT_ptr-bcopy_gdt] ; RM-like IDT push ecx ; == 0, for cleaning the flags register and esi,esi - jz pm_shuffle_real_mode + jz pm_shuffle_16 popfd ; Clean the flags jmp edi ; Protected mode entry - ; We have a real-mode entry point, so we need to return - ; to real mode. Note: EDX already points to the GDT. -pm_shuffle_real_mode: + ; We have a 16-bit entry point, so we need to return + ; to 16-bit mode. Note: EDX already points to the GDT. +pm_shuffle_16: mov eax,edi mov [edx+PM_CS16+2],ax mov [edx+PM_DS16+2],ax @@ -261,7 +263,11 @@ pm_shuffle_real_mode: mov ss,edx jmp PM_CS16:0 - align 16 + align 4 +RM_IDT_ptr: dw 0FFFFh ; Length (nonsense, but matches CPU) + dd 0 ; Offset + + alignz 16 ; GDT descriptor entry %macro desc 1 bcopy_gdt.%1: @@ -312,4 +318,4 @@ bcopyxx_safe equ bcopyxx_len + bcopyxx_stack + 15 DummyTSS equ 0x580 bits 16 - section .text + section .text16 diff --git a/core/bootsect.inc b/core/bootsect.inc index b107eb5c..c976db69 100644 --- a/core/bootsect.inc +++ b/core/bootsect.inc @@ -122,7 +122,7 @@ replace_bootstrap: jmp .stackok %endif .stdstack: - mov di,7C00h-44 + mov di,StackTop-44 push di mov cx,22 ; 44 bytes rep stosw @@ -211,4 +211,4 @@ replace_stub: jmp 0:0 .csip equ $-4 - section .text + section .text16 diff --git a/core/cache.inc b/core/cache.inc index 59755576..3b24cf04 100644 --- a/core/cache.inc +++ b/core/cache.inc @@ -10,7 +10,7 @@ ; ; ----------------------------------------------------------------------- - section .text + section .text16 struc cptr .sector: resd 1 ; Sector number @@ -103,7 +103,7 @@ getcachesector: pop cx ret - section .bss + section .bss16 ; Each CachePtr contains: ; - Block pointer diff --git a/core/callback.inc b/core/callback.inc new file mode 100644 index 00000000..a33b5825 --- /dev/null +++ b/core/callback.inc @@ -0,0 +1,208 @@ +;; ----------------------------------------------------------------------- +;; +;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved +;; Copyright 2009 Intel Corporation; author: H. Peter Anvin +;; +;; 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. +;; +;; ----------------------------------------------------------------------- + +;; +;; callback.inc +;; +;; Callbacks from 32-bit mode to 16-bit mode +;; + +; +; 16-bit intcall/farcall handling code +; + +; +; 32-bit support code +; + bits 32 + section .text + +; +; Intcall/farcall 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 +; + global core_farcall +core_farcall: + mov eax,[esp+1*4] ; CS:IP + jmp core_syscall + + global core_intcall +core_intcall: + movzx eax,byte [esp+1*4] ; INT number + mov eax,[eax*4] ; Get CS:IP from low memory + +core_syscall: + pushfd ; Save IF among other things... + push ebx + push ebp + push esi + push edi + push dword [CallbackSP] + + cld + + movzx edi,word [word RealModeSSSP] + movzx ebx,word [word RealModeSSSP+2] + sub edi,54 ; Allocate 54 bytes + mov [word RealModeSSSP],di + shl ebx,4 + add edi,ebx ; Create linear address + + mov esi,[esp+8*4] ; Source regs + xor ecx,ecx + mov cl,11 ; 44 bytes to copy + rep movsd + + ; EAX is already set up to be CS:IP + stosd ; Save in stack frame + mov eax,.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,.rm + jmp enter_rm ; Go to real mode + + bits 16 + section .text16 +.rm: + pop gs + pop fs + pop es + pop ds + popad + popfd + mov [cs:CallbackSP],sp + retf ; Invoke routine + +.rm_return: + ; We clean up SP here because we don't know if the + ; routine returned with RET, RETF or IRET + mov sp,[cs:CallbackSP] + pushfd + pushad + push ds + push es + push fs + push gs + mov ebx,.pm_return + jmp enter_pm + + ; On return, the 44-byte return structure is on the + ; real-mode stack, plus the 10 additional bytes used + ; by the target address (see above.) + bits 32 + section .text +.pm_return: + movzx esi,word [word RealModeSSSP] + movzx eax,word [word RealModeSSSP+2] + mov edi,[esp+9*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 RealModeSSSP],54 + ; Remove from stack + + pop dword [CallbackSP] + pop edi + pop esi + pop ebp + pop ebx + popfd + ret ; Return to 32-bit program + +; +; Cfarcall invocation. We copy the stack frame to the real-mode stack, +; followed by the return CS:IP and the CS:IP of the target function. +; + global core_cfarcall +core_cfarcall: + pushfd ; Save IF among other things... + push ebx + push ebp + push esi + push edi + push dword [CallbackSP] + + cld + mov ecx,[esp+9*4] ; Size of stack frame + + movzx edi,word [word RealModeSSSP] + movzx ebx,word [word RealModeSSSP+2] + mov [word CallbackSP],di + sub edi,ecx ; Allocate space for stack frame + and edi,~3 ; Round + sub edi,4*2 ; Return pointer, return value + mov [word RealModeSSSP],di + shl ebx,4 + add edi,ebx ; Create linear address + + mov eax,[esp+7*4] ; CS:IP + stosd ; Save to stack frame + mov eax,.rm_return ; Return seg:off + stosd + mov esi,[esp+8*4] ; Stack frame + mov eax,ecx ; Copy the stack frame + shr ecx,2 + rep movsd + mov ecx,eax + and ecx,3 + rep movsb + + mov bx,.rm + jmp enter_rm + + bits 16 + section .text16 +.rm: + retf +.rm_return: + mov sp,[cs:CallbackSP] + mov esi,eax + mov ebx,.pm_return + jmp enter_pm + + bits 32 + section .text +.pm_return: + mov eax,esi + ; EDX already set up to be the RM return value + pop dword [CallbackSP] + pop ebx + pop ebp + pop esi + pop edi + popfd + ret + + bits 16 + section .bss16 + alignb 4 +CallbackSP resd 1 ; SP saved during callback + + bits 16 + section .text16 diff --git a/core/cleanup.inc b/core/cleanup.inc index 1b00e0b0..7db5593d 100644 --- a/core/cleanup.inc +++ b/core/cleanup.inc @@ -16,7 +16,7 @@ ;; Some final tidying before jumping to a kernel or bootsector ;; - section .text + section .text16 ; ; cleanup_hardware: ; @@ -50,5 +50,7 @@ cleanup_hardware: .no_vmware: %endif + call comboot_cleanup_api + popad ret diff --git a/core/cmdline.inc b/core/cmdline.inc index 642e5e14..8b84f48d 100644 --- a/core/cmdline.inc +++ b/core/cmdline.inc @@ -45,7 +45,7 @@ make_plain_cmdline: ; Actual IPAppend strings... ; %if IS_PXELINUX - section .data + section .data16 alignz 2 IPAppends dw IPOption dw BOOTIFStr @@ -60,7 +60,7 @@ numIPAppends equ 0 ; ; Assumes DS == CS; pushes output to ES:DI ; - section .text + section .text16 do_ip_append: %ifndef DEPEND diff --git a/core/com32.inc b/core/com32.inc index 72327929..40c5c034 100644 --- a/core/com32.inc +++ b/core/com32.inc @@ -1,6 +1,7 @@ ;; ----------------------------------------------------------------------- ;; -;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved +;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved +;; Copyright 2009 Intel Corporation; author: H. Peter Anvin ;; ;; 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 @@ -27,29 +28,9 @@ ; program with an error if run in 16-bit mode. ; - ; We need to make this a proper section rather - ; than using absolute numbers, in order to work - ; around a bug in GNU ld 2.17, which is still in - ; use as of this writing in the form of Debian - ; 4.0 (etch). - bits 32 - section .com32 exec write nobits align=16 -pm_idt equ 0x100000 ; Needs to be absolute... - resb 4096 -pm_entry: ; Needs to not be... - - bits 16 - section .data - alignz 2 -com32_pmidt: - dw 8*256 ; Limit - dd pm_idt ; Address +pm_entry equ 101000h -com32_rmidt: - dw 0ffffh ; Limit - dd 0 ; Address - - section .text + section .text16 is_com32_image: push si ; Save file handle push eax ; Save file length @@ -75,354 +56,42 @@ is_com32_image: call load_high com32_start: - mov ebx,com32_call_start ; Where to go in PM - -com32_enter_pm: - cli - mov ax,cs - mov ds,ax - mov [RealModeSSSP],sp - mov [RealModeSSSP+2],ss - cld - call a20_test - jnz .a20ok - call enable_a20 - -.a20ok: - mov byte [bcopy_gdt.TSS+5],89h ; Mark TSS unbusy - - 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 PM_CS32:.in_pm - - bits 32 -.in_pm: - xor eax,eax ; Available for future use... - mov fs,eax - mov gs,eax - lldt ax - - mov al,PM_DS32 ; Set up data segments - mov es,eax - mov ds,eax - mov ss,eax - - mov al,PM_TSS ; Be nice to Intel's VT by - ltr ax ; giving it a valid TR - - mov esp,[PMESP] ; Load protmode %esp if available - jmp ebx ; Go to where we need to go + ; + ; Point the stack to the end of (permitted) high memory + ; + mov eax,[HighMemRsvd] + xor ax,ax ; Align to a 64K boundary + mov [PMESP],eax + mov ebx,.pm ; Where to go in PM + jmp enter_pm ; ; 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 (permitted) high memory - ; - mov esp,[word HighMemRsvd] - xor sp,sp ; Align to a 64K boundary - - ; - ; 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... + bits 32 + section .text +.pm: + ; Set up the calling stack frame push dword [HighMemSize] ; Memory managed by Syslinux - push dword com32_cfarcall ; Cfarcall entry point - push dword com32_farcall ; Farcall entry point + push dword core_cfarcall ; Cfarcall entry point + push dword core_farcall ; Farcall entry point push dword (1 << 16) ; 64K bounce buffer push dword (xfer_buf_seg << 4) ; Bounce buffer address - push dword com32_intcall ; Intcall entry point + push dword core_intcall ; Intcall entry point push dword command_line ; Command line pointer push dword 7 ; 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 PM_CS16:.in_pm16 ; Return to 16-bit mode first + mov bx,.rm + jmp enter_rm bits 16 -.in_pm16: - mov ax,PM_DS16 ; 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,[RealModeSSSP] ; Restore stack - jmp bx ; Go to whereever we need to go... - -com32_done: + section .text16 +.rm: + mov dword [PMESP],__stack_end ; Stop use of COM32 stack 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 intcall/farcall handling code -; -com32_sys_rm: - pop gs - pop fs - pop es - pop ds - popad - popfd - mov [cs:Com32SysSP],sp - retf ; Invoke routine -.return: - ; We clean up SP here because we don't know if the - ; routine returned with RET, RETF or IRET - mov sp,[cs:Com32SysSP] - pushfd - pushad - push ds - push es - push fs - push gs - mov ebx,com32_syscall.resume - jmp com32_enter_pm - -; -; 16-bit cfarcall handing code -; -com32_cfar_rm: - retf -.return: - mov sp,[cs:Com32SysSP] - mov [cs:RealModeEAX],eax - mov ebx,com32_cfarcall.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 - -; -; Intcall/farcall 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_farcall: - pushfd ; Save IF among other things... - pushad ; We only need to save some, but... - - mov eax,[esp+10*4] ; CS:IP - jmp com32_syscall - - -com32_intcall: - pushfd ; Save IF among other things... - pushad ; We only need to save some, but... - - movzx eax,byte [esp+10*4] ; INT number - mov eax,[eax*4] ; Get CS:IP from low memory - -com32_syscall: - cld - - movzx edi,word [word RealModeSSSP] - movzx ebx,word [word RealModeSSSP+2] - sub edi,54 ; Allocate 54 bytes - mov [word RealModeSSSP],di - shl ebx,4 - add edi,ebx ; Create linear address - - mov esi,[esp+11*4] ; Source regs - xor ecx,ecx - mov cl,11 ; 44 bytes to copy - rep movsd - - ; EAX is already set up to be CS:IP - 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, plus the 10 additional bytes used - ; by the target address (see above.) -.resume: - movzx esi,word [word RealModeSSSP] - movzx eax,word [word RealModeSSSP+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 RealModeSSSP],54 ; Remove from stack - - popad - popfd - ret ; Return to 32-bit program - -; -; Cfarcall invocation. We copy the stack frame to the real-mode stack, -; followed by the return CS:IP and the CS:IP of the target function. -; -com32_cfarcall: - pushfd - pushad - - cld - mov ecx,[esp+12*4] ; Size of stack frame - - movzx edi,word [word RealModeSSSP] - movzx ebx,word [word RealModeSSSP+2] - mov [word Com32SysSP],di - sub edi,ecx ; Allocate space for stack frame - and edi,~3 ; Round - sub edi,4*2 ; Return pointer, return value - mov [word RealModeSSSP],di - shl ebx,4 - add edi,ebx ; Create linear address - - mov eax,[esp+10*4] ; CS:IP - stosd ; Save to stack frame - mov eax,com32_cfar_rm.return ; Return seg:off - stosd - mov esi,[esp+11*4] ; Stack frame - mov eax,ecx ; Copy the stack frame - shr ecx,2 - rep movsd - mov ecx,eax - and ecx,3 - rep movsb - - mov bx,com32_cfar_rm - jmp com32_enter_rm - -.resume: - popad - mov eax,[word RealModeEAX] - popfd - ret - - bits 16 - - section .bss1 - alignb 4 -RealModeSSSP resd 1 ; Real-mode SS:SP -RealModeEAX resd 1 ; Real mode EAX -PMESP resd 1 ; Protected-mode ESP -Com32SysSP resw 1 ; SP saved during COM32 syscall - - section .text diff --git a/core/comboot.inc b/core/comboot.inc index bbb0ad71..57e631ef 100644 --- a/core/comboot.inc +++ b/core/comboot.inc @@ -17,7 +17,7 @@ ;; Common code for running a COMBOOT image ;; - section .text + section .text16 ; Parameter registers definition; this is the definition ; of the stack frame used by INT 21h and INT 22h. @@ -148,8 +148,8 @@ comboot_return: cli ; Don't trust anyone jmp comboot_exit ; -; Set up the COMBOOT API interrupt vectors. This is also used -; by the COM32 code. +; Set up the COMBOOT API interrupt vectors. This is now done at +; initialization time. ; comboot_setup_api: mov di,DOSErrTramp ; Error trampolines @@ -178,11 +178,23 @@ comboot_setup_api: loop .loop2 ret - section .bss +; +; Restore the original state of the COMBOOT API vectors +; +comboot_cleanup_api: + pusha + mov si,DOSSaveVectors + mov di,4*20h + mov cx,20h + rep movsd ; Restore DOS-range vectors + popa + ret + + section .bss16 alignb 4 DOSSaveVectors resd 32 - section .data + section .data16 %define comboot_err(x) (DOSErrTramp+4*((x)-20h)) comboot_vectors: @@ -219,7 +231,7 @@ comboot_vectors: dw comboot_err(3Eh) ; INT 3E = DOS FPU emulation dw comboot_err(3Fh) ; INT 3F = DOS overlay manager - section .text + section .text16 ; INT 21h: generic DOS system call comboot_int21: cli @@ -296,12 +308,6 @@ comboot_exit_msg: pop bx ; Return address RESET_STACK_AND_SEGS SI ; Contains cld call adjust_screen ; The COMBOOT program might have changed the screen - pusha - mov si,DOSSaveVectors - mov di,4*20h - mov cx,20h - rep movsd ; Restore DOS-range vectors - popa jcxz .nomsg mov si,KernelCName call writestr @@ -692,7 +698,7 @@ comapi_dnsresolv: comapi_dnsresolv equ comapi_err %endif - section .text + section .text16 ; ; INT 22h AX=0011h Obsolete @@ -964,7 +970,7 @@ comapi_shufraw: mov ecx,P_ECX jmp shuffle_and_boot_raw - section .data + section .data16 %macro int21 2 db %1 @@ -1043,7 +1049,7 @@ 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 .bss16 alignb 4 DOSErrTramp resd 33 ; Error trampolines ConfigName resb FILENAME_MAX diff --git a/core/common.inc b/core/common.inc new file mode 100644 index 00000000..ad64c23c --- /dev/null +++ b/core/common.inc @@ -0,0 +1,20 @@ +; +; Modules common to all derivatives. Do not include modules in this list +; which have special section requirements (i.e. need to be in .init for +; some derivatives.) +; + +%include "getc.inc" ; getc et al +%include "conio.inc" ; Console I/O +%include "configinit.inc" ; Initialize configuration +%include "parseconfig.inc" ; High-level config file handling +%include "parsecmd.inc" ; Low-level config file handling +%include "pm.inc" ; Protected mode +%include "bcopy32.inc" ; 32-bit bcopy +%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 +%include "strcpy.inc" ; strcpy() +%include "idle.inc" ; Idle handling +%include "adv.inc" ; Auxillary Data Vector diff --git a/core/configinit.inc b/core/configinit.inc index cf6a814c..1dd253ce 100644 --- a/core/configinit.inc +++ b/core/configinit.inc @@ -16,7 +16,7 @@ ;; Initialize the configuration section ;; - section .text + section .text16 reset_config: call highmemsize @@ -54,6 +54,6 @@ mkkeymap: stosb ret - section .data + section .data16 linuxauto_cmd db 'linux auto',0 linuxauto_len equ $-linuxauto_cmd diff --git a/core/conio.inc b/core/conio.inc index d1b92f54..08cf5382 100644 --- a/core/conio.inc +++ b/core/conio.inc @@ -23,7 +23,7 @@ ; loadkeys: Load a LILO-style keymap; file is open on the top of the ; getc stack. ; - section .text + section .text16 loadkeys: mov cx,256 @@ -365,7 +365,7 @@ debug_tracer: pushad ret %endif ; DEBUG_TRACERS - section .data + section .data16 %if IS_ISOLINUX == 0 ; Defined elsewhere for ISOLINUX crlf_msg db CR, LF null_msg db 0 @@ -378,7 +378,7 @@ DisplayCon dw 01h ; Console display enabled ScrollAttribute db 07h ; Grey on white (normal text color) - section .bss + section .bss16 alignb 2 NextCharJump resw 1 ; Routine to interpret next print char CursorDX equ $ @@ -398,3 +398,5 @@ FlowDummy resb 1 ; Unused TextAttribute resb 1 ; Text attribute for message file DisplayMask resb 1 ; Display modes mask + + section .text16 diff --git a/core/cpuinit.inc b/core/cpuinit.inc index 4d8cc2e7..fdd097ae 100644 --- a/core/cpuinit.inc +++ b/core/cpuinit.inc @@ -39,14 +39,14 @@ dosram_k equ (real_mode_seg+0x1000) >> 6 ; Minimum DOS memory (K) enough_ram: skip_checks: - section .data + section .data16 err_noram db 'It appears your computer has less than ' asciidec dosram_k db 'K of low ("DOS")' db CR, LF - db 'RAM. Linux needs at least this amount to boot. If you get' + db 'RAM. Syslinux needs at least this amount to boot. If you get' db CR, LF db 'this message in error, hold down the Ctrl key while' db CR, LF db 'booting, and I will take your word for it.', CR, LF, 0 - section .text + section .text16 diff --git a/core/diskstart.inc b/core/diskstart.inc index c3881eab..b713a1ea 100644 --- a/core/diskstart.inc +++ b/core/diskstart.inc @@ -18,11 +18,12 @@ ; ; Expanded superblock - section .bss + section .earlybss alignb 8 SuperInfo resq 16 ; The first 16 bytes expanded 8 times +DriveNumber resb 1 - section .text + section .init ; ; Some of the things that have to be saved very early are saved ; "close" to the initial stack pointer offset, in order to @@ -33,6 +34,7 @@ PartInfo equ StackBuf ; Saved partition table entry FloppyTable equ PartInfo+16 ; Floppy info table (must follow PartInfo) OrigFDCTabPtr equ StackBuf-8 ; The 2nd high dword on the stack OrigESDI equ StackBuf-4 ; The high dword on the stack +StackTop equ OrigFDCTabPtr ; The start of the canonical stack ; ; Primary entry point. Tempting as though it may be, we can't put the @@ -411,7 +413,7 @@ disk_error: kaboom: xor si,si mov ss,si - mov sp,StackBuf-4 ; Reset stack + mov sp,OrigFDCTabPtr ; Reset stack mov ds,si ; Reset data segment pop dword [fdctab] ; Restore FDC table .patch: ; When we have full code, intercept here @@ -480,18 +482,14 @@ ldlinux_magic dd LDLINUX_MAGIC ; LDLINUX_MAGIC, plus 8 bytes. ; patch_area: -LDLDwords dw 0 ; Total dwords starting at ldlinux_sys, - ; not including ADVs -LDLSectors dw 0 ; Number of sectors - (bootsec+this sec) - ; but including any ADVs +DataSectors dw 0 ; Number of sectors (not including bootsec) +ADVSectors dw 0 ; Additional sectors for ADVs +LDLDwords dd 0 ; Total dwords starting at ldlinux_sys, CheckSum dd 0 ; Checksum starting at ldlinux_sys ; value = LDLINUX_MAGIC - [sum of dwords] -%if IS_EXTLINUX -CurrentDir dd 2 ; "Current" directory inode number -%endif - -; Space for up to 64 sectors, the theoretical maximum -SectorPtrs times 64 dd 0 +CurrentDir dd 2 ; "Current" directory inode number (EXTLINUX) +SecPtrOffset dw SectorPtrs - ldlinux_sys +SecPtrCnt dw (SectorPtrsEnd - SectorPtrs) >> 2 ldlinux_ent: ; @@ -522,23 +520,25 @@ print_bios: mov [BIOSName],si call writestr_early - section .bss + section .earlybss %define HAVE_BIOSNAME 1 BIOSName resw 1 - section .text + section .init ; ; Now we read the rest of LDLINUX.SYS. Don't bother loading the first ; sector again, though. ; load_rest: - mov si,SectorPtrs - mov bx,7C00h+2*SECTOR_SIZE ; Where we start loading - mov cx,[LDLSectors] + lea esi,[SectorPtrs] + mov ebx,7C00h+2*SECTOR_SIZE ; Where we start loading + mov cx,[DataSectors] + dec cx ; Minus this sector .get_chunk: jcxz .done - xor bp,bp + xor ebp,ebp + mov di,bx ; Low 64K of target address lodsd ; First sector of this chunk mov edx,eax @@ -547,16 +547,27 @@ load_rest: inc bp dec cx jz .chunk_ready + cmp ebx,esi ; Pointer we don't have yet? + jae .chunk_ready inc edx ; Next linear sector cmp [si],edx ; Does it match jnz .chunk_ready ; If not, this is it add si,4 ; If so, add sector to chunk - jmp short .make_chunk + add di,SECTOR_SIZE ; Check for 64K segment wrap + jnz .make_chunk .chunk_ready: + push ebx + push es + shr ebx,4 ; Convert to a segment + mov es,bx + xor bx,bx + xor edx,edx ; Zero-extend LBA call getlinsecsr - shl bp,SECTOR_SHIFT - add bx,bp + pop es + pop ebx + shl ebp,SECTOR_SHIFT + add ebx,ebp jmp .get_chunk .done: @@ -568,14 +579,23 @@ load_rest: ; verify_checksum: mov si,ldlinux_sys - mov cx,[LDLDwords] - mov edx,-LDLINUX_MAGIC + mov ecx,[LDLDwords] + mov eax,-LDLINUX_MAGIC + push ds .checksum: - lodsd - add edx,eax - loop .checksum + add eax,[si] + add si,4 + jnz .nowrap + ; Handle segment wrap + mov dx,ds + add dx,1000h + mov ds,dx +.nowrap: + dec ecx + jnz .checksum + pop ds - and edx,edx ; Should be zero + and eax,eax ; Should be zero jz all_read ; We're cool, go for it! ; @@ -641,15 +661,23 @@ rl_checkpt equ $ ; Must be <= 8000h rl_checkpt_off equ ($-$$) %ifndef DEPEND -%if rl_checkpt_off > 400h +%if rl_checkpt_off > 3FCh ; Need one pointer in here %error "Sector 1 overflow" %endif %endif +; Sector pointers + alignz 4 + global MaxInitDataSize +MaxInitDataSize equ 96 << 10 +SectorPtrs times MaxInitDataSize >> SECTOR_SHIFT dd 0 +SectorPtrsEnd equ $ + ; ---------------------------------------------------------------------------- ; End of code and data that have to be in the first sector ; ---------------------------------------------------------------------------- + section .text16 all_read: ; ; Let the user (and programmer!) know we got this far. This used to be @@ -678,4 +706,3 @@ expand_super: ; ; Fall through to the mainline code... ; - section .text diff --git a/core/dnsresolv.inc b/core/dnsresolv.inc index c2c429cb..7b632378 100644 --- a/core/dnsresolv.inc +++ b/core/dnsresolv.inc @@ -24,7 +24,7 @@ DNS_MAX_PACKET equ 512 ; Defined by protocol DNS_LOCAL_PORT equ htons(60053) ; All local DNS queries come from this port # DNS_MAX_SERVERS equ 4 ; Max no of DNS servers - section .text + section .text16 ; ; Turn a string in DS:SI into a DNS "label set" in ES:DI. @@ -150,14 +150,14 @@ dns_skiplabel: .rdata: equ $ endstruc - section .bss2 + section .bss16 alignb 2 DNSSendBuf resb DNS_MAX_PACKET DNSRecvBuf resb DNS_MAX_PACKET LocalDomain resb 256 ; Max possible length DNSServers resd DNS_MAX_SERVERS - section .data + section .data16 pxe_udp_write_pkt_dns: .status: dw 0 ; Status .sip: dd 0 ; Server IP @@ -185,7 +185,7 @@ LastDNSServer dw DNSServers ; ; No segment assumptions permitted. ; - section .text + section .text16 dns_resolv: push ds push es diff --git a/core/extern.inc b/core/extern.inc new file mode 100644 index 00000000..f765cffe --- /dev/null +++ b/core/extern.inc @@ -0,0 +1,15 @@ +; +; extern.inc +; +; Prototypes for external functions + +%ifndef EXTERN_INC +%define EXTERN_INC + + ; rllpack.c + extern rllpack, rllunpack + + ; hello.c + extern hello + +%endif ; EXTERN_INC diff --git a/core/extlinux.asm b/core/extlinux.asm index 46faac55..3a054b22 100644 --- a/core/extlinux.asm +++ b/core/extlinux.asm @@ -92,13 +92,12 @@ trackbufsize equ 8192 trackbuf resb trackbufsize ; Track buffer goes here ; ends at 2800h - section .bss + section .bss16 SuperBlock resb 1024 ; ext2 superblock ClustSize resd 1 ; Bytes/cluster ("block") ClustMask resd 1 ; Sectors/cluster - 1 PtrsPerBlock1 resd 1 ; Pointers/cluster PtrsPerBlock2 resd 1 ; (Pointers/cluster)^2 -DriveNumber resb 1 ; BIOS drive number ClustShift resb 1 ; Shift count for sectors/cluster ClustByteShift resb 1 ; Shift count for bytes/cluster @@ -111,6 +110,12 @@ Files resb MAX_OPEN*open_file_t_size %include "diskstart.inc" ; +; Common initialization code +; +%include "init.inc" +%include "cpuinit.inc" + +; ; Load the real (ext2) superblock; 1024 bytes long at offset 1024 ; mov bx,SuperBlock @@ -146,12 +151,6 @@ Files resb MAX_OPEN*open_file_t_size mov [PtrsPerBlock2],edx ; -; Common initialization code -; -%include "init.inc" -%include "cpuinit.inc" - -; ; Initialize the metadata cache ; call initcache @@ -161,7 +160,12 @@ Files resb MAX_OPEN*open_file_t_size ; verbosity and using the full screen system ; ; E9 = JMP NEAR - mov dword [kaboom.patch],0e9h+((kaboom2-(kaboom.patch+3)) << 8) + mov di,kaboom.patch + mov al,0e9h + stosb + mov ax,kaboom2-2 + sub ax,di + stosw ; ; Now we're all set to start with our *real* business. First load the @@ -341,11 +345,11 @@ open_inode: pop di ret - section .bss + section .bss16 alignb 4 ThisInode resb EXT2_GOOD_OLD_INODE_SIZE ; The most recently opened inode - section .text + section .text16 ; ; close_file: ; Deallocates a file structure (pointer in SI) @@ -573,7 +577,7 @@ searchdir: jmp .symlink_finish - section .bss + section .bss16 alignb 4 SymlinkBuf resb SYMLINK_SECTORS*SECTOR_SIZE+64 SymlinkTmpBuf equ trackbuf @@ -582,7 +586,7 @@ ThisDir resd 1 EndBlock resw 1 SymlinkCtr resb 1 - section .text + section .text16 ; ; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed ; to by ES:DI; ends on encountering any whitespace. @@ -865,31 +869,19 @@ build_curdir_str: ; Common modules ; ----------------------------------------------------------------------------- -%include "getc.inc" ; getc et al -%include "conio.inc" ; Console I/O +%include "common.inc" ; Universal modules %include "plaincon.inc" ; writechr %include "writestr.inc" ; String output %include "writehex.inc" ; Hexadecimal output -%include "configinit.inc" ; Initialize configuration -%include "parseconfig.inc" ; High-level config file handling -%include "parsecmd.inc" ; Low-level config file handling -%include "bcopy32.inc" ; 32-bit bcopy -%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 -%include "strcpy.inc" ; strcpy() %include "strecpy.inc" ; strcpy with end pointer check %include "cache.inc" ; Metadata disk cache -%include "idle.inc" ; Idle handling -%include "adv.inc" ; Auxillary Data Vector %include "localboot.inc" ; Disk-based local boot ; ----------------------------------------------------------------------------- ; Begin data section ; ----------------------------------------------------------------------------- - section .data + section .data16 copyright_str db ' Copyright (C) 1994-' asciidec YEAR db ' H. Peter Anvin et al', CR, LF, 0 diff --git a/core/font.inc b/core/font.inc index 4090e5af..12236358 100644 --- a/core/font.inc +++ b/core/font.inc @@ -16,7 +16,7 @@ ;; VGA font handling code ;; - section .text + section .text16 ; ; loadfont: Load a .psf font file and install it onto the VGA console @@ -141,12 +141,12 @@ vidrows_ok: mov [VidRows],al popa ret - section .data + section .data16 alignz 2 VGAFontSize dw 16 ; Defaults to 16 byte font UserFont db 0 ; Using a user-specified font - section .bss1 + section .bss16 alignb 4 GXPixCols resw 1 ; Graphics mode pixel columns GXPixRows resw 1 ; Graphics mode pixel rows diff --git a/core/getc.inc b/core/getc.inc index bb12047b..a8d54c7f 100644 --- a/core/getc.inc +++ b/core/getc.inc @@ -321,7 +321,7 @@ parseint: .isk: shl ebx,10 ; * 2^10 jmp .fini - section .bss1 + section .bss16 alignb 4 NumBuf resb 15 ; Buffer to load number NumBufEnd resb 1 ; Last byte in NumBuf @@ -329,14 +329,14 @@ NumBufEnd resb 1 ; Last byte in NumBuf GetCStack resb getc_file_size*MAX_GETC .end equ $ - section .data + section .data16 CurrentGetC dw GetCStack.end ; GetCStack empty ; ; unhexchar: Convert a hexadecimal digit in AL to the equivalent number; ; return CF=1 if not a hex digit ; - section .text + section .text16 unhexchar: cmp al,'0' jb .ret ; If failure, CF == 1 already diff --git a/core/graphics.inc b/core/graphics.inc index 3ba51465..d530193f 100644 --- a/core/graphics.inc +++ b/core/graphics.inc @@ -21,7 +21,7 @@ ; ; Assumes CS == DS == ES. ; - section .text + section .text16 vgadisplayfile: ; This is a cheap and easy way to make sure the screen is @@ -300,7 +300,7 @@ vgacursorcommon: ret - section .data + section .data16 ; Map colors to consecutive DAC registers linear_color db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 @@ -308,7 +308,7 @@ linear_color db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 ; of this byte. UsingVGA db 0 - section .bss2 + section .bss16 alignb 4 LSSHeader equ $ LSSMagic resd 1 ; Magic number diff --git a/core/head.inc b/core/head.inc index 37f1b36f..ff62b602 100644 --- a/core/head.inc +++ b/core/head.inc @@ -23,6 +23,8 @@ %include "macros.inc" %include "config.inc" %include "layout.inc" +%include "pmcall.inc" +%include "extern.inc" %include "kernel.inc" %include "bios.inc" %include "tracers.inc" diff --git a/core/hello.c b/core/hello.c new file mode 100644 index 00000000..6c12c738 --- /dev/null +++ b/core/hello.c @@ -0,0 +1,27 @@ +#include <stddef.h> +#include "core.h" + +void myputchar(int c) +{ + static com32sys_t ireg; + static uint16_t *vram = 0xb8000; + + ireg.eax.b[1] = 0x02; + ireg.edx.b[0] = c; + core_intcall(0x21, &ireg, NULL); + + *vram++ = c + 0x1f00; +} + +void myputs(const char *str) +{ + while (*str) + myputchar(*str++); +} + +void hello(void) +{ + static char hello_str[] = "Hello, World! (hello.c)\r\n"; + + myputs(hello_str); +} diff --git a/core/highmem.inc b/core/highmem.inc index 5ae3abea..2a4c59e1 100644 --- a/core/highmem.inc +++ b/core/highmem.inc @@ -17,7 +17,7 @@ ;; mem= command on the command line while booting a new kernel. ;; - section .text + section .text16 ; ; This is set up as a subroutine; it will set up the global variable @@ -155,7 +155,7 @@ got_highmem: pop es ret ; Done! - section .bss + section .bss16 alignb 4 E820Buf resd 6 ; INT 15:E820 data buffer E820Mem resd 1 ; Memory detected by E820 diff --git a/core/idle.inc b/core/idle.inc index c2ce1348..4b073641 100644 --- a/core/idle.inc +++ b/core/idle.inc @@ -11,7 +11,7 @@ ;; ;; ----------------------------------------------------------------------- - section .text + section .text16 TICKS_TO_IDLE equ 4 reset_idle: @@ -42,9 +42,9 @@ do_idle: pop ax .ret: ret - section .data + section .data16 NoHalt dw 0 IdleHook dw do_idle.ret - section .bss + section .bss16 IdleTimer resw 1 diff --git a/core/include/core.h b/core/include/core.h new file mode 100644 index 00000000..bfbd6075 --- /dev/null +++ b/core/include/core.h @@ -0,0 +1,10 @@ +#ifndef CORE_H +#define CORE_H + +#include <com32.h> + +void __cdecl core_intcall(uint8_t, const com32sys_t *, com32sys_t *); +void __cdecl core_farcall(uint32_t, const com32sys_t *, com32sys_t *); +int __cdecl core_cfarcall(uint32_t, const void *, uint32_t); + +#endif /* CORE_H */ diff --git a/core/init.inc b/core/init.inc index 0b213ace..7f65ffa6 100644 --- a/core/init.inc +++ b/core/init.inc @@ -2,6 +2,7 @@ ; ----------------------------------------------------------------------- ; ; Copyright 2004-2008 H. Peter Anvin - All Rights Reserved +; Copyright 2009 Intel Corporation; author: H. Peter Anvin ; ; 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 @@ -17,10 +18,30 @@ ; Common initialization code (inline) ; - section .text + section .text16 common_init: - ; Now set up screen parameters - call adjust_screen + ; Initialize PM invocation framework + call pm_init + + ; Copy PM code to its target location + mov esi,__pm_code_lma + mov edi,__pm_code_start + mov ecx,__pm_code_len + call bcopy + or esi,-1 ; bzero + mov edi,__bss_start + mov ecx,__bss_len + call bcopy + + ; Zero bss sections (but not .earlybss, since it may + ; contain already-live data.) + xor eax,eax + mov di,__bss16_start + mov cx,__bss16_dwords + rep stosd + mov di,__uibss_start + mov cx,__uibss_dwords + rep stosd ; ; Initialize configuration information @@ -28,13 +49,8 @@ common_init: call reset_config ; -; Clear Files structures +; Initialize Files structures (other than zeroing) ; - mov di,Files - mov cx,(MAX_OPEN*open_file_t_size)/4 - xor eax,eax - rep stosd - %if IS_PXELINUX mov di,Files+tftp_pktbuf mov cx,MAX_OPEN @@ -44,4 +60,13 @@ common_init: add ax,PKTBUF_SIZE loop .setbufptr %endif - section .text ; This is an inline file... + +; +; Set up the COMBOOT APIs +; + call comboot_setup_api + +; +; Now set up screen parameters +; + call adjust_screen diff --git a/core/isolinux.asm b/core/isolinux.asm index cc97f479..4ed12a74 100644 --- a/core/isolinux.asm +++ b/core/isolinux.asm @@ -91,8 +91,8 @@ trackbuf resb trackbufsize ; Track buffer goes here ; ends at 2800h ; Some of these are touched before the whole image - ; is loaded. DO NOT move this to .uibss. - section .bss2 + ; is loaded. DO NOT move this to .bss16/.uibss. + section .earlybss alignb 4 ISOFileName resb 64 ; ISO filename canonicalization buffer ISOFileNameEnd equ $ @@ -187,10 +187,11 @@ dsp_dummy: resb 1 ; Scratch, safe to overwrite _spec_end equ $ _spec_len equ _spec_end - _spec_start + section .bss16 alignb open_file_t_size Files resb MAX_OPEN*open_file_t_size - section .text + section .init ;; ;; Primary entry point. Because BIOSes are buggy, we only load the first ;; CD-ROM sector (2K) of the file, so the number one priority is actually @@ -200,6 +201,7 @@ StackBuf equ $-44 ; 44 bytes needed for ; the bootsector chainloading ; code! OrigESDI equ StackBuf-4 ; The high dword on the stack +StackTop equ OrigESDI bootsec equ $ @@ -682,9 +684,7 @@ writemsg: push ax ; writechr: - jmp near writechr_simple ; 3-byte jump - -writechr_simple: +.simple: pushfd pushad mov ah,0Eh @@ -1069,6 +1069,8 @@ rl_checkpt equ $ ; Must be <= 800h ; End of code and data that have to be in the first sector ; ---------------------------------------------------------------------------- + section .text16 + all_read: ; Test tracers @@ -1082,7 +1084,12 @@ all_read: %include "cpuinit.inc" ; Patch the writechr routine to point to the full code - mov word [writechr+1], writechr_full-(writechr+3) + mov di,writechr + mov al,0e9h + stosb + mov ax,writechr_full-2 + sub ax,di + stosw ; Tell the user we got this far... %ifndef DEBUG_MESSAGES ; Gets messy with debugging on @@ -1685,27 +1692,15 @@ getfssec: ; Common modules ; ----------------------------------------------------------------------------- -%include "getc.inc" ; getc et al -%include "conio.inc" ; Console I/O -%include "configinit.inc" ; Initialize configuration -%include "parseconfig.inc" ; High-level config file handling -%include "parsecmd.inc" ; Low-level config file handling -%include "bcopy32.inc" ; 32-bit bcopy -%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 -%include "strcpy.inc" ; strcpy() +%include "common.inc" ; Universal modules %include "rawcon.inc" ; Console I/O w/o using the console functions -%include "idle.inc" ; Idle handling -%include "adv.inc" ; Auxillary Data Vector %include "localboot.inc" ; Disk-based local boot ; ----------------------------------------------------------------------------- ; Begin data section ; ----------------------------------------------------------------------------- - section .data + section .data16 default_str db 'default', 0 default_len equ ($-default_str) diff --git a/core/layout.inc b/core/layout.inc index 8d567455..850f243f 100644 --- a/core/layout.inc +++ b/core/layout.inc @@ -39,10 +39,10 @@ LATEBSS_START equ 0B800h section .config write progbits align=4 section .replacestub exec write progbits align=16 - ; Use .bss for things that doesn't have to be in low memory; - ; with .bss1 and .bss2 to offload. .earlybss should be used - ; for things that absolutely have to be below 0x7c00. - section .bss write nobits align=16 + ; Use .bss16 for things that doesn't have to be in low memory; + ; .earlybss should be used for things that absolutely have + ; to be below 0x7c00. + section .bss16 write nobits align=16 %if 0 ; IS_PXELINUX ; Warning here: RBFG build 22 randomly overwrites @@ -54,11 +54,11 @@ LATEBSS_START equ 0B800h RBFG_brainfuck: resb 2048 ; Bigger than an Ethernet packet... %endif - section .bss2 write nobits align=16 - - section .text exec write progbits align=16 + section .init exec write progbits align=1 + section .text16 exec write progbits align=1 + section .textnr exec nowrite progbits align=1 section .bcopyxx exec write progbits align=16 - section .data write progbits align=16 + section .data16 write progbits align=16 section .adv write nobits align=512 @@ -68,20 +68,22 @@ RBFG_brainfuck: resb 2048 ; Bigger than an Ethernet packet... ; the spillover from the last fractional sector load. section .uibss write nobits align=16 - ; Normal bss... - section .bss1 write nobits align=16 - ; Symbols from linker script %macro SECINFO 1 extern __%1_start, __%1_lma, __%1_end extern __%1_len, __%1_dwords %endmacro + SECINFO bss16 + SECINFO uibss SECINFO config SECINFO replacestub + SECINFO pm_code + extern __bss_start, __bss_end, __bss_len, __bss_dwords + global _start - section .text + section .text16 ; ; Segment assignments in the bottom 640K @@ -89,19 +91,24 @@ RBFG_brainfuck: resb 2048 ; Bigger than an Ethernet packet... ; failure! ; ; 0000h - main code/data segment (and BIOS segment) - -xfer_buf_seg equ 1000h -aux_seg equ 2000h +; +; This stuff really should come from the linker... +; + global xfer_buf_seg +xfer_buf_seg equ 2000h ; ; Contents of aux_seg ; + extern aux_seg ; Actual segment assigned by linker + struc aux .fontbuf resb 8192 alignb 4096 ; Align the next segment to 4K endstruc -aux_seg_end equ aux_seg + (aux_size >> 4) + section .auxseg write nobits align=16 +auxseg resb aux_size ; ; Bounce buffer for I/O to high mem @@ -111,10 +118,10 @@ aux_seg_end equ aux_seg + (aux_size >> 4) %if IS_ISOLINUX ; ISOLINUX doesn't have a block cache yet -real_mode_seg equ aux_seg_end +real_mode_seg equ 3000h %else -cache_seg equ aux_seg_end ; 64K area for metadata cache -real_mode_seg equ cache_seg + 1000h +cache_seg equ 3000h ; 64K area for metadata cache +real_mode_seg equ 4000h pktbuf_seg equ cache_seg ; PXELINUX packet buffers %endif diff --git a/core/ldlinux.asm b/core/ldlinux.asm index ba7e8040..c08799f4 100644 --- a/core/ldlinux.asm +++ b/core/ldlinux.asm @@ -106,7 +106,7 @@ trackbufsize equ 8192 trackbuf resb trackbufsize ; Track buffer goes here ; ends at 2800h - section .bss + section .bss16 alignb 4 FAT resd 1 ; Location of (first) FAT RootDirArea resd 1 ; Location of root directory area @@ -117,7 +117,6 @@ TotalSectors resd 1 ; Total number of sectors ClustSize resd 1 ; Bytes/cluster ClustMask resd 1 ; Sectors/cluster - 1 CopySuper resb 1 ; Distinguish .bs versus .bss -DriveNumber resb 1 ; BIOS drive number ClustShift resb 1 ; Shift count for sectors/cluster ClustByteShift resb 1 ; Shift count for bytes/cluster @@ -130,6 +129,12 @@ Files resb MAX_OPEN*open_file_t_size %include "diskstart.inc" ; +; Common initialization code +; +%include "init.inc" +%include "cpuinit.inc" + +; ; Compute some information about this filesystem. ; @@ -202,11 +207,6 @@ getfattype: .setsize: mov byte [nextcluster+1],cl -; -; Common initialization code -; -%include "cpuinit.inc" -%include "init.inc" ; ; Initialize the metadata cache @@ -218,7 +218,12 @@ getfattype: ; verbosity and using the full screen system ; ; E9 = JMP NEAR - mov dword [kaboom.patch],0e9h+((kaboom2-(kaboom.patch+3)) << 8) + mov di,kaboom.patch + mov al,0e9h + stosb + mov ax,kaboom2-2 + sub ax,di + stosw ; ; Now we're all set to start with our *real* business. First load the @@ -553,7 +558,7 @@ search_dos_dir: pop bx ret - section .data + section .data16 alignz 4 ; Note: we have no use of the first 32 bytes (header), ; nor of the folloing 32 bytes (case mapping of control @@ -565,7 +570,7 @@ cp_unicode equ codepage+cp.unicode cp_unicode_alt equ codepage+cp.unicode_alt codepage_end equ $ - section .text + section .text16 ; ; Input: UCS-2 character in AX ; Output: Single byte character in AL, ZF = 1 @@ -587,12 +592,12 @@ ucs2_to_cp: not ax ; Doesn't change the flags! ret - section .bss + section .bss16 VFATInit resb 1 VFATNext resb 1 VFATCsum resb 1 - section .text + section .text16 ; ; close_file: ; Deallocates a file structure (pointer in SI) @@ -946,12 +951,11 @@ readdir: .end: ret - section .bss + section .bss16 alignb 4 -CurrentDir resd 1 ; Current directory PrevDir resd 1 ; Last scanned directory - section .text + section .text16 ; ; @@ -1100,13 +1104,13 @@ mangle_dos_name: stosb ; Otherwise, write a space loop .period_loop ; Dec CX and *always* jump - section .bss + section .bss16 alignb 2 NameStart resw 1 NameLen resw 1 MangledBuf resb 11 - section .text + section .text16 ; ; getfssec_edx: Get multiple sectors from a file ; @@ -1360,30 +1364,18 @@ getfatsector: ; Common modules ; ----------------------------------------------------------------------------- -%include "getc.inc" ; getc et al -%include "conio.inc" ; Console I/O +%include "common.inc" ; Universal modules %include "plaincon.inc" ; writechr %include "writestr.inc" ; String output %include "writehex.inc" ; Hexadecimal output -%include "configinit.inc" ; Initialize configuration -%include "parseconfig.inc" ; High-level config file handling -%include "parsecmd.inc" ; Low-level config file handling -%include "bcopy32.inc" ; 32-bit bcopy -%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 -%include "strcpy.inc" ; strcpy() %include "cache.inc" ; Metadata disk cache -%include "idle.inc" ; Idle handling -%include "adv.inc" ; Auxillary Data Vector %include "localboot.inc" ; Disk-based local boot ; ----------------------------------------------------------------------------- ; Begin data section ; ----------------------------------------------------------------------------- - section .data + section .data16 copyright_str db ' Copyright (C) 1994-' asciidec YEAR db ' H. Peter Anvin et al', CR, LF, 0 diff --git a/core/loadhigh.inc b/core/loadhigh.inc index 8ff9da1c..5c9969f6 100644 --- a/core/loadhigh.inc +++ b/core/loadhigh.inc @@ -17,7 +17,7 @@ ;; Load a file into high memory ;; - section .text + section .text16 ; ; load_high: loads (the remainder of) a file into high memory. @@ -103,12 +103,12 @@ load_high: .overflow: mov si,err_nohighmem jmp abort_load - section .data + section .data16 err_nohighmem db CR, LF db 'Not enough memory to load specified image.', CR, LF, 0 - section .bss + section .bss16 alignb 2 PauseBird resw 1 - section .text + section .text16 diff --git a/core/localboot.inc b/core/localboot.inc index ae54737a..3fee7d62 100644 --- a/core/localboot.inc +++ b/core/localboot.inc @@ -22,7 +22,7 @@ ; Boot a specified local disk. AX specifies the BIOS disk number; or ; -1 in case we should execute INT 18h ("next device.") ; - section .text + section .text16 local_boot: call vgaclearmode @@ -67,9 +67,9 @@ local_boot: int 18h ; Hope this does the right thing... jmp kaboom ; If we returned, oh boy... - section .data + section .data16 localboot_msg db 'Booting from local disk...', CR, LF, 0 - section .text + section .text16 %endif ; HAS_LOCALBOOT diff --git a/core/macros.inc b/core/macros.inc index 1aa2b2ce..e3aedca1 100644 --- a/core/macros.inc +++ b/core/macros.inc @@ -47,7 +47,7 @@ ; ; Macros similar to res[bwd], but which works in the code segment (after -; section .text) or the data segment (section .data) +; section .text16) or the data segment (section .data16) ; %macro zb 1.nolist times %1 db 0 diff --git a/core/parsecmd.inc b/core/parsecmd.inc index e63c205e..94627b8c 100644 --- a/core/parsecmd.inc +++ b/core/parsecmd.inc @@ -17,7 +17,7 @@ ;; Command line parser code ;; - section .text + section .text16 ; ------------------------------------------------------------------------- ; getcommand: Get a keyword from the current "getc" file and match it @@ -106,7 +106,7 @@ skipline: cmp al,10 ; Search for LF jnc skipline .end: ret - section .data + section .data16 err_badcfg db 'Unknown keyword in configuration file: ',0 err_noparm db 'Missing parameter in configuration file. Keyword: ',0 diff --git a/core/parseconfig.inc b/core/parseconfig.inc index 61e7b330..e6819bf7 100644 --- a/core/parseconfig.inc +++ b/core/parseconfig.inc @@ -17,7 +17,7 @@ ;; Configuration file operations ;; - section .text + section .text16 ; ; "default" or "ui" command, with level (1 = default, 2 = ui) ; @@ -425,7 +425,7 @@ commit_vk: mov esi,VKernelBuf mov edi,[VKernelEnd] mov ecx,vk_size - call rllpack + pm_call rllpack mov [VKernelEnd],edi .nolabel: ret @@ -434,11 +434,11 @@ commit_vk: call writestr ret - section .data + section .data16 vk_overflow_msg db 'Out of memory parsing config file', CR, LF, 0 SerialNotice db 1 ; Only print this once - section .bss + section .bss16 alignb 4 VKernelEnd resd 1 ; Lowest high memory address used @@ -473,5 +473,3 @@ IPAppend db 0 ; Default IPAPPEND option command_line resb max_cmd_len+2 ; Command line buffer alignb 4 default_cmd resb max_cmd_len+1 ; "default" command line - -%include "rllpack.inc" diff --git a/core/plaincon.inc b/core/plaincon.inc index 59b2cbb5..c41629d0 100644 --- a/core/plaincon.inc +++ b/core/plaincon.inc @@ -2,7 +2,7 @@ ; writechr: Write a single character in AL to the console without ; mangling any registers; handle video pages correctly. ; - section .text + section .text16 writechr: call write_serial ; write to serial port if needed diff --git a/core/pm.inc b/core/pm.inc new file mode 100644 index 00000000..1e6f4178 --- /dev/null +++ b/core/pm.inc @@ -0,0 +1,459 @@ +;; ----------------------------------------------------------------------- +;; +;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved +;; Copyright 2009 Intel Corporation; author: H. Peter Anvin +;; +;; 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. +;; +;; ----------------------------------------------------------------------- + +;; +;; pm.inc +;; +;; Functions to enter and exit 32-bit protected mode, handle interrupts +;; and cross-mode calls. +;; +;; PM refers to 32-bit flat protected mode; RM to 16-bit real mode. +;; + + bits 16 + section .text16 +; +; _pm_call: call PM routine in low memory from RM +; +; on stack = PM routine to call (a 32-bit address) +; +; ECX, ESI, EDI passed to the called function; +; EAX = EBP in the called function points to the stack frame +; which includes all registers (which can be changed if desired.) +; +; All registers and the flags saved/restored +; +; This routine is invoked by the pm_call macro. +; +_pm_call: + pushfd + pushad + push ds + push es + push fs + push gs + mov bp,sp + mov ax,cs + mov ebx,.pm + mov ds,ax + jmp enter_pm + + bits 32 + section .textnr +.pm: + ; EAX points to the top of the RM stack, which is EFLAGS + test RM_FLAGSH,02h ; RM EFLAGS.IF + jz .no_sti + sti +.no_sti: + call [ebp+4*2+9*4+2] ; Entrypoint on RM stack + mov bx,.rm + jmp enter_rm + + bits 16 + section .text16 +.rm: + pop gs + pop fs + pop es + pop ds + popad + popfd + ret 4 ; Drop entrypoint + +; +; enter_pm: Go to PM with interrupt service configured +; EBX = PM entry point +; EAX = EBP = on exit, points to the RM stack as a 32-bit value +; ECX, EDX, ESI, EDI preserved across this routine +; +; Assumes CS == DS +; +; This routine doesn't enable interrupts, but the target routine +; can enable interrupts by executing STI. +; + bits 16 + section .text16 +enter_pm: + cli + xor eax,eax + mov ds,ax + mov ax,ss + mov [RealModeSSSP],sp + mov [RealModeSSSP+2],ax + movzx ebp,sp + shl eax,4 + add ebp,eax ; EBP -> top of real-mode stack + cld + call enable_a20 + +.a20ok: + mov byte [bcopy_gdt.TSS+5],89h ; Mark TSS unbusy + + lgdt [bcopy_gdt] ; We can use the same GDT just fine + lidt [PM_IDT_ptr] ; Set up the IDT + mov eax,cr0 + or al,1 + mov cr0,eax ; Enter protected mode + jmp PM_CS32:.in_pm + + bits 32 + section .textnr +.in_pm: + xor eax,eax ; Available for future use... + mov fs,eax + mov gs,eax + lldt ax + + mov al,PM_DS32 ; Set up data segments + mov es,eax + mov ds,eax + mov ss,eax + + mov al,PM_TSS ; Be nice to Intel's VT by + ltr ax ; giving it a valid TR + + mov esp,[PMESP] ; Load protmode %esp + mov eax,ebp ; EAX -> top of real-mode stack + jmp ebx ; Go to where we need to go + +; +; enter_rm: Return to RM from PM +; +; BX = RM entry point (CS = 0) +; ECX, EDX, ESI, EDI preserved across this routine +; EAX clobbered +; EBP reserved +; +; This routine doesn't enable interrupts, but the target routine +; can enable interrupts by executing STI. +; + bits 32 + section .textnr +enter_rm: + cli + cld + mov [PMESP],esp ; Save exit %esp + jmp PM_CS16:.in_pm16 ; Return to 16-bit mode first + + bits 16 + section .text16 +.in_pm16: + mov ax,PM_DS16 ; Real-mode-like segment + mov es,ax + mov ds,ax + mov ss,ax + mov fs,ax + mov gs,ax + + lidt [RM_IDT_ptr] ; Real-mode IDT (rm needs no GDT) + xor dx,dx + mov eax,cr0 + and al,~1 + mov cr0,eax + jmp 0:.in_rm + +.in_rm: ; Back in real mode + lss sp,[cs:RealModeSSSP] ; Restore stack + movzx esp,sp ; Make sure the high bits are zero + mov ds,dx ; Set up sane segments + mov es,dx + mov fs,dx + mov gs,dx + jmp bx ; Go to whereever we need to go... + + section .data16 + alignz 4 + + extern __stack_end +PMESP dd __stack_end ; Protected-mode ESP + +PM_IDT_ptr: dw 8*256-1 ; Length + dd IDT ; Offset + +; +; 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. +; + bits 32 + section .textnr +pm_irq: + pushad + movzx esi,byte [esp+8*4] ; Interrupt number + mov ebx,.rm + jmp enter_rm ; Go to real mode + + bits 16 + section .text16 +.rm: + pushf ; Flags on stack + call far [cs:esi*4] ; Call IVT entry + mov ebx,.pm + jmp enter_pm ; Go back to PM + + bits 32 + section .textnr +.pm: + popad + add esp,4 ; Drop interrupt number + iretd + + bits 16 + section .text16 +; +; Routines to enable and disable (yuck) A20. These routines are gathered +; from tips from a couple of sources, including the Linux kernel and +; http://www.x86.org/. The need for the delay to be as large as given here +; is indicated by Donnie Barnes of RedHat, the problematic system being an +; IBM ThinkPad 760EL. +; +; We typically toggle A20 twice for every 64K transferred. +; +%define IO_DELAY_PORT 80h ; Invalid port (we hope!) + +slow_out: out dx, al ; Fall through + +%macro io_delay 0 + out IO_DELAY_PORT,al + out IO_DELAY_PORT,al +%endmacro + + section .data16 + alignz 2 +A20Ptr dw a20_dunno + + section .bss16 + alignb 4 +A20Test resd 1 ; Counter for testing A20 status +A20Tries resb 1 ; Times until giving up on A20 + + section .text16 +enable_a20: + pushad + mov byte [cs:A20Tries],255 ; Times to try to make this work + +try_enable_a20: + +; +; First, see if we are on a system with no A20 gate, or the A20 gate +; is already enabled for us... +; +a20_none: + call a20_test + jnz a20_done + ; Otherwise, see if we had something memorized... + jmp word [cs:A20Ptr] + +; +; Next, try the BIOS (INT 15h AX=2401h) +; +a20_dunno: +a20_bios: + mov word [cs:A20Ptr], a20_bios + mov ax,2401h + pushf ; Some BIOSes muck with IF + int 15h + popf + + call a20_test + jnz a20_done + +; +; Enable the keyboard controller A20 gate +; +a20_kbc: + mov dl, 1 ; Allow early exit + call empty_8042 + jnz a20_done ; A20 live, no need to use KBC + + mov word [cs:A20Ptr], a20_kbc ; Starting KBC command sequence + + mov al,0D1h ; Write output port + out 064h, al + call empty_8042_uncond + + mov al,0DFh ; A20 on + out 060h, al + call empty_8042_uncond + + ; Apparently the UHCI spec assumes that A20 toggle + ; ends with a null command (assumed to be for sychronization?) + ; Put it here to see if it helps anything... + mov al,0FFh ; Null command + out 064h, al + call empty_8042_uncond + + ; Verify that A20 actually is enabled. Do that by + ; observing a word in low memory and the same word in + ; the HMA until they are no longer coherent. Note that + ; we don't do the same check in the disable case, because + ; we don't want to *require* A20 masking (SYSLINUX should + ; work fine without it, if the BIOS does.) +.kbc_wait: push cx + xor cx,cx +.kbc_wait_loop: + call a20_test + jnz a20_done_pop + loop .kbc_wait_loop + + pop cx +; +; Running out of options here. Final attempt: enable the "fast A20 gate" +; +a20_fast: + mov word [cs:A20Ptr], a20_fast + in al, 092h + or al,02h + and al,~01h ; Don't accidentally reset the machine! + out 092h, al + +.fast_wait: push cx + xor cx,cx +.fast_wait_loop: + call a20_test + jnz a20_done_pop + loop .fast_wait_loop + + pop cx + +; +; Oh bugger. A20 is not responding. Try frobbing it again; eventually give up +; and report failure to the user. +; + dec byte [cs:A20Tries] + jnz a20_dunno ; Did we get the wrong type? + + mov si, err_a20 + jmp abort_load + + section .data16 +err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0 + section .text16 + +; +; A20 unmasked, proceed... +; +a20_done_pop: pop cx +a20_done: popad + ret + +; +; This routine tests if A20 is enabled (ZF = 0). This routine +; must not destroy any register contents. +; +; The no-write early out avoids the io_delay in the (presumably common) +; case of A20 already enabled (e.g. from a previous call.) +; +a20_test: + push es + push cx + push eax + mov cx,0FFFFh ; HMA = segment 0FFFFh + mov es,cx + mov eax,[cs:A20Test] + mov cx,32 ; Loop count + jmp .test ; First iteration = early out +.wait: add eax,0x430aea41 ; A large prime number + mov [cs:A20Test],eax + io_delay ; Serialize, and fix delay +.test: cmp eax,[es:A20Test+10h] + loopz .wait +.done: pop eax + pop cx + pop es + ret + +; +; Routine to empty the 8042 KBC controller. If dl != 0 +; then we will test A20 in the loop and exit if A20 is +; suddenly enabled. +; +empty_8042_uncond: + xor dl,dl +empty_8042: + call a20_test + jz .a20_on + and dl,dl + jnz .done +.a20_on: io_delay + in al, 064h ; Status port + test al,1 + jz .no_output + io_delay + in al, 060h ; Read input + jmp short empty_8042 +.no_output: + test al,2 + jnz empty_8042 + io_delay +.done: ret + +; +; This initializes the protected-mode interrupt thunk set +; + section .text16 +pm_init: + xor edi,edi + mov bx,IDT + mov di,IRQStubs + + mov eax,7aeb006ah ; push byte .. jmp short .. + + mov cx,8 ; 8 groups of 32 IRQs +.gloop: + push cx + mov cx,32 ; 32 entries per group +.eloop: + mov [bx],di ; IDT offset [15:0] + mov word [bx+2],PM_CS32 ; IDT segment + mov dword [bx+4],08e00h ; IDT offset [31:16], 32-bit interrupt + ; gate, CPL 0 (we don't have a TSS + ; set up...) + add bx,8 + + stosd + ; Increment IRQ, decrement jmp short offset + add eax,(-4 << 24)+(1 << 8) + + loop .eloop + + ; At the end of each group, replace the EBxx with + ; the final E9xxxxxxxx + add di,3 + mov byte [di-5],0E9h ; JMP NEAR + mov edx,pm_irq + sub edx,edi + mov [di-4],edx + + add eax,(0x80 << 24) ; Proper offset for the next one + pop cx + loop .gloop + + ret + + ; pm_init is called before bss clearing, so put these + ; in .earlybss! + section .earlybss + alignb 8 +IDT: resq 256 +IRQStubs: resb 4*256+3*8 + +RealModeSSSP resd 1 ; Real-mode SS:SP + + section .text16 + +%include "callback.inc" ; Real-mode callbacks diff --git a/core/pmcall.inc b/core/pmcall.inc new file mode 100644 index 00000000..0a580150 --- /dev/null +++ b/core/pmcall.inc @@ -0,0 +1,70 @@ +;; +;; pmcall.inc +;; +;; Macros for the stack frame set up by pm_call, assuming ebp is left +;; as the RM frame pointer. +;; + +%ifndef PMCALL_INC +%define PMCALL_INC + +%define RM_GS word [ebp] +%define RM_FS word [ebp+2] +%define RM_ES word [ebp+4] +%define RM_DS word [ebp+6] + +%define RM_EDI dword [ebp+8] +%define RM_DI word [ebp+8] +%define RM_HDI word [ebp+10] +%define RM_DIL byte [ebp+8] +%define RM_DIH byte [ebp+9] + +%define RM_ESI dword [ebp+12] +%define RM_SI word [ebp+12] +%define RM_HSI word [ebp+14] +%define RM_SIL byte [ebp+12] +%define RM_SIH byte [ebp+13] + +%define RM_EBP dword [ebp+16] +%define RM_BP word [ebp+16] +%define RM_HBP word [ebp+18] +%define RM_BPL byte [ebp+16] +%define RM_BPH byte [ebp+17] + +%define RM_EBX dword [ebp+24] +%define RM_BX word [ebp+24] +%define RM_HBX word [ebp+26] +%define RM_BL byte [ebp+24] +%define RM_BH byte [ebp+25] + +%define RM_EDX dword [ebp+28] +%define RM_DX word [ebp+28] +%define RM_HDX word [ebp+30] +%define RM_DL byte [ebp+28] +%define RM_DH byte [ebp+29] + +%define RM_ECX dword [ebp+32] +%define RM_CX word [ebp+32] +%define RM_HCX word [ebp+34] +%define RM_CL byte [ebp+32] +%define RM_CH byte [ebp+33] + +%define RM_EAX dword [ebp+36] +%define RM_AX word [ebp+36] +%define RM_HAX word [ebp+38] +%define RM_AL byte [ebp+36] +%define RM_AH byte [ebp+37] + +%define RM_EFLAGS dword [ebp+40] +%define RM_FLAGS word [ebp+40] +%define RM_HFLAGS word [ebp+42] +%define RM_FLAGSL byte [ebp+40] +%define RM_FLAGSH byte [ebp+41] + +; Convenience macro to call a PM function +%macro pm_call 1 + push dword %1 + call _pm_call +%endmacro + +%endif ; PMCALL_INC diff --git a/core/pxeidle.inc b/core/pxeidle.inc index f661b57a..1d458810 100644 --- a/core/pxeidle.inc +++ b/core/pxeidle.inc @@ -18,7 +18,7 @@ ;; Query for the NIC type, and detect certain special cases. ;; - section .text + section .text16 ;; ;; Initializes the idle mechanism based on the device type @@ -55,7 +55,7 @@ pxe_detect_nic_type: ;; ;; List of devices for which we want to actually issue idle calls. ;; - section .data + section .data16 alignz 4 pxe_idle_pci_list: ; @@ -76,7 +76,7 @@ pxe_idle_pci_list: ; .len equ ($-pxe_idle_pci_list) >> 2 - section .bss + section .bss16 pxenv_get_nic_type: .status: resw 1 .nic_type: resb 1 @@ -90,7 +90,7 @@ pxenv_get_nic_type: .svid: resw 1 .sdid: resw 1 - section .text + section .text16 ; ; Call the receive loop while idle. This is done mostly so we can respond to ; ARP messages, but perhaps in the future this can be used to do network diff --git a/core/pxelinux.asm b/core/pxelinux.asm index ad1686c1..4352903d 100644 --- a/core/pxelinux.asm +++ b/core/pxelinux.asm @@ -161,6 +161,7 @@ trackbufsize equ 8192 trackbuf resb trackbufsize ; Track buffer goes here ; ends at 2800h + section .bss16 alignb open_file_t_size Files resb MAX_OPEN*open_file_t_size @@ -172,7 +173,6 @@ IPOption resb 80 ; ip= option buffer InitStack resd 1 ; Pointer to reset stack (SS:SP) PXEStack resd 1 ; Saved stack during PXE call - section .bss alignb 4 RebootTime resd 1 ; Reboot timeout, if set by option StrucPtr resd 1 ; Pointer to PXENV+ or !PXE structure @@ -207,17 +207,18 @@ pxe_unload_stack_pkt_len equ $-pxe_unload_stack_pkt alignb 16 ; BOOTP/DHCP packet buffer - section .bss2 + section .bss16 alignb 16 packet_buf resb 2048 ; Transfer packet packet_buf_size equ $-packet_buf - section .text + section .text16 ; ; PXELINUX needs more BSS than the other derivatives; ; therefore we relocate it from 7C00h on startup. ; StackBuf equ $ ; Base of stack if we use our own +StackTop equ $ ; ; Primary entry point. @@ -1459,12 +1460,12 @@ is_gpxe: pop es jmp .again - section .data + section .data16 gpxe_warning_msg: db 'URL syntax, but gPXE extensions not detected, ' db 'trying plain TFTP...', CR, LF, 0 HasGPXE db -1 ; Unknown - section .text + section .text16 %endif @@ -1628,11 +1629,11 @@ pxenv: ; Must be after function def due to NASM bug PXEEntry equ pxenv.jump+1 - section .bss + section .bss16 alignb 2 PXEStatus resb 2 - section .text + section .text16 ; ; getfssec: Get multiple clusters from a file, given the starting cluster. @@ -1876,14 +1877,14 @@ fill_buffer: ; ; This is roughly an exponential backoff... ; - section .data + section .data16 TimeoutTable: db 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18 db 21, 26, 31, 37, 44, 53, 64, 77, 92, 110, 132 db 159, 191, 229, 255, 255, 255, 255 TimeoutTableEnd equ $ - section .text + section .text16 ; ; ack_packet: ; @@ -2207,10 +2208,10 @@ pxe_get_cached_info: call crlf jmp kaboom - section .data + section .data16 get_packet_msg db 'Getting cached packet', 0 - section .text + section .text16 ; ; ip_ok ; @@ -2355,15 +2356,15 @@ parse_some_dhcp_options: .done: ret - section .data + section .data16 dhcp_option_list: - section .text + section .text16 %macro dopt 2 - section .data + section .data16 db %1 dw dopt_%2 - section .text + section .text16 dopt_%2: %endmacro @@ -2488,14 +2489,14 @@ dhcp_copyoption: stosb ; Null-terminate ret - section .data + section .data16 dhcp_option_list_end: - section .text + section .text16 - section .data + section .data16 HaveUUID db 0 uuid_dashes db 4,2,2,2,6,0 ; Bytes per UUID dashed section - section .text + section .text16 ; ; genipopt @@ -2531,31 +2532,19 @@ genipopt: ; Common modules ; ----------------------------------------------------------------------------- -%include "getc.inc" ; getc et al -%include "conio.inc" ; Console I/O +%include "common.inc" ; Universal modules %include "writestr.inc" ; String output writestr_early equ writestr %include "writehex.inc" ; Hexadecimal output -%include "configinit.inc" ; Initialize configuration -%include "parseconfig.inc" ; High-level config file handling -%include "parsecmd.inc" ; Low-level config file handling -%include "bcopy32.inc" ; 32-bit bcopy -%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 -%include "strcpy.inc" ; strcpy() %include "rawcon.inc" ; Console I/O w/o using the console functions %include "dnsresolv.inc" ; DNS resolver -%include "idle.inc" ; Idle handling %include "pxeidle.inc" ; PXE-specific idle mechanism -%include "adv.inc" ; Auxillary Data Vector ; ----------------------------------------------------------------------------- ; Begin data section ; ----------------------------------------------------------------------------- - section .data + section .data16 copyright_str db ' Copyright (C) 1994-' asciidec YEAR @@ -2599,7 +2588,7 @@ bootif_str_len equ $-bootif_str ; ; Extensions to search for (in *forward* order). -; (.bs and .bss are disabled for PXELINUX, since they are not supported) +; (.bs and .bss16 are disabled for PXELINUX, since they are not supported) ; alignz 4 exten_table: db '.cbt' ; COMBOOT (specific) @@ -2628,7 +2617,7 @@ old_api_unload: ; ; PXE query packets partially filled in ; - section .bss + section .bss16 pxe_bootp_query_pkt: .status: resw 1 ; Status .packettype: resw 1 ; Boot server packet type @@ -2636,34 +2625,35 @@ pxe_bootp_query_pkt: .buffer: resw 2 ; seg:off of buffer .bufferlimit: resw 1 ; Unused - section .data pxe_udp_open_pkt: -.status: dw 0 ; Status -.sip: dd 0 ; Source (our) IP +.status: resw 1 ; Status +.sip: resd 1 ; Source (our) IP pxe_udp_close_pkt: -.status: dw 0 ; Status +.status: resw 1 ; Status pxe_udp_write_pkt: -.status: dw 0 ; Status -.sip: dd 0 ; Server IP -.gip: dd 0 ; Gateway IP -.lport: dw 0 ; Local port -.rport: dw 0 ; Remote port -.buffersize: dw 0 ; Size of packet -.buffer: dw 0, 0 ; seg:off of buffer +.status: resw 1 ; Status +.sip: resd 1 ; Server IP +.gip: resd 1 ; Gateway IP +.lport: resw 1 ; Local port +.rport: resw 1 ; Remote port +.buffersize: resw 1 ; Size of packet +.buffer: resw 2 ; seg:off of buffer pxe_udp_read_pkt: -.status: dw 0 ; Status -.sip: dd 0 ; Source IP -.dip: dd 0 ; Destination (our) IP -.rport: dw 0 ; Remote port -.lport: dw 0 ; Local port -.buffersize: dw 0 ; Max packet size -.buffer: dw 0, 0 ; seg:off of buffer +.status: resw 1 ; Status +.sip: resd 1 ; Source IP +.dip: resd 1 ; Destination (our) IP +.rport: resw 1 ; Remote port +.lport: resw 1 ; Local port +.buffersize: resw 1 ; Max packet size +.buffer: resw 2 ; seg:off of buffer %if GPXE + section .data16 + gpxe_file_api_check: .status: dw 0 ; Status .size: dw 20 ; Size in bytes @@ -2672,28 +2662,32 @@ gpxe_file_api_check: .apimask: dd 0 .flags: dd 0 + section .bss16 + gpxe_file_open: -.status: dw 0 ; Status -.filehandle: dw 0 ; FileHandle -.filename: dd 0 ; seg:off of FileName -.reserved: dd 0 +.status: resw 1 ; Status +.filehandle: resw 1 ; FileHandle +.filename: resd 1 ; seg:off of FileName +.reserved: resd 1 gpxe_get_file_size: -.status: dw 0 ; Status -.filehandle: dw 0 ; FileHandle -.filesize: dd 0 ; FileSize +.status: resw 1 ; Status +.filehandle: resw 1 ; FileHandle +.filesize: resd 1 ; FileSize gpxe_file_read: -.status: dw 0 ; Status -.filehandle: dw 0 ; FileHandle -.buffersize: dw 0 ; BufferSize -.buffer: dd 0 ; seg:off of buffer +.status: resw 1 ; Status +.filehandle: resw 1 ; FileHandle +.buffersize: resw 1 ; BufferSize +.buffer: resd 1 ; seg:off of buffer %endif ; GPXE ; ; Misc initialized (data) variables ; + section .data16 + alignz 4 BaseStack dd StackBuf ; ESP of base stack dw 0 ; SS of base stack diff --git a/core/rllpack.c b/core/rllpack.c new file mode 100644 index 00000000..26613916 --- /dev/null +++ b/core/rllpack.c @@ -0,0 +1,105 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009 Intel Corporation; author: H. Peter Anvin + * + * 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., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * rllpack.inc + * + * Very simple RLL compressor/decompressor, used to pack binary structures + * together. + * + * Format of leading byte + * 1-128 = x verbatim bytes follow + * 129-223 = (x-126) times subsequent byte + * 224-255 = (x-224)*256+(next byte) times the following byte + * 0 = end of data + * + * These structures are stored *in reverse order* in high memory. + * High memory pointers point to one byte beyond the end. + */ + +#include <com32.h> +#include <stddef.h> +#include <string.h> + +void rllpack(com32sys_t *regs) +{ + uint8_t *i = (uint8_t *)(regs->esi.l); + uint8_t *o = (uint8_t *)(regs->edi.l); + size_t cnt = regs->ecx.l; + size_t run, vrun, tcnt; + uint8_t *hdr = NULL; + uint8_t c; + + vrun = (size_t)-1; + while (cnt) { + c = *i; + + run = 1; + tcnt = (cnt > 8191) ? 8191 : cnt; + while (run < tcnt && i[run] == c) + run++; + + if (run < 3) { + if (vrun >= 128) { + hdr = --o; + vrun = 0; + } + *--o = c; + *hdr = ++vrun; + i++; + cnt--; + } else { + if (run < 224-126) { + *--o = run+126; + } else { + o -= 2; + *(uint16_t *)o = run + (224 << 8); + } + *--o = c; + vrun = (size_t)-1; + i += run; + cnt -= run; + } + } + *--o = 0; + + regs->esi.l = (size_t)i; + regs->edi.l = (size_t)o; +} + +void rllunpack(com32sys_t *regs) +{ + uint8_t *i = (uint8_t *)regs->esi.l; + uint8_t *o = (uint8_t *)regs->edi.l; + uint8_t c; + size_t n; + + while ((c = *--i)) { + if (c <= 128) { + while (c--) + *o++ = *--i; + } else { + if (c < 224) + n = c - 126; + else + n = ((c-224) << 8) + *--i; + c = *--i; + while (n--) + *o++ = c; + } + } + + regs->esi.l = (size_t)i; + regs->ecx.l = (size_t)o - regs->edi.l; + regs->edi.l = (size_t)o; +} diff --git a/core/rllpack.inc b/core/rllpack.inc deleted file mode 100644 index c3bca696..00000000 --- a/core/rllpack.inc +++ /dev/null @@ -1,164 +0,0 @@ -; -*- fundamental -*- --------------------------------------------------- -; -; Copyright 2007-2009 H. Peter Anvin - All Rights Reserved -; Copyright 2009 Intel Corporation; author: H. Peter Anvin -; -; 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. -; -; ----------------------------------------------------------------------- - -; -; rllpack.inc -; -; Very simple RLL compressor/decompressor, used to pack binary structures -; together. -; -; Format of leading byte -; 1-128 = x verbatim bytes follow -; 129-223 = (x-126) times subsequent byte -; 224-255 = (x-224)*256+(next byte) times the following byte -; 0 = end of data -; -; These structures are stored *in reverse order* in high memory. -; High memory pointers point to one byte beyond the end. -; - - section .text - -; -; rllpack: -; Pack ECX bytes from ESI into EDI. -; Returns updated ESI and EDI. -; -rllpack: - push word .pmentry - call simple_pm_call - ret - - bits 32 -.pmentry: - push ecx - push ebx - push edx -.startseq: - xor eax,eax ; Zero byte - xor ebx,ebx ; Run length zero - dec edi - mov edx,edi ; Pointer to header byte - mov [edi],al ; Create header byte - jcxz .done ; If done, this was the terminator -.stdbyte: - lodsb - dec edi - mov [edi],al - dec ecx - cmp ah,al - je .same -.diff: - mov ah,al - xor ebx,ebx -.plainbyte: - inc ebx - inc byte [edx] - jcxz .startseq - jns .stdbyte - jmp .startseq -.same: - cmp bl,2 - jb .plainbyte - ; 3 bytes or more in a row, time to convert sequence - sub [edx],bl - jnz .normal - inc edi ; We killed a whole stretch, - ; drop start byte -.normal: - inc ebx - add edi,ebx ; Remove the stored run bytes -.getrun: - jcxz .nomatch - lodsb - cmp al,ah - jne .nomatch - cmp bx,(256-224)*256-1 ; Maximum run size - jae .nomatch - inc ebx - dec ecx - jmp .getrun -.nomatch: - cmp bx,224-126 - jae .twobyte -.onebyte: - add bl,126 - dec edi - mov [edi],bl - jmp .storebyte -.twobyte: - add bh,224 - sub edi,2 - mov [edi],bx -.storebyte: - dec edi - mov [edi],ah - dec esi ; Reload subsequent byte - jmp .startseq -.done: - pop edx - pop ebx - pop ecx - ret - - bits 16 -; -; rllunpack: -; Unpack bytes from ESI into EDI -; On return ESI, EDI are updated and -; ECX contains number of bytes output. -; -rllunpack: - push word .pmentry - call simple_pm_call - ret - - bits 32 -.pmentry: - push edi - xor ecx,ecx -.header: - dec esi - mov cl,[esi] - jcxz .done - cmp cl,129 - jae .isrun - ; Not a run -.copy: - dec esi - mov al,[esi] - stosb - loop .copy - jmp .header -.isrun: - cmp cl,224 - jae .longrun - sub cl,126 -.dorun: - dec esi - mov al,[esi] - rep stosb - jmp .header -.longrun: - sub cl,224 - mov ch,cl - dec esi - mov cl,[esi] - jmp .dorun -.done: - pop ecx - sub ecx,edi - neg ecx - ret - - bits 16 diff --git a/core/runkernel.inc b/core/runkernel.inc index 8bfc8b8d..083c9672 100644 --- a/core/runkernel.inc +++ b/core/runkernel.inc @@ -629,7 +629,7 @@ writestr_qchk: jz writestr ret - section .data + section .data16 crlfloading_msg db CR, LF loading_msg db 'Loading ', 0 dotdot_msg db '.' @@ -662,7 +662,7 @@ str_initrd equ $+1 ; Pointer to "initrd=" in memory %endif db 0 - section .bss + section .bss16 alignb 4 MyHighMemSize resd 1 ; Possibly adjusted highmem size RamdiskMax resd 1 ; Highest address for ramdisk diff --git a/core/stack.inc b/core/stack.inc index f670dec0..3a4b60b3 100644 --- a/core/stack.inc +++ b/core/stack.inc @@ -1,6 +1,7 @@ ; ----------------------------------------------------------------------- ; ; Copyright 2005-2008 H. Peter Anvin - All Rights Reserved +; Copyright 2009 Intel Corporation; author: H. Peter Anvin ; ; 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 @@ -29,16 +30,11 @@ xor %1,%1 mov ds,%1 mov es,%1 -%if IS_SYSLINUX || IS_EXTLINUX - mov ss,%1 ; Just in case... - mov sp,StackBuf-2*5 ; Reset stack -%elif IS_PXELINUX +%if IS_PXELINUX lss esp,[BaseStack] -%elif IS_ISOLINUX - mov ss,%1 - mov sp,StackBuf-2*2 %else - NEED TO KNOW HOW TO RESET STACK + mov ss,%1 + mov esp,StackTop %endif sti cld diff --git a/core/strcpy.inc b/core/strcpy.inc index 2bafa7fe..9762cbbf 100644 --- a/core/strcpy.inc +++ b/core/strcpy.inc @@ -2,7 +2,7 @@ ; strcpy: Copy DS:SI -> ES:DI up to and including a null byte; ; on exit SI and DI point to the byte *after* the null byte ; - section .text + section .text16 strcpy: push ax .loop: lodsb diff --git a/core/strecpy.inc b/core/strecpy.inc index 1fc53e96..bfcddc1a 100644 --- a/core/strecpy.inc +++ b/core/strecpy.inc @@ -5,7 +5,7 @@ ; target buffer; return with CF=1 if target buffer overflows; ; the output is still zero-terminated. ; - section .text + section .text16 strecpy: push ax diff --git a/core/syslinux.ld b/core/syslinux.ld index c1da230e..9149b9b4 100644 --- a/core/syslinux.ld +++ b/core/syslinux.ld @@ -20,7 +20,8 @@ OUTPUT_ARCH(i386) EXTERN(_start) ENTRY(_start) -STACK_LEN = 4096; +STACK16_LEN = 4096; +STACK32_LEN = 8192; SECTIONS { @@ -35,15 +36,16 @@ SECTIONS __earlybss_len = __earlybss_end - __earlybss_start; __earlybss_dwords = (__earlybss_len + 3) >> 2; - .bss : { - __bss_start = .; - *(.bss) - *(.bss2) - __bss_end = .; + . = ALIGN(4); + .bss16 : { + __bss16_start = .; + *(.bss16) + __bss16_end = .; } - __bss_len = __bss_end - __bss_start; - __bss_dwords = (__bss_len + 3) >> 2; + __bss16_len = __bss16_end - __bss16_start; + __bss16_dwords = (__bss16_len + 3) >> 2; + . = ALIGN(4); .config : AT (__config_lma) { __config_start = .; *(.config) @@ -61,29 +63,52 @@ SECTIONS __replacestub_len = __replacestub_end - __replacestub_start; __replacestub_dwords = (__replacestub_len + 3) >> 2; - /* Stack */ + /* 16-bit stack */ - STACK_BASE = 0x7c00 - STACK_LEN; - . = STACK_BASE; - .stack : AT(STACK_BASE) { - __stack_start = .; - . += STACK_LEN; - __stack_end = .; + STACK16_BASE = 0x7c00 - STACK16_LEN; + . = STACK16_BASE; + .stack16 : AT(STACK16_BASE) { + __stack16_start = .; + . += STACK16_LEN; + __stack16_end = .; } - __stack_len = __stack_end - __stack_start; - __stack_dwords = (__stack_len + 3) >> 2; + __stack16_len = __stack16_end - __stack16_start; + __stack16_dwords = (__stack16_len + 3) >> 2; /* Initialized sections */ . = 0x7c00; - .text : { + .init : { FILL(0x90909090) - __text_start = .; - *(.text) - __text_end = .; + __init_start = .; + *(.init) + __init_end = .; } - __text_len = __text_end - __text_start; - __text_dwords = (__text_len + 3) >> 2; + __init_len = __init_end - __init_start; + __init_dwords = (__init_len + 3) >> 2; + + .text16 : { + FILL(0x90909090) + __text16_start = .; + *(.text16) + __text16_end = .; + } + __text16_len = __text16_end - __text16_start; + __text16_dwords = (__text16_len + 3) >> 2; + + /* + * .textnr is used for 32-bit code that is used on the code + * path to initialize the .text segment + */ + . = ALIGN(16); + .textnr : { + FILL(0x90909090) + __textnr_start = .; + *(.textnr) + __textnr_end = .; + } + __textnr_len = __textnr_end - __textnr_start; + __textnr_dwords = (__textnr_len + 3) >> 2; . = ALIGN(16); .bcopyxx : { @@ -96,13 +121,13 @@ SECTIONS __bcopyxx_dwords = (__bcopyxx_len + 3) >> 2; . = ALIGN(4); - .data : { - __data_start = .; - *(.data) - __data_end = .; + .data16 : { + __data16_start = .; + *(.data16) + __data16_end = .; } - __data_len = __data_end - __data_start; - __data_dwords = (__data_len + 3) >> 2; + __data16_len = __data16_end - __data16_start; + __data16_dwords = (__data16_len + 3) >> 2; . = ALIGN(4); __config_lma = .; @@ -112,10 +137,13 @@ SECTIONS __replacestub_lma = .; . += SIZEOF(.replacestub); - /* ADV, must be the last intialized section */ + /* The 32-bit code loads above the non-progbits sections */ + + . = ALIGN(16); + __pm_code_lma = .; . = ALIGN(512); - .adv : { + .adv (NOLOAD) : { __adv_start = .; *(.adv) __adv_end = .; @@ -125,7 +153,8 @@ SECTIONS /* Late uninitialized sections */ - .uibss : { + . = ALIGN(4); + .uibss (NOLOAD) : { __uibss_start = .; *(.uibss) __uibss_end = .; @@ -133,18 +162,87 @@ SECTIONS __uibss_len = __uibss_end - __uibss_start; __uibss_dwords = (__uibss_len + 3) >> 2; - .bss1 : { - __bss1_start = .; - *(.bss1) - __bss1_end = .; + _end16 = .; + __assert_end16 = ASSERT(_end16 <= 0x10000, "64K overflow"); + + /* + * The auxilliary data segment is allowed to spill out of the + * low 64K. + */ + + . = ALIGN(16); + .auxseg (NOLOAD) : { + __auxseg_start = .; + *(.auxseg) + __auxseg_end = .; + } + __auxseg_len = __auxseg_end - __auxseg_start; + __auxseg_dwords = (__auxseg_len + 3) >> 2; + aux_seg = __auxseg_start >> 4; + + /* + * 32-bit code. This is a hack for the moment due to the + * real-mode segments also allocated. + */ + + . = ALIGN(128); + + __pm_code_start = .; + + __text_vma = .; + __text_lma = __pm_code_lma; + .text : AT(__text_lma) { + __text_start = .; + *(.text) + __text_end = .; + } + + . = ALIGN(16); + + __rodata_vma = .; + __rodata_lma = __rodata_vma + __text_lma - __text_vma; + .rodata : AT(__rodata_lma) { + __rodata_start = .; + *(.rodata) + __rodata_end = .; + } + + . = ALIGN(16); + + __data_vma = .; + __data_lma = __data_vma + __text_lma - __text_vma; + .data : AT(__data_lma) { + __data_start = .; + *(.data) + __data_end = .; + } + + __pm_code_end = .; + __pm_code_len = __pm_code_end - __pm_code_start; + __pm_code_dwords = (__pm_code_len + 3) >> 2; + + . = ALIGN(128); + + __bss_vma = .; + .bss : AT (__bss_vma) { + __bss_start = .; + *(.bss) + __bss_end = .; } - __bss1_len = __bss1_end - __bss1_start; - __bss1_dwords = (__bss1_len + 3) >> 2; + __bss_len = __bss_end - __bss_start; + __bss_dwords = (__bss_len + 3) >> 2; - . = ASSERT(__bss1_end <= 0x10000, "64K overflow"); + . = ALIGN(128); - . = 0x100000; - .com32 : { - *(.com32) + __stack_vma = .; + .stack : AT(__stack_vma) { + __stack_start = .; + . += STACK32_LEN; + __stack_end = .; } + __stack_len = __stack_end - __stack_start; + __stack_dwords = (__stack_len + 3) >> 2; + + _end = .; + __assert_end = ASSERT(_end <= 0x20000, "pm_code_seg overflow"); } diff --git a/core/ui.inc b/core/ui.inc index a12233c2..4a97e7d3 100644 --- a/core/ui.inc +++ b/core/ui.inc @@ -45,6 +45,9 @@ no_config_file: .no_bootonce: + ; *** TEST HACK *** + pm_call hello + ; ; Check whether or not we are supposed to display the boot prompt. ; @@ -162,7 +165,7 @@ display_labels: push cx ; save command line size mov edi,VKernelBuf - call rllunpack + pm_call rllunpack ; ESI updated on return sub di,cx ; Return to beginning of buf @@ -351,7 +354,7 @@ vk_check: jbe .not_vk mov edi,VKernelBuf - call rllunpack + pm_call rllunpack ; ESI updated on return sub di,cx ; Return to beginning of buf @@ -572,12 +575,12 @@ getchar_timeout: ; ; Anything else is assumed to be a Linux kernel. ; - section .bss + section .bss16 alignb 4 Kernel_EAX resd 1 Kernel_SI resw 1 - section .text + section .text16 kernel_good_saved: ; Alternate entry point for which the return from ; searchdir is stored in memory. This is used for @@ -683,7 +686,7 @@ is_bss_sector equ is_bad_image is_disk_image equ is_bad_image %endif - section .data + section .data16 boot_prompt db 'boot: ', 0 wipe_char db BS, ' ', BS, 0 err_badimage db 'Invalid image type for this media type!', CR, LF, 0 @@ -703,7 +706,7 @@ kerneltype_table: dw is_com32_image ; VK_COM32 dw is_config_file ; VK_CONFIG - section .bss + section .bss16 alignb 4 ThisKbdTo resd 1 ; Temporary holder for KbdTimeout ThisTotalTo resd 1 ; Temporary holder for TotalTimeout @@ -713,7 +716,7 @@ KbdFlags resb 1 ; Check for keyboard escapes FuncFlag resb 1 ; Escape sequences received from keyboard KernelType resb 1 ; Kernel type, from vkernel, if known - section .text + section .text16 ; ; Linux kernel loading code is common. ; diff --git a/core/writedec.inc b/core/writedec.inc index 10bf7bae..bfac0997 100644 --- a/core/writedec.inc +++ b/core/writedec.inc @@ -16,7 +16,7 @@ ;; Write decimal numbers to the console ;; - section .text + section .text16 ; ; writedec[bwl]: Write an unsigned decimal number in (AL, AX, EAX) ; to the console diff --git a/core/writehex.inc b/core/writehex.inc index 1dbe4ab3..e2bf86b4 100644 --- a/core/writehex.inc +++ b/core/writehex.inc @@ -16,7 +16,6 @@ ;; Write hexadecimal numbers to the console ;; - section .text ; ; writehex[248]: Write a hex number in (AL, AX, EAX) to the console ; diff --git a/core/writestr.inc b/core/writestr.inc index 4adc6bf4..9c11b320 100644 --- a/core/writestr.inc +++ b/core/writestr.inc @@ -16,7 +16,6 @@ ;; Code to write a simple string. ;; - section .text ; ; crlf: Print a newline ; |