summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2007-02-10 13:22:40 -0800
committerH. Peter Anvin <hpa@zytor.com>2007-02-10 13:22:40 -0800
commit14df2f8046001f2dc24e1f65bb17c6e31dfbbd09 (patch)
treee1aa9c709cd2e3ff208d2160157bac9f3acff61c
parent1970446f95df5ac0a0d3b2b0e90b72e0dd353699 (diff)
parentd48bb2b249d996587cfe6e39e810a9805d013abe (diff)
downloadsyslinux-14df2f8046001f2dc24e1f65bb17c6e31dfbbd09.tar.gz
Merge with git+ssh://master.kernel.org/pub/scm/boot/syslinux/syslinux.git#syslinux-3.3xsyslinux-3.40-pre5
-rw-r--r--Makefile34
-rw-r--r--Makefile.private4
-rw-r--r--NEWS11
-rw-r--r--README.menu4
-rw-r--r--TODO1
-rw-r--r--abort.inc2
-rw-r--r--bootsect.inc6
-rw-r--r--cache.inc85
-rw-r--r--com32/lib/MCONFIG7
-rw-r--r--com32/lib/sys/fileread.c4
-rw-r--r--com32/libutil/Makefile2
-rw-r--r--com32/modules/Makefile2
-rw-r--r--com32/samples/Makefile2
-rw-r--r--comboot.doc2
-rw-r--r--comboot.inc2
-rw-r--r--dos/Makefile7
-rw-r--r--dummy.c8
-rw-r--r--extlinux.asm6
-rw-r--r--extlinux/Makefile8
-rw-r--r--font.inc2
-rw-r--r--head.inc2
-rw-r--r--layout.inc4
-rw-r--r--ldlinux.asm16
-rw-r--r--loadhigh.inc2
-rw-r--r--mbr/Makefile47
-rwxr-xr-xmbr/checksize.pl31
-rw-r--r--mbr/mbr.S299
-rw-r--r--mbr/mbr.ld73
-rw-r--r--mbr/oldmbr.asm (renamed from mbr.asm)0
-rw-r--r--memdisk/Makefile2
-rw-r--r--memdisk/memdisk.asm11
-rw-r--r--memdisk/memdisk.doc8
-rw-r--r--memdisk/setup.c24
-rw-r--r--menu/Makefile2
-rw-r--r--mtools/Makefile8
-rw-r--r--mtools/syslinux.c2
-rw-r--r--sample/Makefile2
-rw-r--r--ui.inc22
-rw-r--r--unix/Makefile12
-rw-r--r--unix/syslinux.c389
40 files changed, 865 insertions, 290 deletions
diff --git a/Makefile b/Makefile
index 7673cf5c..5a27526c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
## -----------------------------------------------------------------------
##
-## Copyright 1998-2006 H. Peter Anvin - All Rights Reserved
+## Copyright 1998-2007 H. Peter Anvin - All Rights Reserved
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
@@ -17,12 +17,18 @@
# No builtin rules
MAKEFLAGS = -r
+gcc_ok = $(shell if gcc $(1) dummy.c -o /dev/null 2>/dev/null; \
+ then echo '$(1)'; else echo '$(2)'; fi)
+
+comma := ,
+LDHASH := $(call gcc_ok,-Wl$(comma)--hash-style=both,)
+
OSTYPE = $(shell uname -msr)
CC = gcc
INCLUDE =
CFLAGS = -W -Wall -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64
PIC = -fPIC
-LDFLAGS = -O2 -s
+LDFLAGS = -O2 -s $(LDHASH)
AR = ar
RANLIB = ranlib
@@ -63,12 +69,16 @@ BINFILES = bootsect_bin.c ldlinux_bin.c mbr_bin.c \
# mingw suite installed
BTARGET = kwdhash.gen version.gen version.h \
ldlinux.bss ldlinux.sys ldlinux.bin \
- pxelinux.0 mbr.bin isolinux.bin isolinux-debug.bin \
+ pxelinux.0 isolinux.bin isolinux-debug.bin \
extlinux.bin extlinux.bss extlinux.sys
-BOBJECTS = $(BTARGET) dos/syslinux.com win32/syslinux.exe memdisk/memdisk
+BOBJECTS = $(BTARGET) mbr/mbr.bin dos/syslinux.com win32/syslinux.exe memdisk/memdisk
+# BESUBDIRS and IESUBDIRS are "early", i.e. before the root; BSUBDIRS
+# and ISUBDIRS are "late", after the root.
+BESUBDIRS = mbr
BSUBDIRS = memdisk dos win32
ITARGET = copybs.com gethostip mkdiskimage
IOBJECTS = $(ITARGET) mtools/syslinux unix/syslinux extlinux/extlinux
+IESUBDIRS =
ISUBDIRS = mtools unix extlinux sample com32
DOCS = COPYING NEWS README TODO BUGS *.doc sample menu com32
OTHER = Makefile bin2c.pl now.pl genhash.pl keywords findpatch.pl \
@@ -82,7 +92,7 @@ INSTALL_BIN = mtools/syslinux gethostip ppmtolss16 lss16toppm
INSTALL_SBIN = extlinux/extlinux
# Things to install in /usr/lib/syslinux
INSTALL_AUX = pxelinux.0 isolinux.bin isolinux-debug.bin \
- dos/syslinux.com copybs.com memdisk/memdisk mbr.bin
+ dos/syslinux.com copybs.com memdisk/memdisk mbr/mbr.bin
INSTALL_AUX_OPT = win32/syslinux.exe
# The DATE is set on the make command line when building binaries for
@@ -102,9 +112,10 @@ MAKE += DATE=$(DATE) HEXDATE=$(HEXDATE)
# error every time you try to build.
#
-all: all-local
- set -e ; for i in $(BSUBDIRS) $(ISUBDIRS) ; do $(MAKE) -C $$i $@ ; done
+all:
+ set -e ; for i in $(BESUBDIRS) $(IESUBDIRS) ; do $(MAKE) -C $$i $@ ; done
$(MAKE) all-local
+ set -e ; for i in $(BSUBDIRS) $(ISUBDIRS) ; do $(MAKE) -C $$i $@ ; done
-ls -l $(BOBJECTS) $(IOBJECTS)
all-local: $(BTARGET) $(ITARGET) $(BINFILES)
@@ -167,10 +178,7 @@ extlinux.bss: extlinux.bin
extlinux.sys: extlinux.bin
dd if=$< of=$@ bs=512 skip=1
-mbr.bin: mbr.asm
- $(NASM) -f bin -l mbr.lst -o mbr.bin mbr.asm
-
-mbr_bin.c: mbr.bin bin2c.pl
+mbr_bin.c: mbr/mbr.bin bin2c.pl
$(PERL) bin2c.pl syslinux_mbr < $< > $@
copybs.com: copybs.asm
@@ -199,8 +207,8 @@ $(LIB_SO): bootsect_bin.o ldlinux_bin.o syslxmod.o
gethostip: gethostip.o
$(CC) $(LDFLAGS) -o $@ $^
-mkdiskimage: mkdiskimage.in mbr.bin bin2hex.pl
- $(PERL) bin2hex.pl < mbr.bin | cat mkdiskimage.in - > $@
+mkdiskimage: mkdiskimage.in mbr/mbr.bin bin2hex.pl
+ $(PERL) bin2hex.pl < mbr/mbr.bin | cat mkdiskimage.in - > $@
chmod a+x $@
install: installer
diff --git a/Makefile.private b/Makefile.private
index 63a3bbdf..8573aa44 100644
--- a/Makefile.private
+++ b/Makefile.private
@@ -35,8 +35,8 @@ burn: isolinux.iso
cdrecord -v blank=fast isolinux.iso
official:
- $(MAKE) spotless CC='$(CC) -m32'
- $(MAKE) depend CC='$(CC) -m32'
+ $(MAKE) spotless CC='$(CC) -m32'
+ $(MAKE) depend CC='$(CC) -m32'
$(MAKE) all CC='$(CC) -m32'
$(MAKE) dist CC='$(CC) -m32'
diff --git a/NEWS b/NEWS
index 646b5c2f..2b450a0f 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,17 @@ Changes in 3.40:
* It is now supported to load a different configuration file
with the CONFIG keyword.
+Changes in 3.36:
+ * MEMDISK: Disable EDD by default on floppy disks. EDD can be
+ enabled with the "edd" option and disabled with "noedd".
+ This (hopefully) should make Ghost work again.
+ * SYSLINUX: "unix" installer now uses Linux ioctls instead of
+ using libfat.
+ * New MBR which can boot from logical partitions.
+ * SYSLINUX: Fix bug in detecting special extensions which was
+ introduced in 3.35 :(
+ * PXELINUX: Unbreak chainbooting FreeBSD (and possibly others.)
+
Changes in 3.35:
* MEMDISK: New "safeint" mode.
* MEMDISK: Be more compliant with the PnP BIOS spec.
diff --git a/README.menu b/README.menu
index 6f0fd83c..fe4f9091 100644
--- a/README.menu
+++ b/README.menu
@@ -186,13 +186,13 @@ MENU COLOR element ansi foreground background shadow
represents fully transparent, and #ffffffff represents opaque
white.
-
+
"shadow" controls the handling of the graphical console text
shadow. Permitted values are "none" (no shadowing), "std" or
"standard" (standard shadowing - foreground pixels are
raised), "all" (both background and foreground raised), and
"rev" or "reverse" (background pixels are raised.)
-
+
If any field is set to "*" or omitted (at the end of the line)
then that field is left unchanged.
diff --git a/TODO b/TODO
index e2aacca6..93f3194d 100644
--- a/TODO
+++ b/TODO
@@ -31,4 +31,3 @@
- COM32-based CLI.
- Rewrite the filesystems to run in protected mode C code.
-
diff --git a/abort.inc b/abort.inc
index e6bf0d52..fd136529 100644
--- a/abort.inc
+++ b/abort.inc
@@ -62,4 +62,4 @@ error_or_command:
mov cx,[OnerrorLen]
and cx,cx
jnz on_error
- jmp enter_command \ No newline at end of file
+ jmp enter_command
diff --git a/bootsect.inc b/bootsect.inc
index 16c5f5e9..7c288daf 100644
--- a/bootsect.inc
+++ b/bootsect.inc
@@ -136,6 +136,11 @@ replace_bootstrap:
mov [es:di+12],esi ; New ESI
mov [es:di+6],bx ; New DS
+%if IS_PXELINUX == 0
+ ; DON'T DO THIS FOR PXELINUX...
+ ; For PXE, ES:BX -> PXENV+, and this would corrupt
+ ; that use.
+
; Hunt for $PnP header if one exists
mov ax,0F000h
mov fs,ax
@@ -163,6 +168,7 @@ replace_bootstrap:
; Found a valid $PnP header, point ES:DI to it
mov [es:di+8], bx ; New DI
mov [es:di+4], fs ; New ES
+%endif
.donepnp:
pop ax ; Copy list count
diff --git a/cache.inc b/cache.inc
index e2595a21..47d815f6 100644
--- a/cache.inc
+++ b/cache.inc
@@ -1,6 +1,6 @@
; -*- fundamental -*- ---------------------------------------------------
;
-; Copyright 2004 H. Peter Anvin - All Rights Reserved
+; Copyright 2004-2007 H. Peter Anvin - All Rights Reserved
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
@@ -11,17 +11,33 @@
; -----------------------------------------------------------------------
section .text
+
+ struc cptr
+.sector: resd 1 ; Sector number
+.prev: resw 1 ; LRU pointer to previous (less recent)
+.next: resw 1 ; LRU pointer to next (more recent)
+ endstruc
+cptr_size_lg2 equ 3
+
+NCacheEntries equ 65536/SECTOR_SIZE
+
;
; initcache: Initialize the cache data structures
;
initcache:
xor eax,eax ; We don't care about sector 0
mov di,CachePtrs
- mov cx,65536/SECTOR_SIZE
- rep stosd
+ mov cx,NCacheEntries+1
+ mov bx,CachePtrs+NCacheEntries*cptr_size ; "prev" pointer
+.loop:
+ mov [di+cptr.sector],eax ; Zero sector number
+ mov [di+cptr.prev],bx ; Previous pointer
+ mov [bx+cptr.next],di ; Previous entry's next pointer
+ mov bx,di
+ add di,cptr_size
+ loop .loop
ret
-
;
; getcachesector: Check for a particular sector (EAX) in the sector cache,
; and if it is already there, return a pointer in GS:SI
@@ -31,32 +47,29 @@ initcache:
;
getcachesector:
push cx
+ push bx
+ push di
mov si,cache_seg
mov gs,si
- mov si,CachePtrs ; Sector cache pointers
- mov cx,65536/SECTOR_SIZE
+ mov si,CachePtrs+cptr_size ; Real sector cache pointers
+ mov cx,NCacheEntries
.search:
cmp eax,[si]
jz .hit
- add si,4
+ add si,cptr_size
loop .search
.miss:
TRACER 'M'
- ; Need to load it. Highly inefficient cache replacement
- ; algorithm: Least Recently Written (LRW)
- push bx
+ ; Need to load it.
push es
push gs
pop es
- mov bx,[NextCacheSlot]
- inc bx
- and bx,(1 << (16-SECTOR_SHIFT))-1
- mov [NextCacheSlot],bx
- shl bx,2
- mov [CachePtrs+bx],eax
- shl bx,SECTOR_SHIFT-2
+ mov bx,[CachePtrs+cptr.next] ; "Next most recent than head node"
+ mov [bx+cptr.sector],eax
mov si,bx
+ sub bx,CachePtrs+cptr_size
+ shl bx,SECTOR_SHIFT-cptr_size_lg2 ; Buffer address
pushad
%if IS_EXTLINUX
call getonesec_ext
@@ -65,18 +78,38 @@ getcachesector:
%endif
popad
pop es
- pop bx
- pop cx
- ret
-
-.hit: ; We have it; get the pointer
+.hit:
+ ; Update LRU, then compute buffer address
TRACER 'H'
- sub si,CachePtrs
- shl si,SECTOR_SHIFT-2
+
+ ; Remove from current position in the list
+ mov bx,[si+cptr.prev]
+ mov di,[si+cptr.next]
+ mov [bx+cptr.next],di
+ mov [di+cptr.prev],bx
+
+ ; Add to just before head node
+ mov bx,[CachePtrs+cptr.prev]
+ mov [si+cptr.prev],bx
+ mov [bx+cptr.next],si
+ mov [CachePtrs+cptr.prev],si
+ mov word [si+cptr.next],CachePtrs
+
+ sub si,CachePtrs+cptr_size
+ shl si,SECTOR_SHIFT-cptr_size_lg2 ; Buffer address
+
+ pop di
+ pop bx
pop cx
ret
section .latebss
+
+ ; Each CachePtr contains:
+ ; - Block pointer
+ ; - LRU previous pointer
+ ; - LRU next pointer
+ ; The first entry is the head node of the list
alignb 4
-CachePtrs resd 65536/SECTOR_SIZE ; Cached sector pointers
-NextCacheSlot resw 1 ; Next cache slot to occupy
+CachePtrs resb (NCacheEntries+1)*cptr_size
+
diff --git a/com32/lib/MCONFIG b/com32/lib/MCONFIG
index 39b62db1..461ada44 100644
--- a/com32/lib/MCONFIG
+++ b/com32/lib/MCONFIG
@@ -1,5 +1,10 @@
# -*- makefile -*-
+gcc_ok = $(shell if gcc $(1) -c -x c /dev/null -o /dev/null 2>/dev/null; \
+ then echo $(1); else echo $(2); fi)
+
+GCCOPT := $(call gcc_ok,-m32,) $(call gcc_ok,-fno-stack-protector,)
+
CC = gcc
LD = ld
INCLUDE = -I.
@@ -21,7 +26,7 @@ LIBFLAGS = -DDYNAMIC_CRC_TABLE -DPNG_NO_CONSOLE_IO \
# fallback anyway, just use that on old machines...
# LIBFLAGS += -DPNG_NO_FLOATING_POINT_SUPPORTED
-REQFLAGS = -g -m32 -mregparm=3 -DREGPARM=3 -D__COM32__ -I. -I./sys -I../include
+REQFLAGS = $(GCCOPT) -g -mregparm=3 -DREGPARM=3 -D__COM32__ -I. -I./sys -I../include
OPTFLAGS = -Os -march=i386 -falign-functions=0 -falign-jumps=0 \
-falign-labels=0 -ffast-math -fomit-frame-pointer
WARNFLAGS = -W -Wall -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Winline
diff --git a/com32/lib/sys/fileread.c b/com32/lib/sys/fileread.c
index e184fc35..8fdd9167 100644
--- a/com32/lib/sys/fileread.c
+++ b/com32/lib/sys/fileread.c
@@ -46,7 +46,7 @@ ssize_t __file_read(struct file_info *fp, void *buf, size_t count)
memset(&ireg, 0, sizeof ireg);
ireg.eax.w[0] = 0x0007; /* Read file */
- ireg.esi.w[0] = OFFS(__com32.cs_bounce);
+ ireg.ebx.w[0] = OFFS(__com32.cs_bounce);
ireg.es = SEG(__com32.cs_bounce);
while ( count ) {
@@ -64,7 +64,7 @@ ssize_t __file_read(struct file_info *fp, void *buf, size_t count)
return -1;
}
- fp->i.filedes = ireg.esi.w[0];
+ fp->i.filedes = oreg.esi.w[0];
fp->i.nbytes = min(fp->i.length-fp->i.offset, (unsigned)MAXBLOCK);
fp->i.datap = fp->i.buf;
memcpy(fp->i.buf, __com32.cs_bounce, fp->i.nbytes);
diff --git a/com32/libutil/Makefile b/com32/libutil/Makefile
index 9adeec66..3656fb3f 100644
--- a/com32/libutil/Makefile
+++ b/com32/libutil/Makefile
@@ -32,7 +32,7 @@
gcc_ok = $(shell if gcc $(1) -c -x c /dev/null -o /dev/null 2>/dev/null; \
then echo $(1); else echo $(2); fi)
-M32 := $(call gcc_ok,-m32,)
+M32 := $(call gcc_ok,-m32,) $(call gcc_ok,-fno-stack-protector,)
CC = gcc
LD = ld -m elf_i386
diff --git a/com32/modules/Makefile b/com32/modules/Makefile
index 3c272f26..877ce399 100644
--- a/com32/modules/Makefile
+++ b/com32/modules/Makefile
@@ -17,7 +17,7 @@
gcc_ok = $(shell if gcc $(1) -c -x c /dev/null -o /dev/null 2>/dev/null; \
then echo $(1); else echo $(2); fi)
-M32 := $(call gcc_ok,-m32,)
+M32 := $(call gcc_ok,-m32,) $(call gcc_ok,-fno-stack-protector,)
CC = gcc
LD = ld -m elf_i386
diff --git a/com32/samples/Makefile b/com32/samples/Makefile
index 213ae1a3..291413a6 100644
--- a/com32/samples/Makefile
+++ b/com32/samples/Makefile
@@ -17,7 +17,7 @@
gcc_ok = $(shell if gcc $(1) -c -x c /dev/null -o /dev/null 2>/dev/null; \
then echo $(1); else echo $(2); fi)
-M32 := $(call gcc_ok,-m32,)
+M32 := $(call gcc_ok,-m32,) $(call gcc_ok,-fno-stack-protector,)
CC = gcc
LD = ld -m elf_i386
diff --git a/comboot.doc b/comboot.doc
index 00743835..0d7af174 100644
--- a/comboot.doc
+++ b/comboot.doc
@@ -699,7 +699,7 @@ AX=0017h [3.30] Report video mode change
which are undefined in the current version of SYSLINUX.
The following bits in BX are currently defined:
-
+
Bit 0: graphics mode
Indicates that the mode is a graphics mode, as opposed
diff --git a/comboot.inc b/comboot.inc
index fac5753e..304accaa 100644
--- a/comboot.inc
+++ b/comboot.inc
@@ -776,7 +776,7 @@ comapi_userfont:
.done: ; CF=0 here
mov P_AL,al
ret
-
+
;
; INT 22h AX=0019h Read disk
;
diff --git a/dos/Makefile b/dos/Makefile
index 61423cec..5fd52d1b 100644
--- a/dos/Makefile
+++ b/dos/Makefile
@@ -1,9 +1,14 @@
+gcc_ok = $(shell if gcc $(1) -c -x c /dev/null -o /dev/null 2>/dev/null; \
+ then echo $(1); else echo $(2); fi)
+
+M32 := $(call gcc_ok,-m32,) $(call gcc_ok,-ffreestanding,) $(call gcc_ok,-fno-stack-protector,)
+
CC = gcc
LD = ld -m elf_i386
OBJCOPY = objcopy
OPTFLAGS = -g -Os -march=i386 -falign-functions=0 -falign-jumps=0 -falign-loops=0 -fomit-frame-pointer
INCLUDES = -include code16.h -I. -I.. -I../libfat
-CFLAGS = -m32 -mregparm=3 -DREGPARM=3 -W -Wall -ffreestanding -msoft-float $(OPTFLAGS) $(INCLUDES)
+CFLAGS = $(M32) -mregparm=3 -DREGPARM=3 -W -Wall -msoft-float $(OPTFLAGS) $(INCLUDES)
LDFLAGS = -T com16.ld
AR = ar
RANLIB = ranlib
diff --git a/dummy.c b/dummy.c
new file mode 100644
index 00000000..81f2586c
--- /dev/null
+++ b/dummy.c
@@ -0,0 +1,8 @@
+/*
+ * Trivial C program to test the compiler
+ */
+
+int main(int argc, char *argv[])
+{
+ return 0;
+}
diff --git a/extlinux.asm b/extlinux.asm
index ddc0cc6b..e4628478 100644
--- a/extlinux.asm
+++ b/extlinux.asm
@@ -5,7 +5,7 @@
;
; A program to boot Linux kernels off an ext2/ext3 filesystem.
;
-; Copyright (C) 1994-2006 H. Peter Anvin
+; Copyright (C) 1994-2007 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
@@ -112,7 +112,7 @@ trackbuf resb trackbufsize ; Track buffer goes here
getcbuf resb trackbufsize
; ends at 4800h
- section .latebss
+ section .bss
SuperBlock resb 1024 ; ext2 superblock
SuperInfo resq 16 ; DOS superblock expanded
ClustSize resd 1 ; Bytes/cluster ("block")
@@ -1024,7 +1024,7 @@ open_inode:
pop di
ret
- section .latebss
+ section .bss
alignb 4
ThisInode resb EXT2_GOOD_OLD_INODE_SIZE ; The most recently opened inode
diff --git a/extlinux/Makefile b/extlinux/Makefile
index a450a3dc..8d347a98 100644
--- a/extlinux/Makefile
+++ b/extlinux/Makefile
@@ -1,8 +1,14 @@
+gcc_ok = $(shell if gcc $(1) ../dummy.c -o /dev/null 2>/dev/null; \
+ then echo '$(1)'; else echo '$(2)'; fi)
+
+comma := ,
+LDHASH := $(call gcc_ok,-Wl$(comma)--hash-style=both,)
+
CC = gcc
OPTFLAGS = -g -Os
INCLUDES = -I. -I.. -I../libfat
CFLAGS = -W -Wall -Wno-sign-compare -D_FILE_OFFSET_BITS=64 $(OPTFLAGS) $(INCLUDES)
-LDFLAGS = -s
+LDFLAGS = $(LDHASH) -s
SRCS = extlinux.c ../extlinux_bss_bin.c ../extlinux_sys_bin.c
OBJS = $(patsubst %.c,%.o,$(notdir $(SRCS)))
diff --git a/font.inc b/font.inc
index c2d1350e..4eeee1d5 100644
--- a/font.inc
+++ b/font.inc
@@ -75,7 +75,7 @@ use_font:
test byte [UsingVGA], 01h ; Are we in graphics mode?
jz .text
-
+
.graphics:
xor cx,cx
mov cl,bh ; CX = bytes/character
diff --git a/head.inc b/head.inc
index e0682b2f..17562079 100644
--- a/head.inc
+++ b/head.inc
@@ -1,6 +1,6 @@
; -*- fundamental -*- (asm-mode sucks)
; -----------------------------------------------------------------------
-;
+;
; Copyright 2006 H. Peter Anvin - All Rights Reserved
;
; This program is free software; you can redistribute it and/or modify
diff --git a/layout.inc b/layout.inc
index d3b9f05b..7b122d74 100644
--- a/layout.inc
+++ b/layout.inc
@@ -1,6 +1,6 @@
; -----------------------------------------------------------------------
;
-; Copyright 1994-2004 H. Peter Anvin - All Rights Reserved
+; Copyright 1994-2007 H. Peter Anvin - All Rights Reserved
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
@@ -26,7 +26,7 @@ TEXT_START equ 7C00h
; The secondary BSS section, above the text; we really wish we could
; just make it follow .bcopy32 or hang off the end,
; but it doesn't seem to work that way.
-LATEBSS_START equ 0B400h
+LATEBSS_START equ 0B200h
; Reserve memory for the stack. This causes checkov to abort the
; compile if we violate this space.
diff --git a/ldlinux.asm b/ldlinux.asm
index d1c0c65a..69259247 100644
--- a/ldlinux.asm
+++ b/ldlinux.asm
@@ -123,7 +123,6 @@ RootDir resd 1 ; Location of root directory proper
DataArea resd 1 ; Location of data area
RootDirSize resd 1 ; Root dir size in sectors
TotalSectors resd 1 ; Total number of sectors
-EndSector resd 1 ; Location of filesystem end
ClustSize resd 1 ; Bytes/cluster
ClustMask resd 1 ; Sectors/cluster - 1
CopySuper resb 1 ; Distinguish .bs versus .bss
@@ -795,9 +794,6 @@ genfatinfo:
.have_secs:
mov [TotalSectors],edx
- add edx,eax
- mov [EndSector],edx
-
mov eax,[bxResSectors]
mov [FAT],eax ; Beginning of FAT
mov edx,[bxFATsecs]
@@ -835,7 +831,7 @@ genfatinfo:
; FAT12, FAT16 or FAT28^H^H32? This computation is fscking ridiculous.
;
getfattype:
- mov eax,[EndSector]
+ mov eax,[TotalSectors]
sub eax,[DataArea]
shr eax,cl ; cl == ClustShift
mov cl,nextcluster_fat12-(nextcluster+2)
@@ -1605,11 +1601,11 @@ initrd_cmd_len equ 7
;
; Extensions to search for (in *forward* order).
;
-exten_table: db 'CBT',0 ; COMBOOT (specific)
- db 'BSS',0 ; Boot Sector (add superblock)
- db 'BS ',0 ; Boot Sector
- db 'COM',0 ; COMBOOT (same as DOS)
- db 'C32',0 ; COM32
+exten_table: db '.cbt' ; COMBOOT (specific)
+ db '.bss' ; Boot Sector (add superblock)
+ db '.bs', 0 ; Boot Sector
+ db '.com' ; COMBOOT (same as DOS)
+ db '.c32' ; COM32
exten_table_end:
dd 0, 0 ; Need 8 null bytes here
diff --git a/loadhigh.inc b/loadhigh.inc
index 7d9f57a4..283778f6 100644
--- a/loadhigh.inc
+++ b/loadhigh.inc
@@ -88,7 +88,7 @@ load_high:
sub eax,ecx
pop bx ; <AA> Pausebird function
jnz .read_loop ; More to read...
-
+
.eof:
pop es ; <AAA> ES
diff --git a/mbr/Makefile b/mbr/Makefile
new file mode 100644
index 00000000..d61f7f1c
--- /dev/null
+++ b/mbr/Makefile
@@ -0,0 +1,47 @@
+## -----------------------------------------------------------------------
+##
+## Copyright 2007 H. Peter Anvin - All Rights Reserved
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+## Boston MA 02111-1307, USA; either version 2 of the License, or
+## (at your option) any later version; incorporated herein by reference.
+##
+## -----------------------------------------------------------------------
+
+#
+# Makefile for MBR
+#
+
+gcc_ok = $(shell if gcc $(1) -c -x c /dev/null -o /dev/null 2>/dev/null; \
+ then echo $(1); else echo $(2); fi)
+
+M32 := $(call gcc_ok,-m32,) $(call gcc_ok,-ffreestanding,) $(call gcc_ok,-fno-stack-protector)
+
+CC = gcc
+LD = ld -m elf_i386
+SFLAGS = $(M32) -march=i386
+OBJCOPY = objcopy
+PERL = perl
+
+.SUFFIXES: .S .s .o .elf
+
+all: mbr.bin
+
+.PRECIOUS: %.o
+%.o: %.S
+ $(CC) $(SFLAGS) -Wa,-a=$*.lst -c -o $@ $<
+
+mbr.elf: mbr.o mbr.ld
+ $(LD) -T mbr.ld -e _start -o $@ $<
+
+mbr.bin: mbr.elf checksize.pl
+ $(OBJCOPY) -O binary $< $@
+ $(PERL) checksize.pl mbr.bin 440
+
+tidy:
+ rm -f *.o *.elf *.lst
+
+clean: tidy
+ rm -f *.bin
diff --git a/mbr/checksize.pl b/mbr/checksize.pl
new file mode 100755
index 00000000..b7d560a0
--- /dev/null
+++ b/mbr/checksize.pl
@@ -0,0 +1,31 @@
+## -----------------------------------------------------------------------
+##
+## Copyright 2007 H. Peter Anvin - All Rights Reserved
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+## Boston MA 02111-1307, USA; either version 2 of the License, or
+## (at your option) any later version; incorporated herein by reference.
+##
+## -----------------------------------------------------------------------
+
+##
+## checksize.pl
+##
+## Check the size of a binary file
+##
+
+($file, $maxsize) = @ARGV;
+
+@st = stat($file);
+if (!defined($size = $st[7])) {
+ die "$0: $file: $!\n";
+}
+if ($size > $maxsize) {
+ print STDERR "$file: too big ($size > $maxsize)\n";
+ exit 1;
+} else {
+ exit 0;
+}
+
diff --git a/mbr/mbr.S b/mbr/mbr.S
new file mode 100644
index 00000000..81e5dd00
--- /dev/null
+++ b/mbr/mbr.S
@@ -0,0 +1,299 @@
+/* -----------------------------------------------------------------------
+ *
+ * Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+ .code16
+ .text
+
+ .globl bootsec
+stack = 0x7c00
+driveno = (stack-6)
+heads = (stack-8)
+sectors = (stack-10)
+
+BIOS_page = 0x462
+
+ /* gas/ld has issues with doing this as absolute addresses... */
+ .section ".bootsec", "a", @nobits
+ .globl bootsec
+bootsec:
+ .space 512
+
+ .text
+ .globl _start
+_start:
+ cli
+ xorw %ax, %ax
+ movw %ax, %ds
+ movw %ax, %ss
+ movw $stack, %sp
+ movw %sp, %si
+ pushw %es /* es:di -> $PnP header */
+ pushw %di
+ pushw %dx /* dl -> drive number */
+ movw %ax, %es
+ sti
+ cld
+
+ /* Copy down to 0:0x600 */
+ movw $_start, %di
+ movw $(512/2), %cx
+ rep; movsw
+
+ ljmpw $0, $next
+
+next:
+ /* Check to see if we have EBIOS */
+ pushw %dx /* drive number */
+ movw $0x4100, %ax
+ movw $0x55aa, %bx
+ xorw %cx, %cx
+ xorb %dh, %dh
+ stc
+ int $0x13
+ jc 1f
+ cmpw $0xaa55, %bx
+ jne 1f
+ testb $0x01, %cl
+ jz 1f
+
+ /* We have EBIOS; patch in a jump to read_sector_ebios */
+ movw $0xeb+((read_sector_ebios-read_sector_cbios-2)<< 8), (read_sector_cbios)
+
+1:
+ popw %dx
+
+ /* Get (C)HS geometry */
+ movb $0x08, %ah
+ int $0x13
+ xorw %ax, %ax
+ movb %dh, %al /* dh = number of heads */
+ incw %ax /* From 0-based to count */
+ pushw %ax /* Save heads on the stack */
+ andw $0x3f, %cx /* Sector count */
+ pushw %cx /* Save sectors on the stack */
+
+ xorl %eax, %eax
+ pushl %eax /* Base */
+ pushl %eax /* Root */
+ call scan_partition_table
+
+ /* If we get here, we have no OS */
+ jmp missing_os
+
+/*
+ * read_sector: read a single sector pointed to by %eax to 0x7c00.
+ * CF is set on error. All registers clobbered.
+ */
+read_sector:
+read_sector_cbios:
+ movl %eax, %edx
+ shrl $16, %edx
+ divw (sectors)
+ incw %dx
+ movw %dx, %cx
+ xorw %dx, %dx
+ divw (heads)
+ /* dx = head, ax = cylinder */
+ movb %al, %ch
+ shrw $2, %ax
+ shrw %ax
+ andb $0xc0, %al
+ orb %al, %cl
+ movb %dl, %dh
+ movw $bootsec, %bx
+ movw $0x0201, %ax
+ jmp read_common
+read_sector_ebios:
+ movw $dapa, %si
+ movl %eax, 8(%si)
+ movb $0x42, %ah
+read_common:
+ movb (driveno), %dl
+ int $0x13
+ ret
+
+/*
+ * read_partition_table:
+ * Read a partition table (pointed to by %eax), and copy
+ * the partition table into the ptab buffer.
+ * Preserve registers.
+ */
+ptab = _start+446
+
+read_partition_table:
+ pushal
+ call read_sector
+ jc 20f
+ movw $bootsec+446, %si
+ movw $ptab, %di
+ movw $(16*4/2), %cx
+ rep ; movsw
+20:
+ popal
+ ret
+
+/*
+ * scan_partition_table:
+ * Scan a partition table currently loaded in the partition table
+ * area. Preserve 16-bit registers.
+ *
+ * On stack:
+ * 18(%bp) - root (offset from MBR, or 0 for MBR)
+ * 22(%bp) - base (location of this partition table)
+ */
+
+scan_partition_table:
+ pusha
+ movw %sp, %bp
+
+ /* Search for active partitions */
+ movw $ptab, %di
+ movw $4, %cx
+ xorw %ax, %ax
+5:
+ testb $0x80, (%di)
+ jz 6f
+ incw %ax
+ movw %di, %si
+6:
+ addw $16, %di
+ loopw 5b
+
+ cmpw $1, %ax /* Number of active partitions found */
+ je boot
+ ja too_many_active
+
+ /* No active partitions found, look for extended partitions */
+ movw $ptab, %di
+ movb $4, %cl /* cx == 0 here */
+7:
+ movb 4(%di), %al
+ cmpb $0x05, %al /* MS-DOS extended */
+ je 8f
+ cmpb $0x0f, %al /* Win9x extended */
+ je 8f
+ cmpb $0x85, %al /* Linux extended */
+ jne 9f
+
+ /* It is an extended partition. Read the extended partition and
+ try to scan it. If the scan returns, re-load the current
+ partition table and resume scan. */
+8:
+ movl 8(%di), %eax /* Partition table offset */
+ movl 18(%bp), %edx /* "Root" */
+ addl %edx, %eax /* Compute location of new ptab */
+ andl %edx, %edx /* Is this the MBR? */
+ jnz 10f
+ movl %eax, %edx /* Offset -> root if this was MBR */
+10:
+ pushl %eax /* Push new base */
+ pushl %edx /* Push new root */
+ call read_partition_table
+ jc 11f
+ call scan_partition_table
+11:
+ addw $8, %sp
+ /* This returned, so we need to reload the current partition table */
+ movl 22(%bp), %eax
+ call read_partition_table
+
+ /* fall through */
+9:
+ /* Not an extended partition */
+ addw $16, %di
+ loopw 7b
+
+ /* Nothing found, return */
+ popa
+ ret
+
+/*
+ * boot: invoke the actual bootstrap. (%si) points to the partition
+ * table entry, and 22(%bp) has the partition table base.
+ */
+boot:
+ movl 8(%si), %eax
+ addl 22(%bp), %eax
+ movl %eax, 8(%si)
+ pushw %si
+ call read_sector
+ popw %si
+ jc disk_error
+ cmpw $0xaa55, (bootsec+510)
+ jne missing_os /* Not a valid boot sector */
+ movw $driveno, %sp
+ popw %dx /* dl -> drive number */
+ popw %di /* es:di -> $PnP vector */
+ popw %es
+ cli
+ jmp bootsec
+
+/*
+ * error messages
+ */
+missing_os:
+ movw $missing_os_msg, %si
+ jmp error
+disk_error:
+ movw $disk_error_msg, %si
+ jmp error
+too_many_active:
+ movw $too_many_active_msg, %si
+ /* jmp error */
+
+error:
+2:
+ lodsb
+ andb %al, %al
+ jz 3f
+ movb $0x0e, %ah
+ movb (BIOS_page), %bh
+ movb $0x07, %bl
+ int $0x10
+ jmp 2b
+3:
+ int $0x18 /* Boot failure */
+ jmp . /* Die */
+
+missing_os_msg:
+ .ascii "Missing operating system."
+ .byte 0
+disk_error_msg:
+ .ascii "Operating system load error."
+ .byte 0
+too_many_active_msg:
+ .ascii "Multiple active partitions."
+ .byte 0
+
+ .balign 4
+dapa:
+ .short 16 /* Size of packet */
+ .short 1 /* Sector count */
+ .short 0x7c00 /* Buffer offset */
+ .short 0 /* Buffer segment */
+ .long 0 /* LSW of LBA */
+ .long 0 /* MSW of LBA */
diff --git a/mbr/mbr.ld b/mbr/mbr.ld
new file mode 100644
index 00000000..d14ba802
--- /dev/null
+++ b/mbr/mbr.ld
@@ -0,0 +1,73 @@
+/*
+ * Linker script for MBR
+ */
+
+/* Script for -z combreloc: combine and sort reloc sections */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386",
+ "elf32-i386")
+OUTPUT_ARCH(i386)
+EXTERN(_start)
+ENTRY(_start)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0x600;
+ .text :
+ {
+ *(.text*)
+ *(.rodata*)
+ } =0x90909090
+
+ . = ALIGN(4);
+ .data :
+ {
+ *(.data*)
+ }
+
+ . = ALIGN(128);
+ .bss :
+ {
+ *(.bss*)
+ }
+
+ . = 0x7c00;
+ .bootsec :
+ {
+ *(.bootsec)
+ }
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /DISCARD/ : { *(.note.GNU-stack) }
+}
diff --git a/mbr.asm b/mbr/oldmbr.asm
index 31bf1fdf..31bf1fdf 100644
--- a/mbr.asm
+++ b/mbr/oldmbr.asm
diff --git a/memdisk/Makefile b/memdisk/Makefile
index 1eebe637..72234cab 100644
--- a/memdisk/Makefile
+++ b/memdisk/Makefile
@@ -17,7 +17,7 @@ gcc_ok = $(shell if gcc $(1) -c -x c /dev/null -o /dev/null 2>/dev/null; \
M32 := $(call gcc_ok,-m32,)
ALIGN := $(call gcc_ok,-falign-functions=0 -falign-jumps=0 -falign-loops=0,-malign-functions=0 -malign-jumps=0 -malign-loops=0)
-FREE := $(call gcc_ok,-ffreestanding,)
+FREE := $(call gcc_ok,-ffreestanding,) $(call gcc_ok,-fno-stack-protector,)
CC = gcc
CFLAGS = $(M32) $(FREE) -g -W -Wall -Wno-sign-compare \
diff --git a/memdisk/memdisk.asm b/memdisk/memdisk.asm
index 09055d8f..1d3d39de 100644
--- a/memdisk/memdisk.asm
+++ b/memdisk/memdisk.asm
@@ -6,7 +6,7 @@
; A program to emulate an INT 13h disk BIOS from a "disk" in extended
; memory.
;
-; Copyright (C) 2001-2006 H. Peter Anvin
+; Copyright (C) 2001-2007 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
@@ -152,8 +152,8 @@ Int13Start:
mov bp,sp ; Point BP to the entry stack frame
TRACER 'F'
; Note: AH == P_AH here
- cmp ah,Int13FuncsMax
- jae Invalid_jump
+ cmp ah,[Int13MaxFunc]
+ ja Invalid_jump
xor al,al ; AL = 0 is standard entry condition
mov di,ax
shr di,7 ; Convert AH to an offset in DI
@@ -870,7 +870,7 @@ Int13Funcs dw Reset ; 00h - RESET
%endif
Int13FuncsEnd equ $
-Int13FuncsMax equ (Int13FuncsEnd-Int13Funcs) >> 1
+Int13FuncsCnt equ (Int13FuncsEnd-Int13Funcs) >> 1
%if EDD
EDD_DPT:
@@ -933,8 +933,9 @@ OldInt15 dd 0 ; INT 15h in chain
OldDosMem dw 0 ; Old position of DOS mem end
BootLoaderID db 0 ; Boot loader ID from header
; ---- MDI structure ends here ---
- db 0, 0, 0 ; pad
+Int13MaxFunc db Int13FuncsCnt-1 ; Max INT 13h function (to disable EDD)
+ db 0, 0 ; pad
MemInt1588 dw 0 ; 1MB-65MB memory amount (1K)
Cylinders dw 0 ; Cylinder count
diff --git a/memdisk/memdisk.doc b/memdisk/memdisk.doc
index fdcc259e..759a7b27 100644
--- a/memdisk/memdisk.doc
+++ b/memdisk/memdisk.doc
@@ -89,6 +89,12 @@ d) MEMDISK normally uses the BIOS "INT 15h mover" API to access high
safeint Use INT 15h access to protected memory, but invoke
INT 15h the way it was *before* MEMDISK was loaded.
+e) MEMDISK by default supports EDD/EBIOS on hard disks, but not on
+ floppy disks. This can be controlled with the options:
+
+ edd Enable EDD/EBIOS
+ noedd Disable EDD/EBIOS
+
Some interesting things to note:
@@ -136,7 +142,7 @@ http://www.ctyme.com/rbrown.htm, for a detailed description.
The MEMDISK info structure currently contains:
- [ES:DI] word Total size of structure (currently 27 bytes)
+ [ES:DI] word Total size of structure (currently 28 bytes)
[ES:DI+2] byte MEMDISK minor version
[ES:DI+3] byte MEMDISK major version
[ES:DI+4] dword Pointer to MEMDISK data in high memory
diff --git a/memdisk/setup.c b/memdisk/setup.c
index 8c83f039..d1eabc58 100644
--- a/memdisk/setup.c
+++ b/memdisk/setup.c
@@ -70,8 +70,10 @@ struct patch_area {
uint16_t olddosmem;
uint8_t bootloaderid;
+ uint8_t maxint13func;
+#define MAXINT13_NOEDD 0x16
- uint8_t _pad[3];
+ uint8_t _pad[2];
uint16_t memint1588;
uint16_t cylinders;
@@ -552,6 +554,7 @@ void setup(syscall_t cs_syscall, void *cs_bounce)
com32sys_t regs;
uint32_t ramdisk_image, ramdisk_size;
int bios_drives;
+ int do_edd = -1; /* -1 = default, 0 = no, 1 = yes */
/* Set up global variables */
syscall = cs_syscall;
@@ -579,11 +582,22 @@ void setup(syscall_t cs_syscall, void *cs_bounce)
geometry = get_disk_image_geometry(ramdisk_image, ramdisk_size);
- printf("Disk is %s %d, %u K, C/H/S = %u/%u/%u\n",
+ if (getcmditem("edd") != CMD_NOTFOUND ||
+ getcmditem("ebios") != CMD_NOTFOUND)
+ do_edd = 1;
+ else if (getcmditem("noedd") != CMD_NOTFOUND ||
+ getcmditem("noebios") != CMD_NOTFOUND ||
+ getcmditem("cbios") != CMD_NOTFOUND)
+ do_edd = 0;
+ else
+ do_edd = (geometry->driveno & 0x80) ? 1 : 0;
+
+ printf("Disk is %s %d, %u K, C/H/S = %u/%u/%u, EDD %s\n",
(geometry->driveno & 0x80) ? "hard disk" : "floppy",
geometry->driveno & 0x7f,
geometry->sectors >> 1,
- geometry->c, geometry->h, geometry->s);
+ geometry->c, geometry->h, geometry->s,
+ do_edd ? "on" : "off");
/* Reserve the ramdisk memory */
insertrange(ramdisk_image, ramdisk_size, 2);
@@ -633,6 +647,10 @@ void setup(syscall_t cs_syscall, void *cs_bounce)
pptr->configflags |= CONFIG_BIGRAW|CONFIG_RAW;
}
+ /* pptr->maxint13func defaults to EDD enabled, if compiled in */
+ if (!do_edd)
+ pptr->maxint13func = MAXINT13_NOEDD;
+
/* Set up a drive parameter table */
if ( geometry->driveno & 0x80 ) {
/* Hard disk */
diff --git a/menu/Makefile b/menu/Makefile
index 91a8697e..cee1c3af 100644
--- a/menu/Makefile
+++ b/menu/Makefile
@@ -17,7 +17,7 @@
gcc_ok = $(shell if gcc $(1) -c -x c /dev/null -o /dev/null 2>/dev/null; \
then echo $(1); else echo $(2); fi)
-M32 := $(call gcc_ok,-m32,)
+M32 := $(call gcc_ok,-m32,) $(call gcc_ok,-fno-stack-protector,)
CC = gcc
LD = ld -m elf_i386
diff --git a/mtools/Makefile b/mtools/Makefile
index 26909a30..546e3d14 100644
--- a/mtools/Makefile
+++ b/mtools/Makefile
@@ -1,8 +1,14 @@
+gcc_ok = $(shell if gcc $(1) ../dummy.c -o /dev/null 2>/dev/null; \
+ then echo '$(1)'; else echo '$(2)'; fi)
+
+comma := ,
+LDHASH := $(call gcc_ok,-Wl$(comma)--hash-style=both,)
+
CC = gcc
OPTFLAGS = -g -Os
INCLUDES = -I. -I.. -I../libfat
CFLAGS = -W -Wall -D_FILE_OFFSET_BITS=64 $(OPTFLAGS) $(INCLUDES)
-LDFLAGS = -s
+LDFLAGS = $(LDHASH) -s
SRCS = syslinux.c ../syslxmod.c ../bootsect_bin.c ../ldlinux_bin.c $(wildcard ../libfat/*.c)
OBJS = $(patsubst %.c,%.o,$(notdir $(SRCS)))
diff --git a/mtools/syslinux.c b/mtools/syslinux.c
index 29259dff..e65b081f 100644
--- a/mtools/syslinux.c
+++ b/mtools/syslinux.c
@@ -210,7 +210,7 @@ int main(int argc, char *argv[])
exit(1);
}
fprintf(mtc,
- "MTOOLS_NO_VFAT=1\n"
+ /* "MTOOLS_NO_VFAT=1\n" */
"MTOOLS_SKIP_CHECK=1\n" /* Needed for some flash memories */
"drive s:\n"
" file=\"/proc/%lu/fd/%d\"\n"
diff --git a/sample/Makefile b/sample/Makefile
index e24ab5be..bacc57ca 100644
--- a/sample/Makefile
+++ b/sample/Makefile
@@ -17,7 +17,7 @@
gcc_ok = $(shell if gcc $(1) -c -x c /dev/null -o /dev/null 2>/dev/null; \
then echo $(1); else echo $(2); fi)
-M32 := $(call gcc_ok,-m32,) $(call gcc_ok,-ffreestanding,)
+M32 := $(call gcc_ok,-m32,) $(call gcc_ok,-ffreestanding,) $(call gcc_ok,-fno-stack-protector,)
CC = gcc
LD = ld -m elf_i386
diff --git a/ui.inc b/ui.inc
index 5c1e7302..b5eed64a 100644
--- a/ui.inc
+++ b/ui.inc
@@ -324,10 +324,6 @@ vk_check:
; Find the kernel on disk
;
get_kernel: mov byte [KernelName+FILENAME_MAX],0 ; Zero-terminate filename/extension
-%if IS_SYSLINUX || IS_MDSLINUX ; SYSLINUX has to deal with DOS mangled names...
- mov eax,[KernelName+8] ; Save initial extension
- mov [exten_table_end],eax ; Last case == initial ext.
-%else
mov di,KernelName+4*IS_PXELINUX
xor al,al
mov cx,FILENAME_MAX-5 ; Need 4 chars + null
@@ -335,7 +331,6 @@ get_kernel: mov byte [KernelName+FILENAME_MAX],0 ; Zero-terminate filename/e
jne .no_skip
dec di ; Point to final null
.no_skip: mov [KernelExtPtr],di
-%endif
mov bx,exten_table
.search_loop: push bx
mov di,KernelName ; Search on disk
@@ -343,13 +338,9 @@ get_kernel: mov byte [KernelName+FILENAME_MAX],0 ; Zero-terminate filename/e
pop bx
jnz kernel_good
mov eax,[bx] ; Try a different extension
-%if IS_SYSLINUX || IS_MDSLINUX
- mov [KernelName+8],eax
-%else
mov si,[KernelExtPtr]
mov [si],eax
mov byte [si+4],0
-%endif
add bx,byte 4
cmp bx,exten_table_end
jna .search_loop ; allow == case (final case)
@@ -493,10 +484,6 @@ kernel_good:
mov [KernelCNameLen],di
popa
-%if IS_SYSLINUX || IS_MDSLINUX
- mov ecx,[KernelName+7]
- mov cl,'.'
-%else
push di
push ax
mov di,KernelName+4*IS_PXELINUX
@@ -508,7 +495,6 @@ kernel_good:
.one_step: mov ecx,[di-4] ; 4 bytes before end
pop ax
pop di
-%endif
;
; At this point, DX:AX contains the size of the kernel, SI contains
@@ -535,19 +521,13 @@ is_unknown_filetype:
je is_bss_sector
cmp ecx,'.bin'
je is_bootsector
-%if IS_SYSLINUX || IS_MDSLINUX
- cmp ecx,'.bs '
- je is_bootsector
- cmp ecx,'.0 '
- je is_bootsector
-%else
shr ecx,8
cmp ecx,'.bs'
je is_bootsector
shr ecx,8
cmp cx,'.0'
je is_bootsector
-%endif
+
; Otherwise Linux kernel
jmp is_linux_kernel
diff --git a/unix/Makefile b/unix/Makefile
index 5dfc0513..f0ab279a 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -1,10 +1,16 @@
+gcc_ok = $(shell if gcc $(1) ../dummy.c -o /dev/null 2>/dev/null; \
+ then echo '$(1)'; else echo '$(2)'; fi)
+
+comma := ,
+LDHASH := $(call gcc_ok,-Wl$(comma)--hash-style=both,)
+
CC = gcc
OPTFLAGS = -g -Os
-INCLUDES = -I. -I.. -I../libfat
+INCLUDES = -I. -I..
CFLAGS = -W -Wall -D_FILE_OFFSET_BITS=64 $(OPTFLAGS) $(INCLUDES)
-LDFLAGS = -s
+LDFLAGS = $(LDHASH) -s
-SRCS = syslinux.c ../syslxmod.c ../bootsect_bin.c ../ldlinux_bin.c $(wildcard ../libfat/*.c)
+SRCS = syslinux.c ../syslxmod.c ../bootsect_bin.c ../ldlinux_bin.c
OBJS = $(patsubst %.c,%.o,$(notdir $(SRCS)))
.SUFFIXES: .c .o .i .s .S
diff --git a/unix/syslinux.c b/unix/syslinux.c
index 36826a1b..4270d728 100644
--- a/unix/syslinux.c
+++ b/unix/syslinux.c
@@ -13,7 +13,7 @@
/*
* syslinux.c - Linux installer program for SYSLINUX
*
- * This program ought to be portable. I hope so, at least.
+ * This is Linux-specific by now.
*
* This is an alternate version of the installer which doesn't require
* mtools, but requires root privilege.
@@ -46,23 +46,28 @@
#include <sys/wait.h>
#include <sys/mount.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h> /* FIGETBSZ, FIBMAP */
+#include <linux/msdos_fs.h> /* FAT_IOCTL_SET_ATTRIBUTES, SECTOR_* */
+#ifndef FAT_IOCTL_SET_ATTRIBUTES
+# define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, uint32_t)
+#endif
+
+#include <paths.h>
+#ifndef _PATH_MOUNT
+# define _PATH_MOUNT "/bin/mount"
+#endif
+#ifndef _PATH_UMOUNT
+# define _PATH_UMOUNT "/bin/umount"
+#endif
+#ifndef _PATH_TMP
+# define _PATH_TMP "/tmp/"
+#endif
+
#include "syslinux.h"
-#include "libfat.h"
#if DO_DIRECT_MOUNT
-
# include <linux/loop.h>
-
-#else
-
-# include <paths.h>
-# ifndef _PATH_MOUNT
-# define _PATH_MOUNT "/bin/mount"
-# endif
-# ifndef _PATH_UMOUNT
-# define _PATH_UMOUNT "/bin/umount"
-# endif
-
#endif
const char *program; /* Name of program */
@@ -156,35 +161,175 @@ ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset)
}
/*
- * Version of the read function suitable for libfat
+ * Create a block map for ldlinux.sys
+ */
+int make_block_map(uint32_t *sectors, int len, int dev_fd, int fd)
+{
+ int nsectors = 0;
+ int blocksize, nblock, block;
+ int i;
+
+ (void)dev_fd;
+
+ if (ioctl(fd, FIGETBSZ, &blocksize) < 0)
+ die("ioctl FIGETBSZ failed");
+
+ blocksize >>= SECTOR_BITS; /* sectors/block */
+
+ nblock = 0;
+ while (len > 0) {
+ block = nblock++;
+ if (ioctl(fd, FIBMAP, &block) < 0)
+ die("ioctl FIBMAP failed");
+
+ for (i = 0; i < blocksize; i++) {
+ if (len <= 0)
+ break;
+
+ *sectors++ = (block*blocksize)+i;
+ nsectors++;
+ len -= (1 << SECTOR_BITS);
+ }
+ }
+
+ return nsectors;
+}
+
+/*
+ * Mount routine
+ */
+int do_mount(int dev_fd, int *cookie, const char *mntpath, const char *fstype)
+{
+ struct stat st;
+
+ (void)cookie;
+
+ if (fstat(dev_fd, &st) < 0)
+ return errno;
+
+#if DO_DIRECT_MOUNT
+ {
+ if ( !S_ISBLK(st.st_mode) ) {
+ /* It's file, need to mount it loopback */
+ unsigned int n = 0;
+ struct loop_info64 loopinfo;
+ int loop_fd;
+
+ for ( n = 0 ; loop_fd < 0 ; n++ ) {
+ snprintf(devfdname, sizeof devfdname, "/dev/loop%u", n);
+ loop_fd = open(devfdname, O_RDWR);
+ if ( loop_fd < 0 && errno == ENOENT ) {
+ die("no available loopback device!");
+ }
+ if ( ioctl(loop_fd, LOOP_SET_FD, (void *)dev_fd) ) {
+ close(loop_fd); loop_fd = -1;
+ if ( errno != EBUSY )
+ die("cannot set up loopback device");
+ else
+ continue;
+ }
+
+ if ( ioctl(loop_fd, LOOP_GET_STATUS64, &loopinfo) ||
+ (loopinfo.lo_offset = filesystem_offset,
+ ioctl(loop_fd, LOOP_SET_STATUS64, &loopinfo)) )
+ die("cannot set up loopback device");
+ }
+
+ *cookie = loop_fd;
+ } else {
+ snprintf(devfdname, sizeof devfdname, "/proc/%lu/fd/%d",
+ (unsigned long)mypid, dev_fd);
+ *cookie = -1;
+ }
+
+ return mount(devfdname, mntpath, fstype,
+ MS_NOEXEC|MS_NOSUID, "umask=077,quiet");
+ }
+#else
+ {
+ char devfdname[128], mnt_opts[128];
+ pid_t f, w;
+ int status;
+
+ snprintf(devfdname, sizeof devfdname, "/proc/%lu/fd/%d",
+ (unsigned long)mypid, dev_fd);
+
+ f = fork();
+ if ( f < 0 ) {
+ return -1;
+ } else if ( f == 0 ) {
+ if ( !S_ISBLK(st.st_mode) ) {
+ snprintf(mnt_opts, sizeof mnt_opts,
+ "rw,nodev,noexec,loop,offset=%llu,umask=077,quiet",
+ (unsigned long long)filesystem_offset);
+ } else {
+ snprintf(mnt_opts, sizeof mnt_opts, "rw,nodev,noexec,umask=077,quiet");
+ }
+ execl(_PATH_MOUNT, _PATH_MOUNT, "-t", fstype, "-o", mnt_opts, \
+ devfdname, mntpath, NULL);
+ _exit(255); /* execl failed */
+ }
+
+ w = waitpid(f, &status, 0);
+ return ( w != f || status ) ? -1 : 0;
+ }
+#endif
+}
+
+/*
+ * umount routine
*/
-int libfat_xpread(intptr_t pp, void *buf, size_t secsize, libfat_sector_t sector)
+void do_umount(const char *mntpath, int cookie)
{
- off_t offset = (off_t)sector * secsize + filesystem_offset;
- return xpread(pp, buf, secsize, offset);
+#if DO_DIRECT_MOUNT
+ int loop_fd = cookie;
+
+ if ( umount2(mntpath, 0) )
+ die("could not umount path");
+
+ if ( loop_fd != -1 ) {
+ ioctl(loop_fd, LOOP_CLR_FD, 0); /* Free loop device */
+ close(loop_fd);
+ loop_fd = -1;
+ }
+
+#else
+ pid_t f = fork();
+ pid_t w;
+ int status;
+ (void)cookie;
+
+ if ( f < 0 ) {
+ perror("fork");
+ exit(1);
+ } else if ( f == 0 ) {
+ execl(_PATH_UMOUNT, _PATH_UMOUNT, mntpath, NULL);
+ }
+
+ w = waitpid(f, &status, 0);
+ if ( w != f || status ) {
+ exit(1);
+ }
+#endif
}
int main(int argc, char *argv[])
{
- static unsigned char sectbuf[512];
+ static unsigned char sectbuf[SECTOR_SIZE];
unsigned char *dp;
const unsigned char *cdp;
int dev_fd, fd;
struct stat st;
int nb, left;
int err = 0;
- pid_t f, w;
- int status;
- char mntname[64], devfdname[64];
+ char mntname[128];
char *ldlinux_name, **argp, *opt;
int force = 0; /* -f (force) option */
const char *subdir = NULL;
- struct libfat_filesystem *fs;
- struct libfat_direntry dentry;
- libfat_sector_t s, *secp, sectors[65]; /* 65 is maximum possible */
- int32_t ldlinux_cluster;
+ uint32_t sectors[65]; /* 65 is maximum possible */
int nsectors = 0;
const char *errmsg;
+ int mnt_cookie;
(void)argc; /* Unused */
@@ -209,7 +354,8 @@ int main(int argc, char *argv[])
} else if ( *opt == 'd' && argp[1] ) {
subdir = *++argp;
} else if ( *opt == 'o' && argp[1] ) {
- filesystem_offset = (off_t)strtoull(*++argp, NULL, 0); /* Byte offset */
+ /* Byte offset */
+ filesystem_offset = (off_t)strtoull(*++argp, NULL, 0);
} else {
usage();
}
@@ -235,15 +381,15 @@ int main(int argc, char *argv[])
exit(1);
}
- if ( !force && !S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode) ) {
- die("not a block device or regular file (use -f to override)");
+ if ( !S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode) ) {
+ die("not a device or regular file");
}
- if ( !force && filesystem_offset && !S_ISREG(st.st_mode) ) {
- die("not a regular file and an offset specified (use -f to override)");
+ if ( filesystem_offset && S_ISBLK(st.st_mode) ) {
+ die("can't combine an offset with a block device");
}
- xpread(dev_fd, sectbuf, 512, filesystem_offset);
+ xpread(dev_fd, sectbuf, SECTOR_SIZE, filesystem_offset);
fsync(dev_fd);
/*
@@ -267,7 +413,7 @@ int main(int argc, char *argv[])
/* We're root or at least setuid.
Make a temp dir and pass all the gunky options to mount. */
- if ( chdir("/tmp") ) {
+ if ( chdir(_PATH_TMP) ) {
perror(program);
exit(1);
}
@@ -276,7 +422,7 @@ int main(int argc, char *argv[])
if ( stat(".", &dst) || !S_ISDIR(dst.st_mode) ||
(dst.st_mode & TMP_MODE) != TMP_MODE ) {
- die("possibly unsafe /tmp permissions");
+ die("possibly unsafe " _PATH_TMP " permissions");
}
for ( i = 0 ; ; i++ ) {
@@ -303,80 +449,29 @@ int main(int argc, char *argv[])
}
mntpath = mntname;
+ }
-#if DO_DIRECT_MOUNT
- if ( S_ISREG(st.st_mode) ) {
- /* It's file, need to mount it loopback */
- unsigned int n = 0;
- struct loop_info64 loopinfo;
-
- for ( n = 0 ; loop_fd < 0 ; n++ ) {
- snprintf(devfdname, sizeof devfdname, "/dev/loop%u", n);
- loop_fd = open(devfdname, O_RDWR);
- if ( loop_fd < 0 && errno == ENOENT ) {
- die("no available loopback device!");
- }
- if ( ioctl(loop_fd, LOOP_SET_FD, (void *)dev_fd) ) {
- close(loop_fd); loop_fd = -1;
- if ( errno != EBUSY )
- die("cannot set up loopback device");
- else
- continue;
- }
-
- if ( ioctl(loop_fd, LOOP_GET_STATUS64, &loopinfo) ||
- (loopinfo.lo_offset = filesystem_offset,
- ioctl(loop_fd, LOOP_SET_STATUS64, &loopinfo)) )
- die("cannot set up loopback device");
- }
- } else {
- snprintf(devfdname, sizeof devfdname, "/proc/%lu/fd/%d",
- (unsigned long)mypid, dev_fd);
- }
-
- if ( mount(devfdname, mntpath, "msdos",
- MS_NOEXEC|MS_NOSUID, "umask=077,quiet") )
- die("could not mount filesystem");
-
-#else
-
- snprintf(devfdname, sizeof devfdname, "/proc/%lu/fd/%d",
- (unsigned long)mypid, dev_fd);
-
- f = fork();
- if ( f < 0 ) {
- perror(program);
- rmdir(mntpath);
- exit(1);
- } else if ( f == 0 ) {
- char mnt_opts[128];
- if ( S_ISREG(st.st_mode) ) {
- snprintf(mnt_opts, sizeof mnt_opts, "rw,nodev,noexec,loop,offset=%llu,umask=077,quiet",
- (unsigned long long)filesystem_offset);
- } else {
- snprintf(mnt_opts, sizeof mnt_opts, "rw,nodev,noexec,umask=077,quiet");
- }
- execl(_PATH_MOUNT, _PATH_MOUNT, "-t", "msdos", "-o", mnt_opts,\
- devfdname, mntpath, NULL);
- _exit(255); /* execl failed */
- }
-
- w = waitpid(f, &status, 0);
- if ( w != f || status ) {
- rmdir(mntpath);
- exit(1); /* Mount failed */
- }
-
-#endif
+ if (do_mount(dev_fd, &mnt_cookie, mntpath, "vfat") &&
+ do_mount(dev_fd, &mnt_cookie, mntpath, "msdos")) {
+ rmdir(mntpath);
+ die("mount failed");
}
- ldlinux_name = alloca(strlen(mntpath)+14);
+ ldlinux_name = alloca(strlen(mntpath)+14+
+ (subdir ? strlen(subdir)+2 : 0));
if ( !ldlinux_name ) {
perror(program);
err = 1;
goto umount;
}
- sprintf(ldlinux_name, "%s//ldlinux.sys", mntpath);
+ sprintf(ldlinux_name, "%s%s%s//ldlinux.sys",
+ mntpath, subdir ? "//" : "", subdir ? subdir : "");
+
+ if ((fd = open(ldlinux_name, O_RDONLY)) >= 0) {
+ uint32_t zero_attr = 0;
+ ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &zero_attr);
+ close(fd);
+ }
unlink(ldlinux_name);
fd = open(ldlinux_name, O_WRONLY|O_CREAT|O_TRUNC, 0444);
@@ -402,81 +497,25 @@ int main(int argc, char *argv[])
left -= nb;
}
+ fsync(fd);
/*
- * I don't understand why I need this. Does the DOS filesystems
- * not honour the mode passed to open()?
+ * Set the attributes
*/
- fchmod(fd, 0400);
-
- close(fd);
-
- sync();
+ {
+ uint32_t attr = 0x07; /* Hidden+System+Readonly */
+ ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
+ }
/*
- * Now, use libfat to create a block map. This probably
- * should be changed to use ioctl(...,FIBMAP,...) since
- * this is supposed to be a simple, privileged version
- * of the installer.
+ * Create a block map.
*/
- fs = libfat_open(libfat_xpread, dev_fd);
- ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", &dentry);
- secp = sectors;
- nsectors = 0;
- s = libfat_clustertosector(fs, ldlinux_cluster);
- while ( s && nsectors < 65 ) {
- *secp++ = s;
- nsectors++;
- s = libfat_nextsector(fs, s);
- }
- libfat_close(fs);
-
- /* Move ldlinux.sys to the desired location */
- if (subdir) {
- char *new_ldlinux_name = alloca(strlen(mntpath)+
- strlen(subdir)+15);
- int mov_err = 1;
+ nsectors = make_block_map(sectors, syslinux_ldlinux_len, dev_fd, fd);
- if ( new_ldlinux_name ) {
- sprintf(new_ldlinux_name, "%s//%s//ldlinux.sys", mntpath, subdir);
-
- if (!rename(ldlinux_name, new_ldlinux_name))
- mov_err = 0;
- }
-
- if (mov_err)
- fprintf(stderr, "%s: warning: unable to move ldlinux.sys: %s\n",
- device, strerror(errno));
- }
+ close(fd);
+ sync();
umount:
-#if DO_DIRECT_MOUNT
-
- if ( umount2(mntpath, 0) )
- die("could not umount path");
-
- if ( loop_fd != -1 ) {
- ioctl(loop_fd, LOOP_CLR_FD, 0); /* Free loop device */
- close(loop_fd);
- loop_fd = -1;
- }
-
-#else
-
- f = fork();
- if ( f < 0 ) {
- perror("fork");
- exit(1);
- } else if ( f == 0 ) {
- execl(_PATH_UMOUNT, _PATH_UMOUNT, mntpath, NULL);
- }
-
- w = waitpid(f, &status, 0);
- if ( w != f || status ) {
- exit(1);
- }
-
-#endif
-
+ do_umount(mntpath, mnt_cookie);
sync();
rmdir(mntpath);
@@ -491,29 +530,21 @@ umount:
/*
* Write the now-patched first sector of ldlinux.sys
*/
- xpwrite(dev_fd, syslinux_ldlinux, 512, filesystem_offset + ((off_t)sectors[0] << 9));
-
- /*
- * Patch the root directory to set attributes to
- * HIDDEN|SYSTEM|READONLY
- */
- {
- const unsigned char attrib = 0x07;
- xpwrite(dev_fd, &attrib, 1, ((off_t)dentry.sector << 9)+dentry.offset+11);
- }
+ xpwrite(dev_fd, syslinux_ldlinux, SECTOR_SIZE,
+ filesystem_offset+((off_t)sectors[0] << SECTOR_BITS));
/*
* To finish up, write the boot sector
*/
/* Read the superblock again since it might have changed while mounted */
- xpread(dev_fd, sectbuf, 512, filesystem_offset);
+ xpread(dev_fd, sectbuf, SECTOR_SIZE, filesystem_offset);
/* Copy the syslinux code into the boot sector */
syslinux_make_bootsect(sectbuf);
/* Write new boot sector */
- xpwrite(dev_fd, sectbuf, 512, filesystem_offset);
+ xpwrite(dev_fd, sectbuf, SECTOR_SIZE, filesystem_offset);
close(dev_fd);
sync();