summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BUGS4
-rw-r--r--Makefile2
-rw-r--r--TODO22
-rw-r--r--core/Makefile39
-rw-r--r--core/abort.inc6
-rw-r--r--core/adv.inc22
-rw-r--r--core/bcopy32.inc307
-rw-r--r--core/bcopyxx.inc18
-rw-r--r--core/bootsect.inc4
-rw-r--r--core/cache.inc4
-rw-r--r--core/callback.inc208
-rw-r--r--core/cleanup.inc4
-rw-r--r--core/cmdline.inc4
-rw-r--r--core/com32.inc379
-rw-r--r--core/comboot.inc36
-rw-r--r--core/common.inc20
-rw-r--r--core/configinit.inc4
-rw-r--r--core/conio.inc8
-rw-r--r--core/cpuinit.inc6
-rw-r--r--core/diskstart.inc87
-rw-r--r--core/dnsresolv.inc8
-rw-r--r--core/extern.inc15
-rw-r--r--core/extlinux.asm46
-rw-r--r--core/font.inc6
-rw-r--r--core/getc.inc6
-rw-r--r--core/graphics.inc6
-rw-r--r--core/head.inc2
-rw-r--r--core/hello.c27
-rw-r--r--core/highmem.inc4
-rw-r--r--core/idle.inc6
-rw-r--r--core/include/core.h10
-rw-r--r--core/init.inc45
-rw-r--r--core/isolinux.asm37
-rw-r--r--core/layout.inc45
-rw-r--r--core/ldlinux.asm54
-rw-r--r--core/loadhigh.inc8
-rw-r--r--core/localboot.inc6
-rw-r--r--core/macros.inc2
-rw-r--r--core/parsecmd.inc4
-rw-r--r--core/parseconfig.inc10
-rw-r--r--core/plaincon.inc2
-rw-r--r--core/pm.inc459
-rw-r--r--core/pmcall.inc70
-rw-r--r--core/pxeidle.inc8
-rw-r--r--core/pxelinux.asm122
-rw-r--r--core/rllpack.c105
-rw-r--r--core/rllpack.inc164
-rw-r--r--core/runkernel.inc4
-rw-r--r--core/stack.inc12
-rw-r--r--core/strcpy.inc2
-rw-r--r--core/strecpy.inc2
-rw-r--r--core/syslinux.ld182
-rw-r--r--core/ui.inc17
-rw-r--r--core/writedec.inc2
-rw-r--r--core/writehex.inc1
-rw-r--r--core/writestr.inc1
-rw-r--r--extlinux/main.c125
-rw-r--r--libinstaller/setadv.c13
-rw-r--r--libinstaller/syslxint.h78
-rw-r--r--version2
60 files changed, 1595 insertions, 1307 deletions
diff --git a/BUGS b/BUGS
deleted file mode 100644
index 9639da80..00000000
--- a/BUGS
+++ /dev/null
@@ -1,4 +0,0 @@
-Known bugs that have not yet been fixed:
-
-- PXELINUX: Some PXE stacks fail with routing enabled, some with
- routing disabled. Try both?
diff --git a/Makefile b/Makefile
index 76abff51..36a0612b 100644
--- a/Makefile
+++ b/Makefile
@@ -51,7 +51,7 @@ BOBJECTS = $(BTARGET) \
# Note: libinstaller is both a BSUBDIR and an ISUBDIR. It contains
# files that depend only on the B phase, but may have to be regenerated
# for "make installer".
-BSUBDIRS = codepage core memdisk modules com32 mbr memdump gpxe sample \
+BSUBDIRS = codepage com32 core memdisk modules mbr memdump gpxe sample \
libinstaller dos win32
ITARGET =
IOBJECTS = $(ITARGET) dos/copybs.com \
diff --git a/TODO b/TODO
deleted file mode 100644
index 530b4bfb..00000000
--- a/TODO
+++ /dev/null
@@ -1,22 +0,0 @@
-*** To do in the short term:
-
-- PXELINUX: Figure out localboot/idle problems.
-
-- PXELINUX: Support changing the default server and boot file prefix?
-
-- Library support for all the comboot system calls.
-
-- Deal with non-512-byte sectors (if I can get media which does...)
-
-
-*** Future projects:
-
-- Clean up the command-line parsing.
-
-- Cleaned up documentation, with a real man page.
-
-- API call to get directory listing.
-
-- COM32-based CLI.
-
-- Rewrite the filesystems to run in protected mode C code.
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
;
diff --git a/extlinux/main.c b/extlinux/main.c
index e9226fce..c4ccd538 100644
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -1,6 +1,7 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 1998-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
@@ -63,12 +64,14 @@ struct my_options {
unsigned int sectors;
unsigned int heads;
int raid_mode;
+ int stupid_mode;
int reset_adv;
const char *set_once;
} opt = {
.sectors = 0,
.heads = 0,
.raid_mode = 0,
+ .stupid_mode = 0,
.reset_adv = 0,
.set_once = NULL,
};
@@ -82,6 +85,7 @@ static void __attribute__((noreturn)) usage(int rv)
" --zip -z Force zipdrive geometry (-H 64 -S 32)\n"
" --sectors=# -S Force the number of sectors per track\n"
" --heads=# -H Force number of heads\n"
+ " --stupid -s Slow, safe and stupid mode\n"
" --raid -r Fall back to the next device on boot failure\n"
" --once=... -o Execute a command once upon boot\n"
" --clear-once -O Clear the boot-once command\n"
@@ -109,6 +113,7 @@ static const struct option long_options[] = {
{ "update", 0, NULL, 'U' },
{ "zipdrive", 0, NULL, 'z' },
{ "sectors", 1, NULL, 'S' },
+ { "stupid", 0, NULL, 's' },
{ "heads", 1, NULL, 'H' },
{ "raid-mode", 0, NULL, 'r' },
{ "version", 0, NULL, 'v' },
@@ -126,57 +131,6 @@ static const char short_options[] = "iUuzS:H:rvho:O";
# define BLKGETSIZE64 _IOR(0x12,114,size_t)
#endif
-#define LDLINUX_MAGIC 0x3eb202fe
-
-enum bs_offsets {
- bsJump = 0x00,
- bsOemName = 0x03,
- bsBytesPerSec = 0x0b,
- bsSecPerClust = 0x0d,
- bsResSectors = 0x0e,
- bsFATs = 0x10,
- bsRootDirEnts = 0x11,
- bsSectors = 0x13,
- bsMedia = 0x15,
- bsFATsecs = 0x16,
- bsSecPerTrack = 0x18,
- bsHeads = 0x1a,
- bsHiddenSecs = 0x1c,
- bsHugeSectors = 0x20,
-
- /* FAT12/16 only */
- bs16DriveNumber = 0x24,
- bs16Reserved1 = 0x25,
- bs16BootSignature = 0x26,
- bs16VolumeID = 0x27,
- bs16VolumeLabel = 0x2b,
- bs16FileSysType = 0x36,
- bs16Code = 0x3e,
-
- /* FAT32 only */
- bs32FATSz32 = 36,
- bs32ExtFlags = 40,
- bs32FSVer = 42,
- bs32RootClus = 44,
- bs32FSInfo = 48,
- bs32BkBootSec = 50,
- bs32Reserved = 52,
- bs32DriveNumber = 64,
- bs32Reserved1 = 65,
- bs32BootSignature = 66,
- bs32VolumeID = 67,
- bs32VolumeLabel = 71,
- bs32FileSysType = 82,
- bs32Code = 90,
-
- bsSignature = 0x1fe
-};
-
-#define bsHead bsJump
-#define bsHeadLen (bsOemName-bsHead)
-#define bsCode bs32Code /* The common safe choice */
-#define bsCodeLen (bsSignature-bs32Code)
-
#ifndef EXT2_SUPER_OFFSET
#define EXT2_SUPER_OFFSET 1024
#endif
@@ -406,8 +360,10 @@ patch_file_and_bootblock(int fd, int dirfd, int devfd)
uint32_t *sectp;
uint64_t totalbytes, totalsectors;
int nsect;
- unsigned char *p, *patcharea;
- int i, dw;
+ uint32_t *wp;
+ struct boot_sector *bs;
+ struct patch_area *patcharea;
+ int i, dw, nptrs;
uint32_t csum;
if ( fstat(dirfd, &dirst) ) {
@@ -428,26 +384,28 @@ patch_file_and_bootblock(int fd, int dirfd, int devfd)
early bootstrap share code with the FAT version. */
dprintf("heads = %u, sect = %u\n", geo.heads, geo.sectors);
+ bs = (struct boot_sector *)boot_block;
+
totalsectors = totalbytes >> SECTOR_SHIFT;
if ( totalsectors >= 65536 ) {
- set_16(boot_block+bsSectors, 0);
+ set_16(&bs->bsSectors, 0);
} else {
- set_16(boot_block+bsSectors, totalsectors);
+ set_16(&bs->bsSectors, totalsectors);
}
- set_32(boot_block+bsHugeSectors, totalsectors);
+ set_32(&bs->bsHugeSectors, totalsectors);
- set_16(boot_block+bsBytesPerSec, SECTOR_SIZE);
- set_16(boot_block+bsSecPerTrack, geo.sectors);
- set_16(boot_block+bsHeads, geo.heads);
- set_32(boot_block+bsHiddenSecs, geo.start);
+ set_16(&bs->bsBytesPerSec, SECTOR_SIZE);
+ set_16(&bs->bsSecPerTrack, geo.sectors);
+ set_16(&bs->bsHeads, geo.heads);
+ set_32(&bs->bsHiddenSecs, geo.start);
/* If we're in RAID mode then patch the appropriate instruction;
either way write the proper boot signature */
- i = get_16(boot_block+0x1FE);
+ i = get_16(&bs->bsSignature);
if (opt.raid_mode)
- set_16(boot_block+i, 0x18CD); /* INT 18h */
+ set_16((uint16_t *)(boot_block+i), 0x18CD); /* INT 18h */
- set_16(boot_block+0x1FE, 0xAA55);
+ set_16(&bs->bsSignature, 0xAA55);
/* Construct the boot file */
@@ -461,37 +419,39 @@ patch_file_and_bootblock(int fd, int dirfd, int devfd)
}
/* First sector need pointer in boot sector */
- set_32(boot_block+0x1F8, *sectp++);
- nsect--;
+ set_32(&bs->NextSector, *sectp++);
+
+ /* Stupid mode? */
+ if (opt.stupid_mode)
+ set_16(&bs->MaxTransfer, 1);
/* Search for LDLINUX_MAGIC to find the patch area */
- for ( p = boot_image ; get_32(p) != LDLINUX_MAGIC ; p += 4 );
- patcharea = p+8;
+ for (wp = (uint32_t *)boot_image; get_32(wp) != LDLINUX_MAGIC; wp++);
+ patcharea = (struct patch_area *)wp;
/* Set up the totals */
dw = boot_image_len >> 2; /* COMPLETE dwords, excluding ADV */
- set_16(patcharea, dw);
- set_16(patcharea+2, nsect); /* Not including the first sector, but
- including the ADV */
- set_32(patcharea+8, dirst.st_ino); /* "Current" directory */
+ set_16(&patcharea->data_sectors, nsect-2); /* -2 for the ADVs */
+ set_16(&patcharea->adv_sectors, 2);
+ set_32(&patcharea->dwords, dw);
+ set_32(&patcharea->currentdir, dirst.st_ino);
/* Set the sector pointers */
- p = patcharea+12;
+ wp = (uint32_t *)((char *)boot_image+get_16(&patcharea->secptroffset));
+ nptrs = get_16(&patcharea->secptrcnt);
- memset(p, 0, 64*4);
- while ( nsect-- ) {
- set_32(p, *sectp++);
- p += 4;
- }
+ memset(wp, 0, nptrs*4);
+ while ( nsect-- )
+ set_32(wp++, *sectp++);
/* Now produce a checksum */
- set_32(patcharea+4, 0);
+ set_32(&patcharea->checksum, 0);
csum = LDLINUX_MAGIC;
- for ( i = 0, p = boot_image ; i < dw ; i++, p += 4 )
- csum -= get_32(p); /* Negative checksum */
+ for (i = 0, wp = (uint32_t *)boot_image; i < dw; i++, wp++)
+ csum -= get_32(wp); /* Negative checksum */
- set_32(patcharea+4, csum);
+ set_32(&patcharea->checksum, csum);
}
/*
@@ -981,6 +941,9 @@ main(int argc, char *argv[])
case 'r':
opt.raid_mode = 1;
break;
+ case 's':
+ opt.stupid_mode = 1;
+ break;
case 'i':
update_only = 0;
break;
diff --git a/libinstaller/setadv.c b/libinstaller/setadv.c
index c768d1b1..c57f0974 100644
--- a/libinstaller/setadv.c
+++ b/libinstaller/setadv.c
@@ -36,14 +36,14 @@ static void cleanup_adv(unsigned char *advbuf)
uint32_t csum;
/* Make sure both copies agree, and update the checksum */
- set_32(advbuf, ADV_MAGIC1);
+ set_32((uint32_t *)advbuf, ADV_MAGIC1);
csum = ADV_MAGIC2;
for (i = 8; i < ADV_SIZE-4; i += 4)
- csum -= get_32(advbuf+i);
+ csum -= get_32((uint32_t *)(advbuf+i));
- set_32(advbuf+4, csum);
- set_32(advbuf+ADV_SIZE-4, ADV_MAGIC3);
+ set_32((uint32_t *)(advbuf+4), csum);
+ set_32((uint32_t *)(advbuf+ADV_SIZE-4), ADV_MAGIC3);
memcpy(advbuf+ADV_SIZE, advbuf, ADV_SIZE);
}
@@ -130,12 +130,13 @@ static int adv_consistent(const unsigned char *p)
int i;
uint32_t csum;
- if (get_32(p) != ADV_MAGIC1 || get_32(p+ADV_SIZE-4) != ADV_MAGIC3)
+ if (get_32((uint32_t *)p) != ADV_MAGIC1 ||
+ get_32((uint32_t *)(p+ADV_SIZE-4)) != ADV_MAGIC3)
return 0;
csum = 0;
for (i = 4; i < ADV_SIZE-4; i += 4)
- csum += get_32(p+i);
+ csum += get_32((uint32_t *)(p+i));
return csum == ADV_MAGIC2;
}
diff --git a/libinstaller/syslxint.h b/libinstaller/syslxint.h
index 120026de..3cecf3c0 100644
--- a/libinstaller/syslxint.h
+++ b/libinstaller/syslxint.h
@@ -18,12 +18,12 @@
/*
* Access functions for littleendian numbers, possibly misaligned.
*/
-static inline uint8_t get_8(const unsigned char *p)
+static inline uint8_t get_8(const uint8_t *p)
{
return *(const uint8_t *)p;
}
-static inline uint16_t get_16(const unsigned char *p)
+static inline uint16_t get_16(const uint16_t *p)
{
#if defined(__i386__) || defined(__x86_64__)
/* Littleendian and unaligned-capable */
@@ -33,7 +33,7 @@ static inline uint16_t get_16(const unsigned char *p)
#endif
}
-static inline uint32_t get_32(const unsigned char *p)
+static inline uint32_t get_32(const uint32_t *p)
{
#if defined(__i386__) || defined(__x86_64__)
/* Littleendian and unaligned-capable */
@@ -44,7 +44,7 @@ static inline uint32_t get_32(const unsigned char *p)
#endif
}
-static inline void set_16(unsigned char *p, uint16_t v)
+static inline void set_16(uint16_t *p, uint16_t v)
{
#if defined(__i386__) || defined(__x86_64__)
/* Littleendian and unaligned-capable */
@@ -55,7 +55,7 @@ static inline void set_16(unsigned char *p, uint16_t v)
#endif
}
-static inline void set_32(unsigned char *p, uint32_t v)
+static inline void set_32(uint32_t *p, uint32_t v)
{
#if defined(__i386__) || defined(__x86_64__)
/* Littleendian and unaligned-capable */
@@ -71,4 +71,72 @@ static inline void set_32(unsigned char *p, uint32_t v)
#define SECTOR_SHIFT 9 /* 512-byte sectors */
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
+#define LDLINUX_MAGIC 0x3eb202fe
+
+/* Patch area for disk-based installers */
+struct patch_area {
+ uint32_t magic; /* LDLINUX_MAGIC */
+ uint32_t instance; /* Per-version value */
+ uint16_t data_sectors;
+ uint16_t adv_sectors;
+ uint32_t dwords;
+ uint32_t checksum;
+ uint32_t currentdir;
+ uint16_t secptroffset;
+ uint16_t secptrcnt;
+};
+
+ /* FAT bootsector format, also used by other disk-based derivatives */
+struct boot_sector {
+ uint8_t bsJump[3];
+ char bsOemName[8];
+ uint16_t bsBytesPerSec;
+ uint8_t bsSecPerClust;
+ uint16_t bsResSectors;
+ uint8_t bsFATs;
+ uint16_t bsRootDirEnts;
+ uint16_t bsSectors;
+ uint8_t bsMedia;
+ uint16_t bsFATsecs;
+ uint16_t bsSecPerTrack;
+ uint16_t bsHeads;
+ uint32_t bsHiddenSecs;
+ uint32_t bsHugeSectors;
+
+ union {
+ struct {
+ uint8_t DriveNumber;
+ uint8_t Reserved1;
+ uint8_t BootSignature;
+ uint32_t VolumeID;
+ char VolumeLabel[11];
+ char FileSysType[8];
+ uint8_t Code[442];
+ } __attribute__((packed)) bs16;
+ struct {
+ uint32_t FATSz32;
+ uint16_t ExtFlags;
+ uint16_t FSVer;
+ uint32_t RootClus;
+ uint16_t FSInfo;
+ uint16_t BkBootSec;
+ uint8_t DriveNumber;
+ uint8_t Reserved1;
+ uint8_t BootSignature;
+ uint32_t VolumeID;
+ char VolumeLabel[11];
+ char FileSysType[8];
+ uint8_t Code[414];
+ } __attribute__((packed)) bs32;
+ } __attribute__((packed));
+
+ uint32_t NextSector; /* Pointer to the first unused sector */
+ uint16_t MaxTransfer; /* Max sectors per transfer */
+ uint16_t bsSignature;
+} __attribute__((packed));
+
+#define bsHead bsJump
+#define bsHeadLen offsetof(struct boot_sector, bsJump)
+#define bsCode bs32.Code /* The common safe choice */
+
#endif /* SYSLXINT_H */
diff --git a/version b/version
index 3020fabd..6b7452cc 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-3.81 2009
+4.00 2009