summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-08-12 20:48:33 -0700
committerH. Peter Anvin <hpa@zytor.com>2010-08-12 20:52:53 -0700
commita104d9a4fd0762b4167668bb43eaeef10469ee9c (patch)
tree397f11badacb1c864e689a0aaaba17e051cff171
parent0fb20934d2145e43f08650dbbf6613f24f2df8c6 (diff)
parentf3ab4925bd8c5c42cf17a34377f82b53b48b132e (diff)
downloadsyslinux-a104d9a4fd0762b4167668bb43eaeef10469ee9c.tar.gz
Merge branch 'master' into elflink-merge
Resolved Conflicts: core/diskfs.inc core/mem/free.c Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--Makefile11
-rw-r--r--NEWS14
-rw-r--r--README4
-rw-r--r--com32/cmenu/libmenu/menu.c2
-rw-r--r--com32/lua/doc/syslinux.asc9
-rw-r--r--com32/lua/src/dmi.c2
-rw-r--r--com32/lua/src/syslinux.c41
-rw-r--r--com32/lua/test/syslinux-derivative.lua38
-rw-r--r--com32/modules/chain.c32
-rw-r--r--com32/modules/ifplop.c19
-rw-r--r--com32/modules/whichsys.c4
-rw-r--r--core/diskfs.inc2
-rw-r--r--core/diskstart.inc15
-rw-r--r--core/extern.inc2
-rw-r--r--core/fs/diskio.c136
-rw-r--r--core/fs/fs.c4
-rw-r--r--core/fs/loadhigh.c9
-rw-r--r--core/fs/pxe/pxe.c2
-rw-r--r--core/include/core.h13
-rw-r--r--core/include/disk.h15
-rw-r--r--core/include/fs.h2
-rw-r--r--core/isolinux.asm3
-rw-r--r--core/mem/free.c2
-rw-r--r--core/pxelinux.asm11
-rw-r--r--dos/Makefile16
-rw-r--r--dos/ctype.h3
-rw-r--r--dos/dosexe.ld10
-rw-r--r--dos/getsetsl.c19
-rw-r--r--dos/int2526.S2
-rw-r--r--dos/ldlinux.S19
-rw-r--r--dos/stdio.h2
-rw-r--r--dos/stdlib.h3
-rw-r--r--dos/strchr.c17
-rw-r--r--dos/string.h2
-rw-r--r--dos/strntoumax.c73
-rw-r--r--dos/strtoul.c15
-rw-r--r--dos/sysexits.h1
-rw-r--r--dos/syslinux.c160
-rwxr-xr-x[-rw-r--r--]extlinux/main.c2
-rw-r--r--libinstaller/getopt/getopt.h25
-rw-r--r--libinstaller/getopt/getopt_long.c152
-rw-r--r--libinstaller/syslxint.h6
-rw-r--r--libinstaller/syslxopt.c58
-rw-r--r--libinstaller/syslxopt.h5
-rwxr-xr-x[-rw-r--r--]linux/syslinux.c2
-rw-r--r--man/syslinux.168
-rwxr-xr-x[-rw-r--r--]mtools/Makefile1
-rwxr-xr-x[-rw-r--r--]mtools/syslinux.c89
-rw-r--r--sample/Makefile35
-rw-r--r--sample/README6
-rw-r--r--sample/atou.c12
-rw-r--r--sample/c32echo.c47
-rw-r--r--sample/c32entry.S66
-rw-r--r--sample/c32exit.S10
-rw-r--r--sample/comecho.asm32
-rw-r--r--sample/conio.c59
-rw-r--r--sample/fd.c59
-rw-r--r--sample/filetest.c97
-rw-r--r--sample/hello.c43
-rw-r--r--sample/hello2.c58
-rw-r--r--sample/printf.c316
-rw-r--r--sample/skipatou.c13
-rw-r--r--version2
-rw-r--r--win/hello.c (renamed from win32/hello.c)0
-rw-r--r--win/sysexits.h1
-rw-r--r--win/syslinux.c (renamed from win32/syslinux.c)117
-rw-r--r--win32/Makefile17
-rw-r--r--win32/README6
-rwxr-xr-xwin32/find-mingw32.sh (renamed from win32/find-mingw.sh)1
-rw-r--r--win64/Makefile92
-rw-r--r--win64/README10
-rwxr-xr-xwin64/find-mingw64.sh24
72 files changed, 999 insertions, 1266 deletions
diff --git a/Makefile b/Makefile
index 9b40e368..da90cdc4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
## -----------------------------------------------------------------------
##
## Copyright 1998-2009 H. Peter Anvin - All Rights Reserved
-## Copyright 2009 Intel Corporation; author: H. Peter Anvin
+## Copyright 2009-2010 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
@@ -43,7 +43,8 @@ BOBJECTS = $(BTARGET) \
mbr/mbr_c.bin mbr/altmbr_c.bin mbr/gptmbr_c.bin \
mbr/mbr_f.bin mbr/altmbr_f.bin mbr/gptmbr_f.bin \
core/pxelinux.0 core/isolinux.bin core/isolinux-debug.bin \
- gpxe/gpxelinux.0 dos/syslinux.com win32/syslinux.exe \
+ gpxe/gpxelinux.0 dos/syslinux.com \
+ win32/syslinux.exe win64/syslinux64.exe \
dosutil/*.com dosutil/*.sys \
$(MODULES)
@@ -54,7 +55,7 @@ BOBJECTS = $(BTARGET) \
# files that depend only on the B phase, but may have to be regenerated
# for "make installer".
BSUBDIRS = codepage com32 lzo core memdisk modules mbr memdump gpxe sample \
- libinstaller dos win32 dosutil
+ libinstaller dos win32 win64 dosutil
ITARGET =
IOBJECTS = $(ITARGET) \
utils/gethostip utils/isohybrid utils/mkdiskimage \
@@ -68,9 +69,9 @@ INSTALL_SBIN = extlinux/extlinux
# Things to install in /usr/lib/syslinux
INSTALL_AUX = core/pxelinux.0 gpxe/gpxelinux.0 core/isolinux.bin \
core/isolinux-debug.bin \
- dos/syslinux.com win32/syslinux.exe \
+ dos/syslinux.com \
mbr/*.bin $(MODULES)
-INSTALL_AUX_OPT = win32/syslinux.exe
+INSTALL_AUX_OPT = win32/syslinux.exe win64/syslinux64.exe
# These directories manage their own installables
INSTALLSUBDIRS = com32 utils dosutil
diff --git a/NEWS b/NEWS
index c2c7c210..8ecb6cd9 100644
--- a/NEWS
+++ b/NEWS
@@ -16,12 +16,19 @@ Changes in 4.02:
* whichsys.c32: execute specific command, based on Syslinux
bootloader variant (Gert Hulselmans).
* lua.c32: a lot of new bindings added to the "syslinux"
- namespace (Marcel Ritter, Gert Hulselmans).
+ namespace: VESA, PCI, DMI, kernel loading (Marcel Ritter).
* btrfs: print a comprehensive error message if compressed or
encrypted files are encountered (neither is currently
supported.)
* SYSLINUX: mtools installer: honor TMPDIR, error out on disk
full.
+ * Handle fallbacks from EDD to CHS, to deal with systems which
+ announce EDD support but don't actually have it.
+ * SYSLINUX: the mtools, DOS and win32 installers now use the new
+ command line options.
+ * PXELINUX: fix the use of IP addresses in TFTP :: or tftp://
+ host syntax.
+ * SYSLINUX: experimental Win64 installer (syslinux64.exe).
Changes in 4.01:
* ISOLINUX: fix initialization on systems which don't zero
@@ -35,7 +42,8 @@ Changes in 4.01:
already has booted a CDROM or USB drive (Gert Hulselmans).
* Correct a severe memory overwrite bug, triggered primarily
when selecting a very long command line in the menu system.
- * lua.c32: Lua script interpreter, currently experimental.
+ * lua.c32: Lua script interpreter, currently experimental
+ (Alexey Zaytsev, Marcel Ritter, Geert Stappers).
* PXELINUX: new option IPAPPEND 4 to append the system UUID to
the kernel command line.
* PXELINUX: display BOOTIF and SYSUUID at startup time, and
@@ -97,6 +105,8 @@ Changes in 4.00:
instead of downwards, in order to avoid a fairly common
bug on some BIOSes where probing drive 0xFF causes a
failure.
+ * NASM 2.03 or later required to build. 2.07 or later
+ recommended.
Changes in 3.86:
* chain.c32: fix chainloading the MBR of a hard disk (broken
diff --git a/README b/README
index aebc421c..ff905aa8 100644
--- a/README
+++ b/README
@@ -17,8 +17,8 @@ Also see the files:
COPYING - For the license terms of this software.
SYSLINUX now builds in a Linux environment, using nasm. You need nasm
-version 0.98.39 or later to build SYSLINUX from source. See
-http://nasm.sf.net/ for information about nasm.
+version 2.03 or later (2.07 or later recommended) to build SYSLINUX
+from source. See http://www.nasm.us/ for information about nasm.
There is now a mailing list for SYSLINUX. See the end of syslinux.txt
for details.
diff --git a/com32/cmenu/libmenu/menu.c b/com32/cmenu/libmenu/menu.c
index 13754768..19a7e598 100644
--- a/com32/cmenu/libmenu/menu.c
+++ b/com32/cmenu/libmenu/menu.c
@@ -655,9 +655,9 @@ pt_menuitem showmenus(uchar startmenu)
ms->menus[(unsigned int)startmenu], 0, NORMALMENU);
// Hide the garbage we left on the screen
- cursoron();
cls();
gotoxy(ms->minrow, ms->mincol);
+ cursoron();
// Return user choice
return rv;
diff --git a/com32/lua/doc/syslinux.asc b/com32/lua/doc/syslinux.asc
index eb8ca7f1..64dc18c5 100644
--- a/com32/lua/doc/syslinux.asc
+++ b/com32/lua/doc/syslinux.asc
@@ -23,6 +23,15 @@ Modules
SYSLINUX
~~~~~~~~
+.syslinux.version()
+
+Returns version string
+
+.syslinux.derivative()
+
+Returns running Syslinux's derivative (ISOLINUX, PXELINUX or SYSLINUX).
+See com32/lua/test/syslinux-derivative.lua for an example.
+
.syslinux.sleep(s)
Sleep for +s+ seconds
diff --git a/com32/lua/src/dmi.c b/com32/lua/src/dmi.c
index 0c89ea9a..d0305333 100644
--- a/com32/lua/src/dmi.c
+++ b/com32/lua/src/dmi.c
@@ -15,7 +15,6 @@ static int dmi_gettable(lua_State *L)
lua_newtable(L);
- /* FIXME initalize *dmi */
if ( ! dmi_iterate(&dmi) ) {
printf("No DMI Structure found\n");
return -1;
@@ -279,7 +278,6 @@ static int dmi_supported(lua_State *L)
{
s_dmi dmi;
- /* FIXME initalize *dmi */
if ( dmi_iterate(&dmi) ) {
lua_pushboolean(L, 1);
} else {
diff --git a/com32/lua/src/syslinux.c b/com32/lua/src/syslinux.c
index cf0189f9..fa54d7f1 100644
--- a/com32/lua/src/syslinux.c
+++ b/com32/lua/src/syslinux.c
@@ -38,7 +38,7 @@
#include "syslinux/boot.h"
#include "syslinux/loadfile.h"
#include "syslinux/linux.h"
-#include "../../cmenu/libmenu/com32io.h"
+#include "syslinux/config.h"
int __parse_argv(char ***argv, const char *str);
@@ -387,7 +387,7 @@ static int sl_initramfs_add_file(lua_State * L)
if (initramfs_add_file(initramfs, file_data, file_len, file_len,
"/testfile1", 0, 0755))
- return 0;
+ return 0;
}
static int sl_boot_it(lua_State * L)
@@ -404,6 +404,41 @@ static int sl_boot_it(lua_State * L)
return 0;
}
+static int sl_derivative(lua_State * L)
+{
+ const struct syslinux_version *sv;
+
+ sv = syslinux_version();
+
+ switch (sv->filesystem) {
+ case SYSLINUX_FS_SYSLINUX:
+ lua_pushstring(L, "SYSLINUX");
+ break;
+ case SYSLINUX_FS_PXELINUX:
+ lua_pushstring(L, "PXELINUX");
+ break;
+ case SYSLINUX_FS_ISOLINUX:
+ lua_pushstring(L, "ISOLINUX");
+ break;
+ case SYSLINUX_FS_UNKNOWN:
+ default:
+ lua_pushstring(L, "Unknown Syslinux derivative");
+ break;
+ }
+
+ return 1;
+}
+
+static int sl_version(lua_State * L)
+{
+ const struct syslinux_version *sv;
+
+ sv = syslinux_version();
+ lua_pushstring(L, sv->version_string);
+
+ return 1;
+}
+
static const luaL_reg syslinuxlib[] = {
{"run_command", sl_run_command},
{"run_default", sl_run_default},
@@ -420,6 +455,8 @@ static const luaL_reg syslinuxlib[] = {
{"initramfs_load_archive", sl_initramfs_load_archive},
{"initramfs_add_file", sl_initramfs_add_file},
{"boot_it", sl_boot_it},
+ {"derivative", sl_derivative},
+ {"version", sl_version},
{NULL, NULL}
};
diff --git a/com32/lua/test/syslinux-derivative.lua b/com32/lua/test/syslinux-derivative.lua
new file mode 100644
index 00000000..fbdf5d57
--- /dev/null
+++ b/com32/lua/test/syslinux-derivative.lua
@@ -0,0 +1,38 @@
+-- get nice output
+printf = function(s,...)
+ return io.write(s:format(...))
+ end
+
+-- get syslinux derivative (ISOLINUX, PXELINUX, SYSLINUX)
+derivative = syslinux.derivative()
+
+printf("Run specific command depending on the Syslinux derivate:\n")
+printf("--------------------------------------------------------\n\n")
+printf(" Detected Syslinux derivative: %s\n", derivative)
+
+if derivative == "SYSLINUX" then
+ -- swap internal (hd1) hard drive with USB stick (hd0)
+ commandline = 'chain.c32 hd1 swap'
+elseif derivative == "ISOLINUX" then
+ -- boot first hard drive
+ commandline = 'chain.c32 hd0'
+elseif derivative == "PXELINUX" then
+ -- boot first hard drive
+ commandline = 'chain.c32 hd0'
+else
+ printf("Do nothing\n")
+ return 1
+end
+
+printf("\n commandline for derivative: %s\n\n", commandline)
+
+
+-- Count down from 7
+for time = 7, 1, -1 do
+ printf(" Boot in %d second(s)... \r", time)
+ syslinux.sleep(1)
+end
+
+-- Boot
+syslinux.run_command(commandline)
+
diff --git a/com32/modules/chain.c b/com32/modules/chain.c
index 48a83d2a..6a5b1151 100644
--- a/com32/modules/chain.c
+++ b/com32/modules/chain.c
@@ -133,6 +133,7 @@ static struct options {
bool swap;
bool hide;
bool sethidden;
+ bool drmk;
} opt;
struct data_area {
@@ -624,8 +625,8 @@ static struct disk_part_iter *next_mbr_part(struct disk_part_iter *part)
/* Update parameters to reflect this new partition. Re-use iterator */
part->lba_data = table[part->private.mbr_index].start_lba;
- dprintf("Partition %d primary lba %u\n", part->index, part->lba_data);
- part->index++;
+ dprintf("Partition %d primary lba %u\n", part->private.mbr_index, part->lba_data);
+ part->index = part->private.mbr_index + 1;
part->record = table + part->private.mbr_index;
return part;
@@ -869,7 +870,7 @@ static struct disk_part_iter *next_gpt_part(struct disk_part_iter *part)
part->private.gpt.part_guid = &gpt_part->uid;
part->private.gpt.part_label = gpt_part->name;
/* Update our index */
- part->index++;
+ part->index = part->private.gpt.index + 1;
gpt_part_dump(gpt_part);
/* In a GPT scheme, we re-use the iterator */
@@ -1281,6 +1282,7 @@ Options: file=<loader> Load and execute file, instead of boot sector\n\
freedos=<loader> Load FreeDOS KERNEL.SYS\n\
msdos=<loader> Load MS-DOS IO.SYS\n\
pcdos=<loader> Load PC-DOS IBMBIO.COM\n\
+ drmk=<loader> Load DRMK DELLBIO.BIN\n\
grub=<loader> Load GRUB Legacy stage2\n\
grubcfg=<filename> Set alternative config filename for GRUB Legacy\n\
grldr=<loader> Load GRUB4DOS grldr\n\
@@ -1351,6 +1353,11 @@ int main(int argc, char *argv[])
opt.seg = 0x70; /* MS-DOS 2.0+ wants this address */
opt.loadfile = argv[i] + 6;
opt.sethidden = true;
+ } else if (!strncmp(argv[i], "drmk=", 5)) {
+ opt.seg = 0x70; /* DRMK wants this address */
+ opt.loadfile = argv[i] + 5;
+ opt.sethidden = true;
+ opt.drmk = true;
} else if (!strncmp(argv[i], "grub=", 5)) {
opt.seg = 0x800; /* stage2 wants this address */
opt.loadfile = argv[i] + 5;
@@ -1697,6 +1704,25 @@ int main(int argc, char *argv[])
}
}
+ if (opt.drmk) {
+ /* DRMK entry is different than MS-DOS/PC-DOS */
+ /*
+ * A new size, aligned to 16 bytes to ease use of ds:[bp+28].
+ * We only really need 4 new, usable bytes at the end.
+ */
+ int tsize = (data[ndata].size + 19) & 0xfffffff0;
+ regs.ss = regs.fs = regs.gs = 0; /* Used before initialized */
+ if (!realloc(data[ndata].data, tsize)) {
+ error("Failed to realloc for DRMK\n");
+ goto bail;
+ }
+ data[ndata].size = tsize;
+ /* ds:[bp+28] must be 0x0000003f */
+ regs.ds = (tsize >> 4) + (opt.seg - 2);
+ /* "Patch" into tail of the new space */
+ *(int *)(data[ndata].data + tsize - 4) = 0x0000003f;
+ }
+
ndata++;
}
diff --git a/com32/modules/ifplop.c b/com32/modules/ifplop.c
index c6286d9e..a846df8d 100644
--- a/com32/modules/ifplop.c
+++ b/com32/modules/ifplop.c
@@ -16,8 +16,11 @@
* This COM32 module detects if the PLoP Boot Manager was used to boot a CDROM
* drive or USB drive, by checking for the presence of the PLoP INT13h hook.
*
- * Usage: ifplop.c32 [<plop_detected>] -- [<plop_not_detected>]
- * Example: ifplop.c32 menu.c32 another.cfg -- plpbt.bin hiddenusb usb1=2
+ * Usage: ifplop.c32 [<plop_detected>] -- [<plop_not_detected>]
+ * Examples: ifplop.c32 menu.c32 another.cfg -- plpbt hiddenusb usb1=2
+ * You need to remove the ".bin" extension of the plpbt.bin file
+ * if you use it this way.
+ * ifplop.c32 plop_detected -- plop_not_detected
*
* A possible config file could be:
*
@@ -40,8 +43,10 @@
* APPEND another.cfg
*
* # PLoP INT13h hook wasn't found, so we boot PLoP, so it can add USB 2.0 support
+ * # When using "LINUX plpbt.bin", you don't need to remove the .bin extension.
* LABEL plop_not_detected
- * LINUX plpbt.bin hiddenusb usb1=2
+ * LINUX plpbt.bin
+ * APPEND hiddenusb usb1=2
*
* ===========================================================================
*
@@ -51,8 +56,8 @@
* USB stick/drive:
* 1. PLoP can upgrade USB 1.1 speed offered by the BIOS to USB 2.0 speed
* if you have USB 2.0 controllers on your mobo.
- * 2. Some BIOSes only can acees the first 128GiB (137GB) on USB drives, while
- * internal hard drives don't neseccarily suffer from this 128GiB problem.
+ * 2. Some BIOSes only can access the first 128GiB (137GB) on USB drives, while
+ * internal hard drives don't necessarily suffer from this 128GiB problem.
* Using PLoPs USB capabilities, you can access the whole drive.
*
* When you select the "USB" entry in PLoP, it will boot your USB stick/drive
@@ -61,7 +66,7 @@
*
* By using ifplop.c32 you can specify which action you want to do the second
* time your USB stick/drive is booted. So you can load another config file or
- * boot a large hard disk image or whathever you want.
+ * boot a large hard disk image or whatever you want.
*
* PLoP Boot Manager website: http://www.plop.at/en/bootmanager.html
*/
@@ -158,7 +163,7 @@ int main(int argc, char *argv[])
} else {
fprintf(stderr,
"Usage: ifplop.c32 [<plop_detected>] -- [<plop_not_detected>]\n"
- "Example: ifplop.c32 menu.c32 another.cfg -- plpbt.bin hiddenusb usb1=2\n");
+ "Example: ifplop.c32 menu.c32 another.cfg -- plpbt hiddenusb usb1=2\n");
}
return 0;
diff --git a/com32/modules/whichsys.c b/com32/modules/whichsys.c
index c1867228..af133f2c 100644
--- a/com32/modules/whichsys.c
+++ b/com32/modules/whichsys.c
@@ -18,7 +18,7 @@
*
* Usage: whichsys.c32 [-iso- command] [-pxe- command] [-sys- command]
* Examples: whichsys.c32 -iso- chain.c32 hd0 -sys- chain.c32 hd1 swap
- * whichsys.c32 -iso- config iso.cfg -sys- sys.cfg -pxe- pxe.cfg
+ * whichsys.c32 -iso- config iso.cfg -pxe- config pxe.cfg
*
*/
@@ -68,7 +68,7 @@ static void usage(void)
static const char usage[] = "\
Usage: whichsys.c32 [-iso- command] [-pxe- command] [-sys- command]\n\
Examples: whichsys.c32 -iso- chain.c32 hd0 -sys- chain.c32 hd1 swap\n\
- whichsys.c32 -iso- config iso.cfg -sys- sys.cfg -pxe- pxe.cfg\n";
+ whichsys.c32 -iso- config iso.cfg -pxe- config pxe.cfg\n";
fprintf(stderr, usage);
}
diff --git a/core/diskfs.inc b/core/diskfs.inc
index 19a46cc2..b4e10024 100644
--- a/core/diskfs.inc
+++ b/core/diskfs.inc
@@ -98,7 +98,7 @@ trackbuf resb trackbufsize ; Track buffer goes here
; Load configuration file
;
;feng
- ;pm_call load_config
+ ;pm_call pm_load_config
;jz no_config_file
;
diff --git a/core/diskstart.inc b/core/diskstart.inc
index c61a615f..642f37e5 100644
--- a/core/diskstart.inc
+++ b/core/diskstart.inc
@@ -31,9 +31,10 @@ PartInfo equ StackBuf
.gpt equ PartInfo+20
FloppyTable equ PartInfo+76
; Total size of PartInfo + FloppyTable == 76+16 = 92 bytes
-Hidden equ StackBuf-20 ; Partition offset
-OrigFDCTabPtr equ StackBuf-12 ; The 2nd high dword on the stack
-OrigESDI equ StackBuf-8 ; The high dword on the stack
+Hidden equ StackBuf-24 ; Partition offset (qword)
+OrigFDCTabPtr equ StackBuf-16 ; Original FDC table
+OrigDSSI equ StackBuf-12 ; DS:SI -> partinfo
+OrigESDI equ StackBuf-8 ; ES:DI -> $PnP structure
DriveNumber equ StackBuf-4 ; Drive number
StackHome equ Hidden ; The start of the canonical stack
@@ -116,6 +117,8 @@ start:
push dx ; Save drive number (in DL)
push es ; Save initial ES:DI -> $PnP pointer
push di
+ push ds ; Save original DS:SI -> partinfo
+ push si
mov es,cx
;
@@ -174,6 +177,12 @@ floppy:
; Note: di points to beyond the end of PartInfo
;
harddisk:
+ mov dx,[di-76-10] ; Original DS
+ mov si,[di-76-12] ; Original SI
+ shr si,4
+ add dx,si
+ cmp dx,PartInfo >> 4
+ jae .no_partition
test byte [di-76],7Fh ; Sanity check: "active flag" should
jnz .no_partition ; be 00 or 80
cmp [di-76+4],cl ; Sanity check: partition type != 0
diff --git a/core/extern.inc b/core/extern.inc
index 5cd56170..b1dad183 100644
--- a/core/extern.inc
+++ b/core/extern.inc
@@ -33,7 +33,7 @@
; fs.c
extern fs_init, pm_searchdir, getfssec, getfsbytes
- extern pm_mangle_name, load_config
+ extern pm_mangle_name, pm_load_config
extern pm_open_file, pm_close_file
extern SectorSize, SectorShift
diff --git a/core/fs/diskio.c b/core/fs/diskio.c
index d4901c3d..481b59b0 100644
--- a/core/fs/diskio.c
+++ b/core/fs/diskio.c
@@ -6,9 +6,15 @@
#include <core.h>
#include <fs.h>
#include <disk.h>
+#include <ilog2.h>
#define RETRY_COUNT 6
+static inline sector_t chs_max(const struct disk *disk)
+{
+ return (sector_t)disk->secpercyl << 10;
+}
+
static int chs_rdwr_sectors(struct disk *disk, void *buf,
sector_t lba, size_t count, bool is_write)
{
@@ -18,11 +24,15 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf,
int sector_shift = disk->sector_shift;
uint32_t xlba = lba + disk->part_start; /* Truncated LBA (CHS is << 2 TB) */
uint32_t t;
- uint16_t c, h, s;
+ uint32_t c, h, s;
com32sys_t ireg, oreg;
size_t done = 0;
size_t bytes;
int retry;
+ uint32_t maxtransfer = disk->maxtransfer;
+
+ if (lba + disk->part_start >= chs_max(disk))
+ return 0; /* Impossible CHS request */
memset(&ireg, 0, sizeof ireg);
@@ -31,8 +41,8 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf,
while (count) {
chunk = count;
- if (chunk > disk->maxtransfer)
- chunk = disk->maxtransfer;
+ if (chunk > maxtransfer)
+ chunk = maxtransfer;
freeseg = (0x10000 - ((size_t)ptr & 0xffff)) >> sector_shift;
@@ -47,16 +57,19 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf,
if (chunk > freeseg)
chunk = freeseg;
- bytes = chunk << sector_shift;
-
- if (tptr != ptr && is_write)
- memcpy(tptr, ptr, bytes);
-
s = xlba % disk->s;
t = xlba / disk->s;
h = t % disk->h;
c = t / disk->h;
+ if (chunk > (disk->s - s))
+ chunk = disk->s - s;
+
+ bytes = chunk << sector_shift;
+
+ if (tptr != ptr && is_write)
+ memcpy(tptr, ptr, bytes);
+
ireg.eax.b[0] = chunk;
ireg.ecx.b[1] = c;
ireg.ecx.b[0] = ((c & 0x300) >> 2) | (s+1);
@@ -67,34 +80,39 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf,
retry = RETRY_COUNT;
for (;;) {
- dprintf("CHS[%02x]: %u @ %llu (%u/%u/%u) %04x:%04x %s %p\n",
- ireg.edx.b[0], chunk, xlba, c, h, s+1,
- ireg.es, ireg.ebx.w[0],
- (ireg.eax.b[1] & 1) ? "<-" : "->",
- ptr);
-
- __intcall(0x13, &ireg, &oreg);
- if (!(oreg.eflags.l & EFLAGS_CF))
- break;
-
- dprintf("CHS: error AX = %04x\n", oreg.eax.w[0]);
-
- if (retry--)
- continue;
-
- /* For any starting value, this will always end with ..., 1, 0 */
- chunk >>= 1;
- if (chunk) {
- disk->maxtransfer = chunk;
- retry = RETRY_COUNT;
- ireg.eax.b[0] = chunk;
- continue;
- } else {
- printf("CHS: Error %04x %s sector %llu (%u/%u/%u)\n",
- oreg.eax.w[0],
- is_write ? "writing" : "reading",
- lba, c, h, s+1);
+ if (c < 1024) {
+ dprintf("CHS[%02x]: %u @ %llu (%u/%u/%u) %04x:%04x %s %p\n",
+ ireg.edx.b[0], chunk, xlba, c, h, s+1,
+ ireg.es, ireg.ebx.w[0],
+ (ireg.eax.b[1] & 1) ? "<-" : "->",
+ ptr);
+
+ __intcall(0x13, &ireg, &oreg);
+ if (!(oreg.eflags.l & EFLAGS_CF))
+ break;
+
+ dprintf("CHS: error AX = %04x\n", oreg.eax.w[0]);
+
+ if (retry--)
+ continue;
+
+ /*
+ * For any starting value, this will always end with
+ * ..., 1, 0
+ */
+ chunk >>= 1;
+ if (chunk) {
+ maxtransfer = chunk;
+ retry = RETRY_COUNT;
+ ireg.eax.b[0] = chunk;
+ continue;
+ }
}
+
+ printf("CHS: Error %04x %s sector %llu (%u/%u/%u)\n",
+ oreg.eax.w[0],
+ is_write ? "writing" : "reading",
+ lba, c, h, s+1);
return done; /* Failure */
}
@@ -103,6 +121,9 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf,
if (tptr != ptr && !is_write)
memcpy(ptr, tptr, bytes);
+ /* If we dropped maxtransfer, it eventually worked, so remember it */
+ disk->maxtransfer = maxtransfer;
+
ptr += bytes;
xlba += chunk;
count -= chunk;
@@ -131,6 +152,7 @@ static int edd_rdwr_sectors(struct disk *disk, void *buf,
size_t done = 0;
size_t bytes;
int retry;
+ uint32_t maxtransfer = disk->maxtransfer;
memset(&ireg, 0, sizeof ireg);
@@ -146,8 +168,8 @@ static int edd_rdwr_sectors(struct disk *disk, void *buf,
lba += disk->part_start;
while (count) {
chunk = count;
- if (chunk > disk->maxtransfer)
- chunk = disk->maxtransfer;
+ if (chunk > maxtransfer)
+ chunk = maxtransfer;
freeseg = (0x10000 - ((size_t)ptr & 0xffff)) >> sector_shift;
@@ -201,13 +223,28 @@ static int edd_rdwr_sectors(struct disk *disk, void *buf,
/* For any starting value, this will always end with ..., 1, 0 */
chunk >>= 1;
if (chunk) {
- disk->maxtransfer = chunk;
+ maxtransfer = chunk;
retry = RETRY_COUNT;
continue;
}
- /*** XXX: Consider falling back to CHS here?! ***/
- printf("EDD: Error %04x %s sector %llu\n",
+ /*
+ * Total failure. There are systems which identify as
+ * EDD-capable but aren't; the known such systems return
+ * error code AH=1 (invalid function), but let's not
+ * assume that for now.
+ *
+ * Try to fall back to CHS. If the LBA is absurd, the
+ * chs_max() test in chs_rdwr_sectors() will catch it.
+ */
+ done = chs_rdwr_sectors(disk, buf, lba - disk->part_start,
+ count, is_write);
+ if (done == (count << sector_shift)) {
+ /* Successful, assume this is a CHS disk */
+ disk->rdwr_sectors = chs_rdwr_sectors;
+ return done;
+ }
+ printf("EDD: Error %04x %s sector %llu\n",
oreg.eax.w[0],
is_write ? "writing" : "reading",
lba);
@@ -219,6 +256,9 @@ static int edd_rdwr_sectors(struct disk *disk, void *buf,
if (tptr != ptr && !is_write)
memcpy(ptr, tptr, bytes);
+ /* If we dropped maxtransfer, it eventually worked, so remember it */
+ disk->maxtransfer = maxtransfer;
+
ptr += bytes;
lba += chunk;
count -= chunk;
@@ -226,6 +266,7 @@ static int edd_rdwr_sectors(struct disk *disk, void *buf,
}
return done;
}
+
struct edd_disk_params {
uint16_t len;
uint16_t flags;
@@ -251,19 +292,6 @@ static inline bool is_power_of_2(uint32_t x)
return !(x & (x-1));
}
-static int ilog2(uint32_t num)
-{
- int i = 0;
-
- if (!is_power_of_2(num)) {
- printf("ERROR: the num must be power of 2 when conveting to log2\n");
- return 0;
- }
- while (num >>= 1)
- i++;
- return i;
-}
-
void getoneblk(struct disk *disk, char *buf, block_t block, int block_size)
{
int sec_per_block = block_size / disk->sector_size;
@@ -349,10 +377,10 @@ struct disk *disk_init(uint8_t devno, bool cdrom, sector_t part_start,
}
disk.disk_number = devno;
- disk.type = ebios;
disk.sector_size = sector_size;
disk.sector_shift = ilog2(sector_size);
disk.part_start = part_start;
+ disk.secpercyl = disk.h * disk.s;
disk.rdwr_sectors = ebios ? edd_rdwr_sectors : chs_rdwr_sectors;
if (!MaxTransfer || MaxTransfer > hard_max_transfer)
diff --git a/core/fs/fs.c b/core/fs/fs.c
index 48856c9e..ad2fb370 100644
--- a/core/fs/fs.c
+++ b/core/fs/fs.c
@@ -77,7 +77,7 @@ void _close_file(struct file *file)
* Convert between a 16-bit file handle and a file structure
*/
-void load_config(void)
+void pm_load_config(com32sys_t *regs)
{
int err;
@@ -85,6 +85,8 @@ void load_config(void)
if (err)
printf("ERROR: No configuration file found\n");
+
+ set_flags(regs, err ? EFLAGS_ZF : 0);
}
void pm_mangle_name(com32sys_t *regs)
diff --git a/core/fs/loadhigh.c b/core/fs/loadhigh.c
index e365b1a3..bd9d3535 100644
--- a/core/fs/loadhigh.c
+++ b/core/fs/loadhigh.c
@@ -50,6 +50,7 @@ void pm_load_high(com32sys_t *regs)
struct file *file;
uint32_t sector_mask;
size_t pad;
+ uint32_t retflags = 0;
bytes = regs->eax.l;
zero_mask = regs->edx.w[0];
@@ -58,9 +59,6 @@ void pm_load_high(com32sys_t *regs)
file = handle_to_file(regs->esi.w[0]);
fs = file->fs;
- regs->eflags.l &= ~(EFLAGS_CF|EFLAGS_OF|EFLAGS_AF|
- EFLAGS_PF|EFLAGS_ZF|EFLAGS_SF);
-
sector_mask = SECTOR_SIZE(fs) - 1;
while (bytes) {
@@ -69,7 +67,7 @@ void pm_load_high(com32sys_t *regs)
if (buf + SECTOR_SIZE(fs) > limit) {
/* Can't fit even one more sector in... */
- regs->eflags.l |= EFLAGS_OF;
+ retflags = EFLAGS_OF;
break;
}
@@ -99,7 +97,7 @@ void pm_load_high(com32sys_t *regs)
*/
_close_file(file);
regs->esi.w[0] = 0;
- regs->eflags.l |= EFLAGS_CF;
+ retflags = EFLAGS_CF;
break;
}
}
@@ -110,4 +108,5 @@ void pm_load_high(com32sys_t *regs)
regs->ebx.l = (size_t)buf;
regs->edi.l = (size_t)buf + pad;
+ set_flags(regs, retflags);
}
diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c
index 25bd094d..0238ed4b 100644
--- a/core/fs/pxe/pxe.c
+++ b/core/fs/pxe/pxe.c
@@ -245,7 +245,7 @@ static const char *parse_dotquad(const char *ip_str, uint32_t *res)
}
p--;
- *res = ip;
+ *res = htonl(ip);
return p;
}
diff --git a/core/include/core.h b/core/include/core.h
index 799c337d..6e6f7fb8 100644
--- a/core/include/core.h
+++ b/core/include/core.h
@@ -74,4 +74,17 @@ static inline uint32_t ms_timer(void)
return __ms_timer;
}
+/*
+ * Helper routine to return a specific set of flags
+ */
+static inline void set_flags(com32sys_t *regs, uint32_t flags)
+{
+ uint32_t eflags;
+
+ eflags = regs->eflags.l;
+ eflags &= ~(EFLAGS_CF|EFLAGS_PF|EFLAGS_AF|EFLAGS_ZF|EFLAGS_SF|EFLAGS_OF);
+ eflags |= flags;
+ regs->eflags.l = eflags;
+}
+
#endif /* CORE_H */
diff --git a/core/include/disk.h b/core/include/disk.h
index df0476a3..ac23e921 100644
--- a/core/include/disk.h
+++ b/core/include/disk.h
@@ -13,17 +13,16 @@ typedef uint64_t block_t;
* contains the I/O function.
*/
struct disk {
- uint8_t disk_number; /* in BIOS style */
- uint8_t type; /* CHS or EDD */
- uint16_t sector_size; /* gener512B or 2048B */
- uint8_t sector_shift;
+ unsigned int disk_number; /* in BIOS style */
+ unsigned int sector_size; /* gener512B or 2048B */
+ unsigned int sector_shift;
+ unsigned int maxtransfer; /* Max sectors per transfer */
- uint8_t h, s; /* CHS geometry */
- uint8_t pad;
+ unsigned int h, s; /* CHS geometry */
+ unsigned int secpercyl; /* h*s */
+ unsigned int _pad;
sector_t part_start; /* the start address of this partition(in sectors) */
-
- uint32_t maxtransfer; /* Max sectors per transfer */
int (*rdwr_sectors)(struct disk *, void *, sector_t, size_t, bool);
};
diff --git a/core/include/fs.h b/core/include/fs.h
index 129ac1e6..fb416eef 100644
--- a/core/include/fs.h
+++ b/core/include/fs.h
@@ -116,8 +116,6 @@ struct file {
struct inode *inode; /* The file-specific information */
};
-enum dev_type {CHS, EDD};
-
/*
* Struct device contains:
* the pointer points to the disk structure,
diff --git a/core/isolinux.asm b/core/isolinux.asm
index 1ef68d8c..ca8ee3a3 100644
--- a/core/isolinux.asm
+++ b/core/isolinux.asm
@@ -1186,7 +1186,8 @@ ROOT_FS_OPS:
;
; Locate the configuration file
;
- pm_call load_config
+ pm_call pm_load_config
+ jz no_config_file
;
; Now we have the config file open. Parse the config file and
diff --git a/core/mem/free.c b/core/mem/free.c
index 9d853a4b..70b45a36 100644
--- a/core/mem/free.c
+++ b/core/mem/free.c
@@ -141,7 +141,7 @@ static void __free_tagged(malloc_tag_t tag) {
for (i = 0; i < NHEAP; i++) {
dprintf("__free_tagged(%u) heap %d\n", tag, i);
head = &__core_malloc_head[i];
- for (fp = head ; fp != head ; fp = fp->a.next) {
+ for (fp = head->a.next ; fp != head ; fp = fp->a.next) {
if (ARENA_TYPE_GET(fp->a.attrs) == ARENA_TYPE_USED &&
fp->a.tag == tag)
fp = __free_block(fp);
diff --git a/core/pxelinux.asm b/core/pxelinux.asm
index 8084ac9a..a46b3da5 100644
--- a/core/pxelinux.asm
+++ b/core/pxelinux.asm
@@ -253,11 +253,6 @@ ROOT_FS_OPS:
;
;
-; Load configuration file
-;
- pm_call load_config
-
-;
; Linux kernel loading code is common. However, we need to define
; a couple of helper macros...
;
@@ -269,6 +264,12 @@ ROOT_FS_OPS:
%endmacro
;
+; Load configuration file
+;
+ pm_call pm_load_config
+ jz no_config_file
+
+;
; Now we have the config file open. Parse the config file and
; run the user interface.
;
diff --git a/dos/Makefile b/dos/Makefile
index 574b65ec..2667de8c 100644
--- a/dos/Makefile
+++ b/dos/Makefile
@@ -23,22 +23,24 @@ CFLAGS += -D__MSDOS__
LDFLAGS = -T dosexe.ld
OPTFLAGS = -g
INCLUDES = -include code16.h -nostdinc -iwithprefix include \
- -I. -I.. -I../libfat -I ../libinstaller
+ -I. -I.. -I../libfat -I ../libinstaller -I ../libinstaller/getopt
SRCS = syslinux.c \
../libinstaller/fat.c \
../libinstaller/syslxmod.c \
+ ../libinstaller/syslxopt.c \
../libinstaller/setadv.c \
+ ../libinstaller/getopt/getopt_long.c \
../libinstaller/bootsect_bin.c \
- ../libinstaller/ldlinux_bin.c \
../libinstaller/mbr_bin.c \
$(wildcard ../libfat/*.c)
-OBJS = header.o crt0.o $(patsubst %.c,%.o,$(notdir $(SRCS)))
+OBJS = header.o crt0.o ldlinux.o \
+ $(patsubst %.c,%.o,$(notdir $(SRCS)))
LIBOBJS = int2526.o conio.o memcpy.o memset.o memmove.o skipatou.o atou.o \
- malloc.o free.o getsetsl.o \
- argv.o printf.o __divdi3.o __udivmoddi4.o
+ malloc.o free.o getopt_long.o getsetsl.o strchr.o strtoul.o \
+ strntoumax.o argv.o printf.o __divdi3.o __udivmoddi4.o
-VPATH = .:../libfat:../libinstaller
+VPATH = .:../libfat:../libinstaller:../libinstaller/getopt
TARGETS = syslinux.com
@@ -71,4 +73,6 @@ syslinux.com: syslinux.elf
%.com: %.asm
$(NASM) $(NASMOPT) -f bin -o $@ -MP -MD .$@.d -l $*.lst $<
+ldlinux.o: ldlinux.S ../core/ldlinux.sys
+
-include .*.d *.tmp
diff --git a/dos/ctype.h b/dos/ctype.h
new file mode 100644
index 00000000..c0d00c04
--- /dev/null
+++ b/dos/ctype.h
@@ -0,0 +1,3 @@
+static int isspace(int c) {
+ return (c == ' ');
+}
diff --git a/dos/dosexe.ld b/dos/dosexe.ld
index 4612b30a..c67c5060 100644
--- a/dos/dosexe.ld
+++ b/dos/dosexe.ld
@@ -26,20 +26,22 @@ SECTIONS
__header_size = .;
__payload_lma = .;
- . = 0;
+ . = 0x100000000 - syslinux_ldlinux_size;
.payload : AT (__payload_lma) {
__payload_start = .;
- ldlinux_bin.o(.data)
+ *(.payload)
__payload_end = .;
}
__payload_len = __payload_end - __payload_start;
__payload_dwords = __payload_len >> 2;
- . = ALIGN(16);
- __text_lma = __payload_lma + .;
+ __text_lma = __payload_lma + syslinux_ldlinux_size;
__payload_sseg = (__payload_lma - __text_lma) >> 4;
_exe_text_seg = (__text_lma - __header_size) >> 4;
+ __assert1 = ASSERT((__payload_len == syslinux_ldlinux_size),
+ "syslinux_ldlinux_size must equal the size of .payload");
+
. = 0;
.text : AT (__text_lma) {
*(.text .stub .text.* .gnu.linkonce.t.*)
diff --git a/dos/getsetsl.c b/dos/getsetsl.c
index a48f3df2..67e954d1 100644
--- a/dos/getsetsl.c
+++ b/dos/getsetsl.c
@@ -87,7 +87,7 @@ void memcpy_to_sl(void *dst, const void *src, size_t len)
uint16_t seg;
uint16_t off;
- seg = ldlinux_seg + ((size_t)dst >> 4);
+ seg = ds() + ((size_t)dst >> 4);
off = (size_t)dst & 15;
asm volatile("pushw %%es ; "
@@ -98,3 +98,20 @@ void memcpy_to_sl(void *dst, const void *src, size_t len)
: "r" (seg)
: "memory");
}
+
+void memcpy_from_sl(void *dst, const void *src, size_t len)
+{
+ uint16_t seg;
+ uint16_t off;
+
+ seg = ds() + ((size_t)src >> 4);
+ off = (size_t)src & 15;
+
+ asm volatile("pushw %%ds ; "
+ "movw %3,%%ds ; "
+ "rep ; movsb ; "
+ "popw %%ds"
+ : "+D" (dst), "+S" (off), "+c" (len)
+ : "r" (seg)
+ : "memory");
+}
diff --git a/dos/int2526.S b/dos/int2526.S
index bcb7707e..53e63f84 100644
--- a/dos/int2526.S
+++ b/dos/int2526.S
@@ -50,6 +50,7 @@ int25_read_sector:
popl %edi
popl %ebp
retl
+ .size int25_read_sector, .-int25_read_sector
.globl int26_write_sector
.type int26_write_sector, @function
@@ -74,3 +75,4 @@ int26_write_sector:
popl %edi
popl %ebp
retl
+ .size int26_write_sector, .-int26_write_sector
diff --git a/dos/ldlinux.S b/dos/ldlinux.S
new file mode 100644
index 00000000..17a65830
--- /dev/null
+++ b/dos/ldlinux.S
@@ -0,0 +1,19 @@
+/*
+ * Wrap ldlinux.sys; this needs special handling for DOS.
+ */
+
+ .section ".payload","aw"
+ .balign 16
+ .globl syslinux_ldlinux, syslinux_ldlinux_size
+syslinux_ldlinux:
+ .incbin "../core/ldlinux.sys"
+ .space ((syslinux_ldlinux - .) & 511)
+syslinux_ldlinux_size = . - syslinux_ldlinux
+ .size syslinux_ldlinux, .-syslinux_ldlinux
+
+ .section ".rodata","a"
+ .balign 4
+ .globl syslinux_ldlinux_len
+syslinux_ldlinux_len:
+ .long syslinux_ldlinux_size
+ .size syslinux_ldlinux_len, .-syslinux_ldlinux_len
diff --git a/dos/stdio.h b/dos/stdio.h
index 2c256669..c7ca25cb 100644
--- a/dos/stdio.h
+++ b/dos/stdio.h
@@ -16,6 +16,8 @@ int printf(const char *fmt, ...);
#define stdout 1
#define stderr 2
+#define EOF (-1)
+
#define fprintf(x, y, ...) printf(y, ## __VA_ARGS__)
#endif /* STDIO_H */
diff --git a/dos/stdlib.h b/dos/stdlib.h
index 71af6907..d3467056 100644
--- a/dos/stdlib.h
+++ b/dos/stdlib.h
@@ -10,4 +10,7 @@ void *malloc(size_t);
void *calloc(size_t, size_t);
void free(void *);
+extern unsigned long int strtoul(const char *nptr,
+ char **endptr, int base);
+
#endif
diff --git a/dos/strchr.c b/dos/strchr.c
new file mode 100644
index 00000000..83153113
--- /dev/null
+++ b/dos/strchr.c
@@ -0,0 +1,17 @@
+/*
+ * strchr.c
+ */
+
+#include <string.h>
+#include "mystuff.h"
+
+char *strchr(const char *s, int c)
+{
+ while (*s != (char)c) {
+ if (!*s)
+ return NULL;
+ s++;
+ }
+
+ return (char *)s;
+}
diff --git a/dos/string.h b/dos/string.h
index 5ee829e8..f648de2d 100644
--- a/dos/string.h
+++ b/dos/string.h
@@ -21,4 +21,6 @@ static inline int memcmp(const void *__m1, const void *__m2, unsigned int __n)
return rv;
}
+extern char *strchr(const char *s, int c);
+
#endif /* _STRING_H */
diff --git a/dos/strntoumax.c b/dos/strntoumax.c
new file mode 100644
index 00000000..d8bc73bc
--- /dev/null
+++ b/dos/strntoumax.c
@@ -0,0 +1,73 @@
+/*
+ * strntoumax.c
+ *
+ * The strntoumax() function and associated
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <ctype.h>
+
+static inline int digitval(int ch)
+{
+ if (ch >= '0' && ch <= '9') {
+ return ch - '0';
+ } else if (ch >= 'A' && ch <= 'Z') {
+ return ch - 'A' + 10;
+ } else if (ch >= 'a' && ch <= 'z') {
+ return ch - 'a' + 10;
+ } else {
+ return -1;
+ }
+}
+
+uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n)
+{
+ int minus = 0;
+ uintmax_t v = 0;
+ int d;
+
+ while (n && isspace((unsigned char)*nptr)) {
+ nptr++;
+ n--;
+ }
+
+ /* Single optional + or - */
+ if (n && *nptr == '-') {
+ minus = 1;
+ nptr++;
+ n--;
+ } else if (n && *nptr == '+') {
+ nptr++;
+ }
+
+ if (base == 0) {
+ if (n >= 2 && nptr[0] == '0' && (nptr[1] == 'x' || nptr[1] == 'X')) {
+ n -= 2;
+ nptr += 2;
+ base = 16;
+ } else if (n >= 1 && nptr[0] == '0') {
+ n--;
+ nptr++;
+ base = 8;
+ } else {
+ base = 10;
+ }
+ } else if (base == 16) {
+ if (n >= 2 && nptr[0] == '0' && (nptr[1] == 'x' || nptr[1] == 'X')) {
+ n -= 2;
+ nptr += 2;
+ }
+ }
+
+ while (n && (d = digitval(*nptr)) >= 0 && d < base) {
+ v = v * base + d;
+ n--;
+ nptr++;
+ }
+
+ if (endptr)
+ *endptr = (char *)nptr;
+
+ return minus ? -v : v;
+}
diff --git a/dos/strtoul.c b/dos/strtoul.c
new file mode 100644
index 00000000..3be94307
--- /dev/null
+++ b/dos/strtoul.c
@@ -0,0 +1,15 @@
+/*
+ * strtoul.c
+ *
+ * strtoul() function
+ */
+
+#include <stddef.h>
+#include <inttypes.h>
+
+extern uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n);
+
+unsigned long strtoul(const char *nptr, char **endptr, int base)
+{
+ return (unsigned long) strntoumax(nptr, endptr, base, ~(size_t) 0);
+}
diff --git a/dos/sysexits.h b/dos/sysexits.h
new file mode 100644
index 00000000..483d3bab
--- /dev/null
+++ b/dos/sysexits.h
@@ -0,0 +1 @@
+#define EX_USAGE 0x40
diff --git a/dos/syslinux.c b/dos/syslinux.c
index 9574553d..b5fdfc52 100644
--- a/dos/syslinux.c
+++ b/dos/syslinux.c
@@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 1998-2008 H. Peter Anvin - All Rights Reserved
- * Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ * Copyright 2009-2010 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
@@ -18,6 +18,7 @@
*/
#include <errno.h>
+#include <getopt.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -27,8 +28,11 @@
#include "syslinux.h"
#include "libfat.h"
#include "setadv.h"
+#include "sysexits.h"
+#include "syslxopt.h"
+#include "syslxint.h"
-const char *program = "syslinux"; /* Name of program */
+char *program = "syslinux.com"; /* Name of program */
uint16_t dos_version;
#ifdef DEBUG
@@ -44,12 +48,6 @@ void pause(void)
# define pause() ((void)0)
#endif
-void __attribute__ ((noreturn)) usage(void)
-{
- puts("Usage: syslinux [-sfmar][-d directory] <drive>: [bootsecfile]\n");
- exit(1);
-}
-
void unlock_device(int);
void __attribute__ ((noreturn)) die(const char *msg)
@@ -122,11 +120,9 @@ int rename(const char *oldname, const char *newname)
return 0;
}
-extern const char __payload_sseg[];
-uint16_t ldlinux_seg;
-
ssize_t write_ldlinux(int fd)
{
+ uint16_t ldlinux_seg = ((size_t)syslinux_ldlinux >> 4) + ds();
uint32_t offset = 0;
uint16_t rv;
uint8_t err;
@@ -139,8 +135,8 @@ ssize_t write_ldlinux(int fd)
"movw %6,%%ds ; "
"int $0x21 ; "
"popw %%ds ; " "setc %0":"=bcdm" (err), "=a"(rv)
- :"a"(0x4000), "b"(fd), "c"(chunk), "d"(offset & 15),
- "SD"((uint16_t) (ldlinux_seg + (offset >> 4))));
+ :"a"(0x4000), "b"(fd), "c"(chunk), "d" (offset & 15),
+ "SD" ((uint16_t)(ldlinux_seg + (offset >> 4))));
if (err || rv == 0)
die("file write error");
offset += rv;
@@ -181,7 +177,7 @@ uint16_t data_segment(void)
void write_device(int drive, const void *buf, size_t nsecs, unsigned int sector)
{
- uint16_t errnum;
+ uint16_t errnum = 0x0001;
struct diskio dio;
dprintf("write_device(%d,%p,%u,%u)\n", drive, buf, nsecs, sector);
@@ -190,14 +186,17 @@ void write_device(int drive, const void *buf, size_t nsecs, unsigned int sector)
dio.sectors = nsecs;
dio.bufoffs = (uintptr_t) buf;
dio.bufseg = data_segment();
-
- /* Try FAT32-aware system call first */
- asm volatile("int $0x21 ; jc 1f ; xorw %0,%0\n"
- "1:"
- : "=a" (errnum)
- : "a" (0x7305), "b" (&dio), "c" (-1), "d" (drive),
- "S" (1), "m" (dio)
- : "memory");
+
+ if (dos_version >= 0x070a) {
+ /* Try FAT32-aware system call first */
+ asm volatile("int $0x21 ; jc 1f ; xorw %0,%0\n"
+ "1:"
+ : "=a" (errnum)
+ : "a" (0x7305), "b" (&dio), "c" (-1), "d" (drive),
+ "S" (1), "m" (dio)
+ : "memory");
+ dprintf(" rv(7305) = %04x", errnum);
+ }
/* If not supported, try the legacy system call (int2526.S) */
if (errnum == 0x0001)
@@ -209,9 +208,9 @@ void write_device(int drive, const void *buf, size_t nsecs, unsigned int sector)
}
}
-void read_device(int drive, const void *buf, size_t nsecs, unsigned int sector)
+void read_device(int drive, void *buf, size_t nsecs, unsigned int sector)
{
- uint16_t errnum;
+ uint16_t errnum = 0x0001;
struct diskio dio;
dprintf("read_device(%d,%p,%u,%u)\n", drive, buf, nsecs, sector);
@@ -220,13 +219,16 @@ void read_device(int drive, const void *buf, size_t nsecs, unsigned int sector)
dio.sectors = nsecs;
dio.bufoffs = (uintptr_t) buf;
dio.bufseg = data_segment();
-
- /* Try FAT32-aware system call first */
- asm volatile("int $0x21 ; jc 1f ; xorw %0,%0\n"
- "1:"
- : "=a" (errnum)
- : "a" (0x7305), "b" (&dio), "c" (-1), "d" (drive),
- "S" (0), "m" (dio));
+
+ if (dos_version >= 0x070a) {
+ /* Try FAT32-aware system call first */
+ asm volatile("int $0x21 ; jc 1f ; xorw %0,%0\n"
+ "1:"
+ : "=a" (errnum)
+ : "a" (0x7305), "b" (&dio), "c" (-1), "d" (drive),
+ "S" (0), "m" (dio));
+ dprintf(" rv(7305) = %04x", errnum);
+ }
/* If not supported, try the legacy system call (int2526.S) */
if (errnum == 0x0001)
@@ -585,78 +587,35 @@ int main(int argc, char *argv[])
static unsigned char sectbuf[SECTOR_SIZE];
int dev_fd, fd;
static char ldlinux_name[] = "@:\\ldlinux.sys";
- char **argp, *opt;
- int force = 0; /* -f (force) option */
struct libfat_filesystem *fs;
libfat_sector_t s, *secp;
libfat_sector_t *sectors;
int ldlinux_sectors;
int32_t ldlinux_cluster;
int nsectors;
- const char *device = NULL, *bootsecfile = NULL;
const char *errmsg;
int i;
- int writembr = 0; /* -m (write MBR) option */
- int set_active = 0; /* -a (set partition active) option */
- const char *subdir = NULL;
- int stupid = 0;
- int raid_mode = 0;
int patch_sectors;
-
- ldlinux_seg = (size_t) __payload_sseg + data_segment();
+ unsigned char *dp;
dprintf("argv = %p\n", argv);
for (i = 0; i <= argc; i++)
dprintf("argv[%d] = %p = \"%s\"\n", i, argv[i], argv[i]);
- (void)argc; /* Unused */
-
get_dos_version();
- for (argp = argv + 1; *argp; argp++) {
- if (**argp == '-') {
- opt = *argp + 1;
- if (!*opt)
- usage();
-
- while (*opt) {
- switch (*opt) {
- case 's': /* Use "safe, slow and stupid" code */
- stupid = 1;
- break;
- case 'r': /* RAID mode */
- raid_mode = 1;
- break;
- case 'f': /* Force install */
- force = 1;
- break;
- case 'm': /* Write MBR */
- writembr = 1;
- break;
- case 'a': /* Set partition active */
- set_active = 1;
- break;
- case 'd':
- if (argp[1])
- subdir = *++argp;
- break;
- default:
- usage();
- }
- opt++;
- }
- } else {
- if (bootsecfile)
- usage();
- else if (device)
- bootsecfile = *argp;
- else
- device = *argp;
- }
- }
+ argv[0] = program;
+ parse_options(argc, argv, MODE_SYSLINUX_DOSWIN);
- if (!device)
- usage();
+ if (!opt.device)
+ usage(EX_USAGE, MODE_SYSLINUX_DOSWIN);
+ if (opt.sectors || opt.heads || opt.reset_adv || opt.set_once
+ || (opt.update_only > 0) || opt.menu_save || opt.offset) {
+ fprintf(stderr,
+ "At least one specified option not yet implemented"
+ " for this installer.\n");
+ exit(1);
+ }
/*
* Create an ADV in memory... this should be smarter.
@@ -666,9 +625,9 @@ int main(int argc, char *argv[])
/*
* Figure out which drive we're talking to
*/
- dev_fd = (device[0] & ~0x20) - 0x40;
- if (dev_fd < 1 || dev_fd > 26 || device[1] != ':' || device[2])
- usage();
+ dev_fd = (opt.device[0] & ~0x20) - 0x40;
+ if (dev_fd < 1 || dev_fd > 26 || opt.device[1] != ':' || opt.device[2])
+ usage(EX_USAGE, MODE_SYSLINUX_DOSWIN);
set_lock_device(dev_fd);
@@ -720,7 +679,7 @@ int main(int argc, char *argv[])
/*
* If requested, move ldlinux.sys
*/
- if (subdir) {
+ if (opt.directory) {
char new_ldlinux_name[160];
char *cp = new_ldlinux_name + 3;
const char *sd;
@@ -730,7 +689,7 @@ int main(int argc, char *argv[])
new_ldlinux_name[1] = ':';
new_ldlinux_name[2] = '\\';
- for (sd = subdir; *sd; sd++) {
+ for (sd = opt.directory; *sd; sd++) {
char c = *sd;
if (c == '/' || c == '\\') {
@@ -763,29 +722,24 @@ int main(int argc, char *argv[])
/*
* Patch ldlinux.sys and the boot sector
*/
- i = syslinux_patch(sectors, nsectors, stupid, raid_mode, subdir, NULL);
+ i = syslinux_patch(sectors, nsectors, opt.stupid_mode, opt.raid_mode, opt.directory, NULL);
patch_sectors = (i + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
/*
* Overwrite the now-patched ldlinux.sys
*/
/* lock_device(3); -- doesn't seem to be needed */
+ dp = syslinux_ldlinux;
for (i = 0; i < patch_sectors; i++) {
- uint16_t si, di, cx;
- si = 0;
- di = (size_t) sectbuf;
- cx = SECTOR_SIZE >> 2;
- asm volatile ("movw %3,%%fs ; fs ; rep ; movsl":"+S" (si), "+D"(di),
- "+c"(cx)
- :"abd"((uint16_t)
- (ldlinux_seg + (i << (SECTOR_SHIFT - 4)))));
+ memcpy_from_sl(sectbuf, dp, SECTOR_SIZE);
+ dp += SECTOR_SIZE;
write_device(dev_fd, sectbuf, 1, sectors[i]);
}
/*
* Muck with the MBR, if desired, while we hold the lock
*/
- adjust_mbr(dev_fd, writembr, set_active);
+ adjust_mbr(dev_fd, opt.install_mbr, opt.activate_partition);
/*
* To finish up, write the boot sector
@@ -798,9 +752,9 @@ int main(int argc, char *argv[])
syslinux_make_bootsect(sectbuf);
/* Write new boot sector */
- if (bootsecfile) {
+ if (opt.bootsecfile) {
unlock_device(0);
- fd = creat(bootsecfile, 0x20); /* ARCHIVE */
+ fd = creat(opt.bootsecfile, 0x20); /* ARCHIVE */
write_file(fd, sectbuf, SECTOR_SIZE);
close(fd);
} else {
diff --git a/extlinux/main.c b/extlinux/main.c
index daebc101..002cecd9 100644..100755
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -809,7 +809,7 @@ int main(int argc, char *argv[])
{
parse_options(argc, argv, MODE_EXTLINUX);
- if (!opt.directory)
+ if (!opt.directory || opt.install_mbr || opt.activate_partition)
usage(EX_USAGE, 0);
if (opt.update_only == -1) {
diff --git a/libinstaller/getopt/getopt.h b/libinstaller/getopt/getopt.h
new file mode 100644
index 00000000..a1b74b10
--- /dev/null
+++ b/libinstaller/getopt/getopt.h
@@ -0,0 +1,25 @@
+#ifndef _GETOPT_H
+#define _GETOPT_H
+
+/* (Very slightly) adapted from klibc */
+
+struct option {
+ const char *name;
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+enum {
+ no_argument = 0,
+ required_argument = 1,
+ optional_argument = 2,
+};
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+extern int getopt_long(int, char *const *, const char *,
+ const struct option *, int *);
+
+#endif /* _GETOPT_H */
diff --git a/libinstaller/getopt/getopt_long.c b/libinstaller/getopt/getopt_long.c
new file mode 100644
index 00000000..cd7fef5a
--- /dev/null
+++ b/libinstaller/getopt/getopt_long.c
@@ -0,0 +1,152 @@
+/*
+ * getopt.c
+ *
+ * getopt_long(), or at least a common subset thereof:
+ *
+ * - Option reordering is not supported
+ * - -W foo is not supported
+ * - First optstring character "-" not supported.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <stddef.h>
+#include <getopt.h>
+
+char *optarg;
+int optind, opterr, optopt;
+static struct getopt_private_state {
+ const char *optptr;
+ const char *last_optstring;
+ char *const *last_argv;
+} pvt;
+
+static inline const char *option_matches(const char *arg_str,
+ const char *opt_name)
+{
+ while (*arg_str != '\0' && *arg_str != '=') {
+ if (*arg_str++ != *opt_name++)
+ return NULL;
+ }
+
+ if (*opt_name)
+ return NULL;
+
+ return arg_str;
+}
+
+int getopt_long(int argc, char *const *argv, const char *optstring,
+ const struct option *longopts, int *longindex)
+{
+ const char *carg;
+ const char *osptr;
+ int opt;
+
+ /* getopt() relies on a number of different global state
+ variables, which can make this really confusing if there is
+ more than one use of getopt() in the same program. This
+ attempts to detect that situation by detecting if the
+ "optstring" or "argv" argument have changed since last time
+ we were called; if so, reinitialize the query state. */
+
+ if (optstring != pvt.last_optstring || argv != pvt.last_argv ||
+ optind < 1 || optind > argc) {
+ /* optind doesn't match the current query */
+ pvt.last_optstring = optstring;
+ pvt.last_argv = argv;
+ optind = 1;
+ pvt.optptr = NULL;
+ }
+
+ carg = argv[optind];
+
+ /* First, eliminate all non-option cases */
+
+ if (!carg || carg[0] != '-' || !carg[1])
+ return -1;
+
+ if (carg[1] == '-') {
+ const struct option *lo;
+ const char *opt_end = NULL;
+
+ optind++;
+
+ /* Either it's a long option, or it's -- */
+ if (!carg[2]) {
+ /* It's -- */
+ return -1;
+ }
+
+ for (lo = longopts; lo->name; lo++) {
+ if ((opt_end = option_matches(carg+2, lo->name)))
+ break;
+ }
+ if (!opt_end)
+ return '?';
+
+ if (longindex)
+ *longindex = lo-longopts;
+
+ if (*opt_end == '=') {
+ if (lo->has_arg)
+ optarg = (char *)opt_end+1;
+ else
+ return '?';
+ } else if (lo->has_arg == 1) {
+ if (!(optarg = argv[optind]))
+ return '?';
+ optind++;
+ }
+
+ if (lo->flag) {
+ *lo->flag = lo->val;
+ return 0;
+ } else {
+ return lo->val;
+ }
+ }
+
+ if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) {
+ /* Someone frobbed optind, change to new opt. */
+ pvt.optptr = carg + 1;
+ }
+
+ opt = *pvt.optptr++;
+
+ if (opt != ':' && (osptr = strchr(optstring, opt))) {
+ if (osptr[1] == ':') {
+ if (*pvt.optptr) {
+ /* Argument-taking option with attached
+ argument */
+ optarg = (char *)pvt.optptr;
+ optind++;
+ } else {
+ /* Argument-taking option with non-attached
+ argument */
+ if (argv[optind + 1]) {
+ optarg = (char *)argv[optind+1];
+ optind += 2;
+ } else {
+ /* Missing argument */
+ optind++;
+ return (optstring[0] == ':')
+ ? ':' : '?';
+ }
+ }
+ return opt;
+ } else {
+ /* Non-argument-taking option */
+ /* pvt.optptr will remember the exact position to
+ resume at */
+ if (!*pvt.optptr)
+ optind++;
+ return opt;
+ }
+ } else {
+ /* Unknown option */
+ optopt = opt;
+ if (!*pvt.optptr)
+ optind++;
+ return '?';
+ }
+}
diff --git a/libinstaller/syslxint.h b/libinstaller/syslxint.h
index f16c2e5c..14a7fc2b 100644
--- a/libinstaller/syslxint.h
+++ b/libinstaller/syslxint.h
@@ -111,8 +111,6 @@ static inline void set_64(uint64_t *p, uint64_t v)
*/
#ifdef __MSDOS__
-extern uint16_t ldlinux_seg; /* Defined in dos/syslinux.c */
-
static inline __attribute__ ((const))
uint16_t ds(void)
{
@@ -125,7 +123,7 @@ static inline void *set_fs(const void *p)
{
uint16_t seg;
- seg = ldlinux_seg + ((size_t) p >> 4);
+ seg = ds() + ((size_t) p >> 4);
asm volatile ("movw %0,%%fs"::"rm" (seg));
return (void *)((size_t) p & 0xf);
}
@@ -139,6 +137,7 @@ void set_16_sl(uint16_t * p, uint16_t v);
void set_32_sl(uint32_t * p, uint32_t v);
void set_64_sl(uint64_t * p, uint64_t v);
void memcpy_to_sl(void *dst, const void *src, size_t len);
+void memcpy_from_sl(void *dst, const void *src, size_t len);
#else
@@ -152,6 +151,7 @@ void memcpy_to_sl(void *dst, const void *src, size_t len);
#define set_32_sl(x,y) set_32(x,y)
#define set_64_sl(x,y) set_64(x,y)
#define memcpy_to_sl(d,s,l) memcpy(d,s,l)
+#define memcpy_from_sl(d,s,l) memcpy(d,s,l)
#endif
diff --git a/libinstaller/syslxopt.c b/libinstaller/syslxopt.c
index 0ff2efbb..9b42c66f 100644
--- a/libinstaller/syslxopt.c
+++ b/libinstaller/syslxopt.c
@@ -40,10 +40,14 @@ struct sys_options opt = {
.device = NULL,
.offset = 0,
.menu_save = NULL,
+ .install_mbr = 0,
+ .activate_partition = 0,
+ .force = 0,
+ .bootsecfile = NULL,
};
const struct option long_options[] = {
- {"force", 0, NULL, 'f'}, /* dummy option for compatibility */
+ {"force", 0, NULL, 'f'}, /* DOS/Win32/mtools only */
{"install", 0, NULL, 'i'},
{"directory", 1, NULL, 'd'},
{"offset", 1, NULL, 't'},
@@ -59,10 +63,12 @@ const struct option long_options[] = {
{"clear-once", 0, NULL, 'O'},
{"reset-adv", 0, NULL, OPT_RESET_ADV},
{"menu-save", 1, NULL, 'M'},
+ {"mbr", 0, NULL, 'm'}, /* DOS/Win32 only */
+ {"active", 0, NULL, 'a'}, /* DOS/Win32 only */
{0, 0, 0, 0}
};
-const char short_options[] = "t:fid:UuzS:H:rvho:OM:";
+const char short_options[] = "t:fid:UuzS:H:rvho:OM:ma";
void __attribute__ ((noreturn)) usage(int rv, enum syslinux_mode mode)
{
@@ -83,11 +89,19 @@ void __attribute__ ((noreturn)) usage(int rv, enum syslinux_mode mode)
"Usage: %s [options] directory\n",
program);
break;
+
+ case MODE_SYSLINUX_DOSWIN:
+ /* For fs installation under Windows (syslinux.exe) */
+ fprintf(stderr,
+ "Usage: %s [options] <drive>: [bootsecfile]\n"
+ " --directory -d Directory for installation target\n",
+ program);
+ break;
}
fprintf(stderr,
" --install -i Install over the current bootsector\n"
- " --update -U Update a previous EXTLINUX installation\n"
+ " --update -U Update a previous installation\n"
" --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"
@@ -95,17 +109,22 @@ void __attribute__ ((noreturn)) usage(int rv, enum syslinux_mode mode)
" --raid -r Fall back to the next device on boot failure\n"
" --once=... %s Execute a command once upon boot\n"
" --clear-once -O Clear the boot-once command\n"
- " --reset-adv Reset auxilliary data\n"
- " --menu-save= -M Set the label to select as default on the next boot\n"
- "\n"
- " Note: geometry is determined at boot time for devices which\n"
- " are considered hard disks by the BIOS. Unfortunately, this is\n"
- " not possible for devices which are considered floppy disks,\n"
- " which includes zipdisks and LS-120 superfloppies.\n"
- "\n"
- " The -z option is useful for USB devices which are considered\n"
- " hard disks by some BIOSes and zipdrives by other BIOSes.\n",
- mode == MODE_SYSLINUX ? " " : "-o");
+ " --reset-adv Reset auxilliary data\n",
+ mode == MODE_SYSLINUX ? " " : "-o");
+ /*
+ * Have to chop this roughly in half for the DOS installer due
+ * to limited output buffer size
+ */
+ fprintf(stderr,
+ " --menu-save= -M Set the label to select as default on the next boot\n");
+ if (mode == MODE_SYSLINUX_DOSWIN)
+ fprintf(stderr,
+ " --mbr -m Install an MBR\n"
+ " --active -a Mark partition as active\n");
+
+ if (mode == MODE_SYSLINUX_DOSWIN || mode == MODE_SYSLINUX)
+ fprintf(stderr,
+ " --force -f Ignore precautions\n");
exit(rv);
}
@@ -119,6 +138,7 @@ void parse_options(int argc, char *argv[], enum syslinux_mode mode)
long_options, NULL)) != EOF) {
switch (o) {
case 'f':
+ opt.force = 1;
break;
case 'z':
opt.heads = 64;
@@ -183,6 +203,12 @@ void parse_options(int argc, char *argv[], enum syslinux_mode mode)
case 'M':
opt.menu_save = optarg;
break;
+ case 'm':
+ opt.install_mbr = 1;
+ break;
+ case 'a':
+ opt.activate_partition = 1;
+ break;
case 'v':
fprintf(stderr,
"%s " VERSION_STR " Copyright 1994-" YEAR_STR
@@ -196,6 +222,7 @@ void parse_options(int argc, char *argv[], enum syslinux_mode mode)
switch (mode) {
case MODE_SYSLINUX:
+ case MODE_SYSLINUX_DOSWIN:
opt.device = argv[optind++];
break;
case MODE_EXTLINUX:
@@ -204,6 +231,9 @@ void parse_options(int argc, char *argv[], enum syslinux_mode mode)
break;
}
+ if (argv[optind] && (mode == MODE_SYSLINUX_DOSWIN))
+ /* Allow for the boot-sector argument */
+ opt.bootsecfile = argv[optind++];
if (argv[optind])
usage(EX_USAGE, mode); /* Excess arguments */
}
diff --git a/libinstaller/syslxopt.h b/libinstaller/syslxopt.h
index 446ab9af..bcbe0352 100644
--- a/libinstaller/syslxopt.h
+++ b/libinstaller/syslxopt.h
@@ -14,6 +14,10 @@ struct sys_options {
const char *device;
unsigned int offset;
const char *menu_save;
+ int force;
+ int install_mbr;
+ int activate_partition;
+ const char *bootsecfile;
};
enum long_only_opt {
@@ -25,6 +29,7 @@ enum long_only_opt {
enum syslinux_mode {
MODE_SYSLINUX, /* Unmounted filesystem */
MODE_EXTLINUX,
+ MODE_SYSLINUX_DOSWIN,
};
void __attribute__ ((noreturn)) usage(int rv, enum syslinux_mode mode);
diff --git a/linux/syslinux.c b/linux/syslinux.c
index 9462138f..97b6a306 100644..100755
--- a/linux/syslinux.c
+++ b/linux/syslinux.c
@@ -273,7 +273,7 @@ int main(int argc, char *argv[])
subdir = "/";
}
- if (!opt.device)
+ if (!opt.device || opt.install_mbr || opt.activate_partition)
usage(EX_USAGE, MODE_SYSLINUX);
/*
diff --git a/man/syslinux.1 b/man/syslinux.1
index 1729ddd4..6babfa41 100644
--- a/man/syslinux.1
+++ b/man/syslinux.1
@@ -1,11 +1,9 @@
-.TH SYSLINUX 1 "18 December 2007" "SYSLINUX"
+.TH SYSLINUX 1 "19 July 2010" "SYSLINUX"
.SH NAME
syslinux \- install the \s-1SYSLINUX\s+1 bootloader on a FAT filesystem
.SH SYNOPSIS
.B syslinux
-[\fB\-sfr\fP]
-[\fB\-d\fP \fIdirectory\fP]
-[\fB\-o\fP \fIoffset\fP]
+[\fBOPTIONS\fP]
.I device
.SH DESCRIPTION
\fBSyslinux\fP is a boot loader for the Linux operating system which
@@ -17,10 +15,11 @@ In order to create a bootable Linux floppy using \fBSyslinux\fP, prepare a
normal MS-DOS formatted floppy. Copy one or more Linux kernel files to
it, then execute the command:
.IP
-.B syslinux /dev/fd0
+.B syslinux \-\-install /dev/fd0
.PP
This will alter the boot sector on the disk and copy a file named
-LDLINUX.SYS into its root directory.
+.I ldlinux.sys
+into its root directory.
.PP
On boot time, by default, the kernel will be loaded from the image named
LINUX on the boot floppy. This default can be changed, see the section
@@ -29,52 +28,79 @@ on the \fBsyslinux\fP configuration file.
If the Shift or Alt keys are held down during boot, or the Caps or Scroll
locks are set, \fBsyslinux\fP will display a
.BR lilo (8)
--style "boot:" prompt. The user can then type a kernel file name followed by
-any kernel parameters. The \fBsyslinux\fP loader does not need to know about the
-kernel file in advance; all that is required is that it is a file located in
-the root directory on the disk.
+-style "boot:" prompt. The user can then type a kernel file name
+followed by any kernel parameters. The \s-1SYSLINUX\s+1 bootloader
+does not need to know about the kernel file in advance; all that is
+required is that it is a file located in the root directory on the
+disk.
.PP
\fBSyslinux\fP supports the loading of initial ramdisks (initrd) and the
bzImage kernel format.
.SH OPTIONS
.TP
-.B \-s
-Install a "safe, slow and stupid" version of \fBsyslinux\fP. This version may
-work on some very buggy BIOSes on which \fBsyslinux\fP would otherwise fail.
+\fB\-i\fP, \fB\-\-install\fP
+Install \s-1SYSLINUX\s+1 on a new medium, overwriting any previously
+installed bootloader.
+.TP
+\fB\-U\fP, \fB\-\-update\fP
+Install \s-1SYSLINUX\s+1 on a new medium if and only if a version of
+\s-1SYSLINUX\s+1 is already installed.
+.TP
+\fB\-s\fP, \fB\-\-stupid\fP
+Install a "safe, slow and stupid" version of \s-1SYSLINUX\s+1. This version may
+work on some very buggy BIOSes on which \s-1SYSLINUX\s+1 would otherwise fail.
If you find a machine on which the \-s option is required to make it boot
reliably, please send as much info about your machine as you can, and include
the failure mode.
.TP
-.B \-f
+\fB\-f\fP, \fB\-\-force\fP
Force install even if it appears unsafe.
.TP
-.B \-r
+\fB\-r\fP, \fB\-\-raid\fB
RAID mode. If boot fails, tell the BIOS to boot the next device in
the boot sequence (usually the next hard disk) instead of stopping
with an error message. This is useful for RAID-1 booting.
.TP
-\fB\-d\fP \fIsubdirectory\fP
+\fB\-d\fP, \fB\-\-directory\fP \fIsubdirectory\fP
Install the \s-1SYSLINUX\s+1 control files in a subdirectory with the
specified name (relative to the root directory on the device).
.TP
-\fB\-o\fP \fIoffset\fP
+\fB\-t\fP, \fB\-\-offset\fP \fIoffset\fP
Indicates that the filesystem is at an offset from the base of the
device or file.
+.TP
+\fB\-\-once\fP \fIcommand\fP
+Declare a boot command to be tried on the first boot only.
+.TP
+\fB\-O\fP, \fB\-\-clear-once\fP
+Clear the boot-once command.
+.TP
+\fB\-H\fP, \fB\-\-heads\fP \fIhead-count\fP
+Override the detected number of heads for the geometry.
+.TP
+\fB\-S\fP, \fB\-\-sectors\fP \fIsector-count\fP
+Override the detected number of sectors for the geometry.
+.TP
+\fB\-z\fP, \fB\-\-zipdrive\fP
+Assume zipdrive geometry (\fI\-\-heads 64 \-\-sectors 32).
.SH FILES
.SS "Configuration file"
-All the configurable defaults in \fBsyslinux\fP can be changed by putting a
+All the configurable defaults in \s-1SYSLINUX\s+1 can be changed by putting a
file called
.B syslinux.cfg
-in the root directory of the boot floppy. This
+in the install directory of the boot disk. This
is a text file in either UNIX or DOS format, containing one or more of
the following items (case is insensitive for keywords).
.PP
+This list is out of date.
+.PP
In the configuration file blank lines and comment lines beginning
with a hash mark (#) are ignored.
.TP
\fBdefault\fP \fIkernel\fP [ \fIoptions ...\fP ]
-Sets the default command line. If \fBsyslinux\fP boots automatically, it will act
-just as if the entries after "default" had been typed in at the "boot:" prompt.
+Sets the default command line. If \fBsyslinux\fP boots automatically,
+it will act just as if the entries after "default" had been typed in
+at the "boot:" prompt.
.IP
If no DEFAULT or UI statement is found, or the configuration file is missing
entirely, \s-1SYSLINUX\s+1 drops to the boot: prompt with an error message (if
diff --git a/mtools/Makefile b/mtools/Makefile
index 70bed14c..6164d24c 100644..100755
--- a/mtools/Makefile
+++ b/mtools/Makefile
@@ -9,6 +9,7 @@ LDFLAGS = -s
SRCS = syslinux.c \
../libinstaller/fat.c \
../libinstaller/syslxmod.c \
+ ../libinstaller/syslxopt.c \
../libinstaller/setadv.c \
../libinstaller/bootsect_bin.c \
../libinstaller/ldlinux_bin.c \
diff --git a/mtools/syslinux.c b/mtools/syslinux.c
index 76cd2ca4..ac189c61 100644..100755
--- a/mtools/syslinux.c
+++ b/mtools/syslinux.c
@@ -23,12 +23,14 @@
#include <alloca.h>
#include <errno.h>
#include <fcntl.h>
+#include <getopt.h>
#include <inttypes.h>
#include <mntent.h>
#include <paths.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <sysexits.h>
#include <syslog.h>
#include <unistd.h>
#include <sys/types.h>
@@ -38,18 +40,10 @@
#include "syslinux.h"
#include "libfat.h"
#include "setadv.h"
+#include "syslxopt.h"
char *program; /* Name of program */
-char *device; /* Device to install to */
pid_t mypid;
-off_t filesystem_offset = 0; /* Offset of filesystem */
-
-void __attribute__ ((noreturn)) usage(void)
-{
- fprintf(stderr, "Usage: %s [-sfr][-d directory][-o offset] device\n",
- program);
- exit(1);
-}
void __attribute__ ((noreturn)) die(const char *msg)
{
@@ -126,7 +120,7 @@ ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset)
int libfat_xpread(intptr_t pp, void *buf, size_t secsize,
libfat_sector_t sector)
{
- off_t offset = (off_t) sector * secsize + filesystem_offset;
+ off_t offset = (off_t) sector * secsize + opt.offset;
return xpread(pp, buf, secsize, offset);
}
@@ -136,10 +130,8 @@ int main(int argc, char *argv[])
int dev_fd;
struct stat st;
int status;
- char **argp, *opt;
const char *tmpdir;
char *mtools_conf;
- const char *subdir = NULL;
int mtc_fd;
FILE *mtc, *mtp;
struct libfat_filesystem *fs;
@@ -151,48 +143,23 @@ int main(int argc, char *argv[])
int ldlinux_sectors, patch_sectors;
int i;
- int force = 0; /* -f (force) option */
- int stupid = 0; /* -s (stupid) option */
- int raid_mode = 0; /* -r (RAID) option */
-
(void)argc; /* Unused */
mypid = getpid();
program = argv[0];
- device = NULL;
-
- for (argp = argv + 1; *argp; argp++) {
- if (**argp == '-') {
- opt = *argp + 1;
- if (!*opt)
- usage();
-
- while (*opt) {
- if (*opt == 's') {
- stupid = 1;
- } else if (*opt == 'r') {
- raid_mode = 1;
- } else if (*opt == 'f') {
- force = 1; /* Force install */
- } else if (*opt == 'd' && argp[1]) {
- subdir = *++argp;
- } else if (*opt == 'o' && argp[1]) {
- filesystem_offset = (off_t) strtoull(*++argp, NULL, 0); /* Byte offset */
- } else {
- usage();
- }
- opt++;
- }
- } else {
- if (device)
- usage();
- device = *argp;
- }
- }
+ parse_options(argc, argv, MODE_SYSLINUX);
- if (!device)
- usage();
+ if (!opt.device)
+ usage(EX_USAGE, MODE_SYSLINUX);
+
+ if (opt.sectors || opt.heads || opt.reset_adv || opt.set_once
+ || (opt.update_only > 0) || opt.menu_save) {
+ fprintf(stderr,
+ "At least one specified option not yet implemented"
+ " for this installer.\n");
+ exit(1);
+ }
/*
* Temp directory of choice...
@@ -212,20 +179,20 @@ int main(int argc, char *argv[])
* First make sure we can open the device at all, and that we have
* read/write permission.
*/
- dev_fd = open(device, O_RDWR);
+ dev_fd = open(opt.device, O_RDWR);
if (dev_fd < 0 || fstat(dev_fd, &st) < 0) {
- die_err(device);
+ die_err(opt.device);
exit(1);
}
- if (!force && !S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode)) {
+ if (!opt.force && !S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode)) {
fprintf(stderr,
"%s: not a block device or regular file (use -f to override)\n",
- device);
+ opt.device);
exit(1);
}
- xpread(dev_fd, sectbuf, SECTOR_SIZE, filesystem_offset);
+ xpread(dev_fd, sectbuf, SECTOR_SIZE, opt.offset);
/*
* Check to see that what we got was indeed an MS-DOS boot sector/superblock
@@ -253,7 +220,8 @@ int main(int argc, char *argv[])
" file=\"/proc/%lu/fd/%d\"\n"
" offset=%llu\n",
(unsigned long)mypid,
- dev_fd, (unsigned long long)filesystem_offset);
+ dev_fd, (unsigned long long)opt.offset);
+
if (ferror(mtc) || fclose(mtc))
die_err(mtools_conf);
@@ -303,24 +271,25 @@ int main(int argc, char *argv[])
libfat_close(fs);
/* Patch ldlinux.sys and the boot sector */
- i = syslinux_patch(sectors, nsectors, stupid, raid_mode, subdir, NULL);
+ i = syslinux_patch(sectors, nsectors, opt.stupid_mode, opt.raid_mode,
+ opt.directory, NULL);
patch_sectors = (i + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
/* Write the now-patched first sectors of ldlinux.sys */
for (i = 0; i < patch_sectors; i++) {
xpwrite(dev_fd, syslinux_ldlinux + i * SECTOR_SIZE, SECTOR_SIZE,
- filesystem_offset + ((off_t) sectors[i] << SECTOR_SHIFT));
+ opt.offset + ((off_t) sectors[i] << SECTOR_SHIFT));
}
/* Move ldlinux.sys to the desired location */
- if (subdir) {
+ if (opt.directory) {
char target_file[4096], command[5120];
char *cp = target_file, *ep = target_file + sizeof target_file - 16;
const char *sd;
int slash = 1;
cp += sprintf(cp, "'s:/");
- for (sd = subdir; *sd; sd++) {
+ for (sd = opt.directory; *sd; sd++) {
if (*sd == '/' || *sd == '\\') {
if (slash)
continue; /* Remove duplicated slashes */
@@ -384,13 +353,13 @@ int main(int argc, char *argv[])
*/
/* Read the superblock again since it might have changed while mounted */
- xpread(dev_fd, sectbuf, SECTOR_SIZE, filesystem_offset);
+ xpread(dev_fd, sectbuf, SECTOR_SIZE, opt.offset);
/* Copy the syslinux code into the boot sector */
syslinux_make_bootsect(sectbuf);
/* Write new boot sector */
- xpwrite(dev_fd, sectbuf, SECTOR_SIZE, filesystem_offset);
+ xpwrite(dev_fd, sectbuf, SECTOR_SIZE, opt.offset);
close(dev_fd);
sync();
diff --git a/sample/Makefile b/sample/Makefile
index 9fa21c2a..f1006ff9 100644
--- a/sample/Makefile
+++ b/sample/Makefile
@@ -15,40 +15,10 @@
##
topdir = ..
-include $(topdir)/MCONFIG.embedded
-
-INCLUDES = -I$(com32)/include
PPMTOLSS16 = $(topdir)/utils/ppmtolss16
-LIBGCC := $(shell $(CC) $(GCCOPT) --print-libgcc)
-LIB = liboldcom32.a
-
-LIBOBJS = conio.o atou.o skipatou.o printf.o c32exit.o
-
-com32 = $(topdir)/com32
-C_LIBS = $(com32)/libutil/libutil_com.a $(com32)/lib/libcom32.a $(LIBGCC)
-LDFLAGS = -m elf_i386 -T $(com32)/lib/com32.ld
-
-all: syslogo.lss comecho.com hello.c32 hello2.c32 filetest.c32 c32echo.c32 \
- fd.c32 $(LIB)
-
-.PRECIOUS: %.o
-
-.PRECIOUS: %.elf
-%.elf: c32entry.o %.o $(LIB)
- $(LD) -Ttext 0x101000 -e _start -o $@ $^
-
-%.c32: %.elf
- $(OBJCOPY) -O binary $< $@
-
-%.com: %.asm
- ( $(NASM) -M -DDEPEND -o $@ $< ; echo '' ) > .$@.d ; true
- $(NASM) $(NASMOPT) -f bin -o $@ -l $*.lst $<
-$(LIB): $(LIBOBJS)
- rm -f $@
- $(AR) cq $@ $^
- $(RANLIB) $@
+all: syslogo.lss
%.lss: %.ppm.gz $(PPMTOLSS16)
$(GZIPPROG) -cd $< | \
@@ -61,9 +31,8 @@ $(LIB): $(LIBOBJS)
tidy dist:
rm -f *.o *.a *.lst *.elf .*.d
-# Don't specify *.com since mdiskchk.com can't be built using Linux tools
clean: tidy
- rm -f *.lss *.o *.c32 comecho.com
+ rm -f *.lss *.o *.c32 *.com
spotless: clean
diff --git a/sample/README b/sample/README
deleted file mode 100644
index 0a053f56..00000000
--- a/sample/README
+++ /dev/null
@@ -1,6 +0,0 @@
-This directory contains files intended to be used as sample code.
-This includes COMBOOT, COM32, and MS-DOS programs as well as LSS
-icons.
-
-For developing COM32 programs, you probably want to use the new com32
-toolkit (libcom32 and libutil), available in the com32 directory.
diff --git a/sample/atou.c b/sample/atou.c
deleted file mode 100644
index 73b0bb79..00000000
--- a/sample/atou.c
+++ /dev/null
@@ -1,12 +0,0 @@
-static inline int isdigit(int ch)
-{
- return (ch >= '0') && (ch <= '9');
-}
-
-unsigned int atou(const char *s)
-{
- unsigned int i = 0;
- while (isdigit(*s))
- i = i * 10 + (*s++ - '0');
- return i;
-}
diff --git a/sample/c32echo.c b/sample/c32echo.c
deleted file mode 100644
index cfde885d..00000000
--- a/sample/c32echo.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2002-2008 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.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * c32echo.c
- *
- * Simple COM32 program which only prints out its own command line
- */
-
-#include <com32.h>
-
-#define NULL ((void *)0)
-
-static inline void memset(void *buf, int ch, unsigned int len)
-{
- asm volatile ("cld; rep; stosb":"+D" (buf), "+c"(len):"a"(ch):"memory");
-}
-
-int __start(void)
-{
- com32sys_t inreg;
- const char *p;
-
- memset(&inreg, 0, sizeof inreg);
- inreg.eax.b[1] = 0x02; /* Write Character */
-
- for (p = __com32.cs_cmdline; *p; p++) {
- inreg.edx.b[0] = *p;
- __com32.cs_intcall(0x21, &inreg, NULL);
- }
-
- inreg.edx.b[0] = '\r';
- __com32.cs_intcall(0x21, &inreg, NULL);
- inreg.edx.b[0] = '\n';
- __com32.cs_intcall(0x21, &inreg, NULL);
-
- return 0;
-}
diff --git a/sample/c32entry.S b/sample/c32entry.S
deleted file mode 100644
index 2e40c58b..00000000
--- a/sample/c32entry.S
+++ /dev/null
@@ -1,66 +0,0 @@
-# -----------------------------------------------------------------------
-#
-# Copyright 2003-2008 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.
-#
-# -----------------------------------------------------------------------
-
-# COM32 start up code - must be linked first in the binary
-
-
- .section ".text","ax"
- .globl _start
-_start:
- # This first instruction acts as COM32 magic number
- movl $0x21cd4cff,%eax
-
- # Upwards string operations
- cld
-
- # Zero the .bss segment
- xorl %eax,%eax
- movl $__bss_start,%edi # Symbol provided by linker
- movl $_end+3,%ecx # Symbol provided by linker
- subl %edi,%ecx
- shrl $2,%ecx
- rep ; stosl
-
- # Copy COM32 invocation parameters
- leal 4(%esp),%esi # Argument list
- movl $__com32,%edi
- movl $6,%ecx
- movl %esp,-4(%edi) # Save the initial stack ptr
- cmpl (%esi),%ecx
- jbe 1f
- movl (%esi),%ecx
-1: rep ; movsl
-
- # Run program; we call this __start rather than main since we
- # did not parse the command line or anything like that.
- jmp __start
-
- .section ".bss","aw"
- .globl __entry_esp
-__entry_esp: .space 4
- .globl __com32
-__com32: .space 4*6
diff --git a/sample/c32exit.S b/sample/c32exit.S
deleted file mode 100644
index 5c5ba030..00000000
--- a/sample/c32exit.S
+++ /dev/null
@@ -1,10 +0,0 @@
-# $Id#
-#
-# Implementation of exit() for com32 based on c32entry.S
-#
- .text
- .globl exit
-exit:
- movl 4(%esp),%eax # Exit code in %eax = return value
- movl (__entry_esp),%esp # Return stack pointer to entry value
- ret # Return to termination address
diff --git a/sample/comecho.asm b/sample/comecho.asm
deleted file mode 100644
index 7125686a..00000000
--- a/sample/comecho.asm
+++ /dev/null
@@ -1,32 +0,0 @@
-;
-; Simple COMBOOT program that just prints out its own command line.
-; This also works in DOS.
-;
-
- org 100h
-
-_start:
- xor cx,cx
- mov cl,[80h] ; Command line len
- mov si,81h ; Command line
-
- mov dl,"<"
- mov ah,02h
- int 21h
-
-.writechar:
- lodsb
- mov dl,al
- mov ah,02h
- int 21h
- loop .writechar
-
- mov dx,end_str
- mov ah,09h
- int 21h
-
- ; Exit with near return, INT 20h, or INT 21h AX=4C00h
- ret
-
-
-end_str db ">", 0Dh, 0Ah, "$"
diff --git a/sample/conio.c b/sample/conio.c
deleted file mode 100644
index e9660b98..00000000
--- a/sample/conio.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2001-2008 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.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * conio.c
- *
- * Output to the screen
- */
-
-#include <com32.h>
-#include <stdarg.h>
-
-#define NULL ((void *)0)
-
-static inline void memset(void *buf, int ch, unsigned int len)
-{
- asm volatile ("cld; rep; stosb":"+D" (buf), "+c"(len):"a"(ch):"memory");
-}
-
-int putchar(int ch)
-{
- com32sys_t regs;
-
- memset(&regs, 0, sizeof regs);
-
- if (ch == '\n') {
- /* \n -> \r\n */
- putchar('\r');
- }
-
- regs.eax.b[1] = 0x02;
- regs.edx.b[0] = ch;
- __com32.cs_intcall(0x21, &regs, NULL);
-
- return ch;
-}
-
-/* Note: doesn't put '\n' like the stdc version does */
-int puts(const char *s)
-{
- int count = 0;
-
- while (*s) {
- putchar(*s);
- count++;
- s++;
- }
-
- return count;
-}
diff --git a/sample/fd.c b/sample/fd.c
deleted file mode 100644
index a1b1a51c..00000000
--- a/sample/fd.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2003-2008 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.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * fd.c
- *
- * Chainload a floppy disk (currently rather braindead.)
- */
-
-#include <com32.h>
-#define NULL ((void *)0)
-
-int printf(const char *, ...);
-unsigned int atou(const char *);
-
-int __start(void)
-{
- int whichfd = atou(__com32.cs_cmdline);
- static com32sys_t inreg, outreg; /* In bss, so zeroed automatically */
- int retry;
-
- for (retry = 0; retry < 6; retry++) {
- printf(">");
- inreg.eax.w[0] = 0x0201; /* Read one sector */
- inreg.ecx.w[0] = 0x0001; /* Cyl 0 sector 1 */
- inreg.edx.b[1] = 0; /* Head 0 */
- inreg.edx.b[0] = whichfd; /* Drive number */
- inreg.es = SEG(__com32.cs_bounce); /* Read into the bounce buffer */
- inreg.ebx.w[0] = OFFS(__com32.cs_bounce);
- __com32.cs_intcall(0x13, &inreg, &outreg);
-
- if ((outreg.eflags.l & 1) == 0)
- break;
- }
-
- if ((outreg.eflags.l & 1) == 0) {
- printf("!\n");
- inreg.eax.w[0] = 0x000d;
- inreg.edx.w[0] = 0;
- inreg.edi.l = (uint32_t) __com32.cs_bounce;
- inreg.ecx.l = 512;
- inreg.ebx.l = whichfd & 0xff;
- inreg.esi.l = 0; /* No partitions */
- inreg.ds = 0; /* No partitions */
- __com32.cs_intcall(0x22, &inreg, NULL);
- }
-
- /* If we get here, badness happened */
- return 255;
-}
diff --git a/sample/filetest.c b/sample/filetest.c
deleted file mode 100644
index 2ef772a1..00000000
--- a/sample/filetest.c
+++ /dev/null
@@ -1,97 +0,0 @@
-#include <com32.h>
-#include <stdarg.h>
-
-#define NULL ((void *)0)
-int printf(const char *, ...);
-int putchar(int);
-
-static inline void memset(void *buf, int ch, unsigned int len)
-{
- asm volatile ("cld; rep; stosb":"+D" (buf), "+c"(len):"a"(ch):"memory");
-}
-
-static void strcpy(char *dst, const char *src)
-{
- while (*src)
- *dst++ = *src++;
-
- *dst = '\0';
-}
-
-static void printregs(const com32sys_t * r)
-{
- printf("eflags = %08x ds = %04x es = %04x fs = %04x gs = %04x\n"
- "eax = %08x ebx = %08x ecx = %08x edx = %08x\n"
- "ebp = %08x esi = %08x edi = %08x esp = %08x\n",
- r->eflags.l, r->ds, r->es, r->fs, r->gs,
- r->eax.l, r->ebx.l, r->ecx.l, r->edx.l,
- r->ebp.l, r->esi.l, r->edi.l, r->_unused_esp.l);
-}
-
-int __start(void)
-{
- unsigned int ax, cx, si, t;
- com32sys_t inreg, outreg;
- char *p;
-
- /* Test null system call */
- inreg.eflags.l = 0xffffffff;
- inreg.eax.l = 0x11110000;
- inreg.ecx.l = 0x22222222;
- inreg.edx.l = 0x33333333;
- inreg.ebx.l = 0x44444444;
- inreg.ebp.l = 0x55555555;
- inreg.esi.l = 0x66666666;
- inreg.edi.l = 0x77777777;
- inreg.ds = 0xaaaa;
- inreg.es = 0xbbbb;
- inreg.fs = 0xcccc;
- inreg.gs = 0xdddd;
- printregs(&inreg);
- __com32.cs_intcall(0x22, &inreg, &outreg);
- printregs(&outreg);
- printf("----\n");
-
- memset(&inreg, 0, sizeof inreg);
- memset(&outreg, 0, sizeof outreg);
- strcpy(__com32.cs_bounce, "test.txt");
- inreg.eax.w[0] = 0x0006; // Open file
- inreg.esi.w[0] = OFFS(__com32.cs_bounce);
- inreg.es = SEG(__com32.cs_bounce);
- printregs(&inreg);
- __com32.cs_intcall(0x22, &inreg, &outreg);
- printregs(&outreg);
- printf("----\n");
-
- si = outreg.esi.w[0]; /* File handle */
- cx = outreg.ecx.w[0]; /* Block size */
- ax = outreg.eax.l; /* File length */
-
- while (si) {
- /* We can only read 64K per call */
- t = (ax > 65536) ? 65536 / cx : (ax + cx - 1) / cx;
-
- memset(&inreg, 0, sizeof inreg);
- inreg.esi.w[0] = si;
- inreg.ecx.w[0] = t; /* Block count */
- inreg.eax.w[0] = 0x0007; // Read file
- inreg.ebx.w[0] = OFFS(__com32.cs_bounce);
- inreg.es = SEG(__com32.cs_bounce);
- printregs(&inreg);
- __com32.cs_intcall(0x22, &inreg, &outreg);
- printregs(&outreg);
- printf("----\n");
- si = outreg.esi.w[0];
-
- /* Print the buffer */
- t = (ax < 65536) ? ax : 65536;
- p = __com32.cs_bounce;
- while (t) {
- putchar(*p++);
- t--;
- ax--;
- }
- }
-
- return 0;
-}
diff --git a/sample/hello.c b/sample/hello.c
deleted file mode 100644
index 25ceb8bb..00000000
--- a/sample/hello.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2002-2008 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.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * hello.c
- *
- * Simple COM32 image
- */
-
-#include <com32.h>
-
-#define NULL ((void *)0)
-
-static inline void memset(void *buf, int ch, unsigned int len)
-{
- asm volatile ("cld; rep; stosb":"+D" (buf), "+c"(len):"a"(ch):"memory");
-}
-
-int __start(void)
-{
- const char *msg = "Hello, World!\r\n";
- com32sys_t inreg;
- const char *p;
-
- memset(&inreg, 0, sizeof inreg);
-
- for (p = msg; *p; p++) {
- inreg.edx.b[0] = *p;
- inreg.eax.b[1] = 0x02; /* Write Character */
- __com32.cs_intcall(0x21, &inreg, NULL);
- }
-
- return 0;
-}
diff --git a/sample/hello2.c b/sample/hello2.c
deleted file mode 100644
index e8920112..00000000
--- a/sample/hello2.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2002-2008 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.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * hello2.c
- *
- * Simple COM32 image
- *
- * This version shows how to use the bounce buffer for data transfer
- * to the BIOS or COMBOOT system calls.
- */
-
-#include <com32.h>
-
-#define NULL ((void *)0)
-
-static inline void memset(void *buf, int ch, unsigned int len)
-{
- asm volatile ("cld; rep; stosb":"+D" (buf), "+c"(len):"a"(ch):"memory");
-}
-
-static void strcpy(char *dst, const char *src)
-{
- while (*src)
- *dst++ = *src++;
-
- *dst = '\0';
-}
-
-static void writemsg(const char *msg)
-{
- com32sys_t inreg;
-
- memset(&inreg, 0, sizeof inreg);
-
- strcpy(__com32.cs_bounce, msg);
- inreg.eax.w[0] = 0x0002; /* Write string */
- inreg.ebx.w[0] = OFFS(__com32.cs_bounce);
- inreg.es = SEG(__com32.cs_bounce);
- __com32.cs_intcall(0x22, &inreg, NULL);
-};
-
-int __start(void)
-{
- writemsg("Hello, World!\r\n" "cmdline = ");
- writemsg(__com32.cs_cmdline);
- writemsg("\r\n");
- return 0;
-}
diff --git a/sample/printf.c b/sample/printf.c
deleted file mode 100644
index 6b7dda24..00000000
--- a/sample/printf.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Oh, it's a waste of space, but oh-so-yummy for debugging. It's just
- * initialization code anyway, so it doesn't take up space when we're
- * actually running. This version of printf() does not include 64-bit
- * support. "Live with it."
- *
- * Most of this code was shamelessly snarfed from the Linux kernel, then
- * modified.
- *
- * FIX THIS: Replace printf() implementation with BSD/MIT-licensed one
- * from klibc
- */
-
-#include <stdarg.h>
-
-int puts(const char *);
-
-static inline int isdigit(int ch)
-{
- return (ch >= '0') && (ch <= '9');
-}
-
-unsigned int skip_atou(const char **s);
-unsigned int atou(const char *s);
-
-static int strnlen(const char *s, int maxlen)
-{
- const char *es = s;
- while (*es && maxlen) {
- es++;
- maxlen--;
- }
-
- return (es - s);
-}
-
-#define ZEROPAD 1 /* pad with zero */
-#define SIGN 2 /* unsigned/signed long */
-#define PLUS 4 /* show plus */
-#define SPACE 8 /* space if plus */
-#define LEFT 16 /* left justified */
-#define SPECIAL 32 /* 0x */
-#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
-
-#define do_div(n,base) ({ \
-int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
-__res; })
-
-static char *number(char *str, long num, int base, int size, int precision,
- int type)
-{
- char c, sign, tmp[66];
- const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
- int i;
-
- if (type & LARGE)
- digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- if (type & LEFT)
- type &= ~ZEROPAD;
- if (base < 2 || base > 36)
- return 0;
- c = (type & ZEROPAD) ? '0' : ' ';
- sign = 0;
- if (type & SIGN) {
- if (num < 0) {
- sign = '-';
- num = -num;
- size--;
- } else if (type & PLUS) {
- sign = '+';
- size--;
- } else if (type & SPACE) {
- sign = ' ';
- size--;
- }
- }
- if (type & SPECIAL) {
- if (base == 16)
- size -= 2;
- else if (base == 8)
- size--;
- }
- i = 0;
- if (num == 0)
- tmp[i++] = '0';
- else
- while (num != 0)
- tmp[i++] = digits[do_div(num, base)];
- if (i > precision)
- precision = i;
- size -= precision;
- if (!(type & (ZEROPAD + LEFT)))
- while (size-- > 0)
- *str++ = ' ';
- if (sign)
- *str++ = sign;
- if (type & SPECIAL) {
- if (base == 8)
- *str++ = '0';
- else if (base == 16) {
- *str++ = '0';
- *str++ = digits[33];
- }
- }
- if (!(type & LEFT))
- while (size-- > 0)
- *str++ = c;
- while (i < precision--)
- *str++ = '0';
- while (i-- > 0)
- *str++ = tmp[i];
- while (size-- > 0)
- *str++ = ' ';
- return str;
-}
-
-/* Forward decl. needed for IP address printing stuff... */
-int sprintf(char *buf, const char *fmt, ...);
-
-int vsprintf(char *buf, const char *fmt, va_list args)
-{
- int len;
- unsigned long num;
- int i, base;
- char *str;
- const char *s;
-
- int flags; /* flags to number() */
-
- int field_width; /* width of output field */
- int precision; /* min. # of digits for integers; max
- number of chars for from string */
- int qualifier; /* 'h', 'l', or 'L' for integer fields */
-
- for (str = buf; *fmt; ++fmt) {
- if (*fmt != '%') {
- *str++ = *fmt;
- continue;
- }
-
- /* process flags */
- flags = 0;
-repeat:
- ++fmt; /* this also skips first '%' */
- switch (*fmt) {
- case '-':
- flags |= LEFT;
- goto repeat;
- case '+':
- flags |= PLUS;
- goto repeat;
- case ' ':
- flags |= SPACE;
- goto repeat;
- case '#':
- flags |= SPECIAL;
- goto repeat;
- case '0':
- flags |= ZEROPAD;
- goto repeat;
- }
-
- /* get field width */
- field_width = -1;
- if (isdigit(*fmt))
- field_width = skip_atou(&fmt);
- else if (*fmt == '*') {
- ++fmt;
- /* it's the next argument */
- field_width = va_arg(args, int);
- if (field_width < 0) {
- field_width = -field_width;
- flags |= LEFT;
- }
- }
-
- /* get the precision */
- precision = -1;
- if (*fmt == '.') {
- ++fmt;
- if (isdigit(*fmt))
- precision = skip_atou(&fmt);
- else if (*fmt == '*') {
- ++fmt;
- /* it's the next argument */
- precision = va_arg(args, int);
- }
- if (precision < 0)
- precision = 0;
- }
-
- /* get the conversion qualifier */
- qualifier = -1;
- if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
- qualifier = *fmt;
- ++fmt;
- }
-
- /* default base */
- base = 10;
-
- switch (*fmt) {
- case 'c':
- if (!(flags & LEFT))
- while (--field_width > 0)
- *str++ = ' ';
- *str++ = (unsigned char)va_arg(args, int);
- while (--field_width > 0)
- *str++ = ' ';
- continue;
-
- case 's':
- s = va_arg(args, char *);
- len = strnlen(s, precision);
-
- if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = ' ';
- for (i = 0; i < len; ++i)
- *str++ = *s++;
- while (len < field_width--)
- *str++ = ' ';
- continue;
-
- case 'p':
- if (field_width == -1) {
- field_width = 2 * sizeof(void *);
- flags |= ZEROPAD;
- }
- str = number(str,
- (unsigned long)va_arg(args, void *), 16,
- field_width, precision, flags);
- continue;
-
- case 'n':
- if (qualifier == 'l') {
- long *ip = va_arg(args, long *);
- *ip = (str - buf);
- } else {
- int *ip = va_arg(args, int *);
- *ip = (str - buf);
- }
- continue;
-
- case '%':
- *str++ = '%';
- continue;
-
- /* integer number formats - set up the flags and "break" */
- case 'o':
- base = 8;
- break;
-
- case 'X':
- flags |= LARGE;
- case 'x':
- base = 16;
- break;
-
- case 'd':
- case 'i':
- flags |= SIGN;
- case 'u':
- break;
-
- default:
- *str++ = '%';
- if (*fmt)
- *str++ = *fmt;
- else
- --fmt;
- continue;
- }
- if (qualifier == 'l')
- num = va_arg(args, unsigned long);
- else if (qualifier == 'h') {
- num = (unsigned short)va_arg(args, int);
- if (flags & SIGN)
- num = (short)num;
- } else if (flags & SIGN)
- num = va_arg(args, int);
- else
- num = va_arg(args, unsigned int);
- str = number(str, num, base, field_width, precision, flags);
- }
- *str = '\0';
- return str - buf;
-}
-
-int sprintf(char *buf, const char *fmt, ...)
-{
- va_list args;
- int i;
-
- va_start(args, fmt);
- i = vsprintf(buf, fmt, args);
- va_end(args);
- return i;
-}
-
-int printf(const char *fmt, ...)
-{
- char printf_buf[1024];
- va_list args;
- int printed;
-
- va_start(args, fmt);
- printed = vsprintf(printf_buf, fmt, args);
- va_end(args);
-
- puts(printf_buf);
-
- return printed;
-}
diff --git a/sample/skipatou.c b/sample/skipatou.c
deleted file mode 100644
index ea2dbadc..00000000
--- a/sample/skipatou.c
+++ /dev/null
@@ -1,13 +0,0 @@
-static inline int isdigit(int ch)
-{
- return (ch >= '0') && (ch <= '9');
-}
-
-unsigned int skip_atou(const char **s)
-{
- int i = 0;
-
- while (isdigit(**s))
- i = i * 10 + *((*s)++) - '0';
- return i;
-}
diff --git a/version b/version
index 0e60f145..1152a5aa 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-4.02 2010
+4.03 2010
diff --git a/win32/hello.c b/win/hello.c
index 4934689b..4934689b 100644
--- a/win32/hello.c
+++ b/win/hello.c
diff --git a/win/sysexits.h b/win/sysexits.h
new file mode 100644
index 00000000..483d3bab
--- /dev/null
+++ b/win/sysexits.h
@@ -0,0 +1 @@
+#define EX_USAGE 0x40
diff --git a/win32/syslinux.c b/win/syslinux.c
index ca98d78b..0e833d8d 100644
--- a/win32/syslinux.c
+++ b/win/syslinux.c
@@ -20,10 +20,13 @@
#include <windows.h>
#include <stdio.h>
#include <ctype.h>
+#include <getopt.h>
#include "syslinux.h"
#include "libfat.h"
#include "setadv.h"
+#include "sysexits.h"
+#include "syslxopt.h"
#ifdef __GNUC__
# define noreturn void __attribute__((noreturn))
@@ -43,12 +46,15 @@ void error(char *msg);
#define PART_ACTIVE 0x80
// The following struct should be in the ntddstor.h file, but I didn't have it.
-// TODO: Make this a conditional compilation
+// mingw32 has <ddk/ntddstor.h>, but including that file causes all kinds
+// of other failures. mingw64 has it in <winioctl.h>.
+#ifndef __x86_64__
typedef struct _STORAGE_DEVICE_NUMBER {
DEVICE_TYPE DeviceType;
ULONG DeviceNumber;
ULONG PartitionNumber;
} STORAGE_DEVICE_NUMBER, *PSTORAGE_DEVICE_NUMBER;
+#endif
BOOL GetStorageDeviceNumberByHandle(HANDLE handle,
const STORAGE_DEVICE_NUMBER * sdn)
@@ -168,7 +174,6 @@ BOOL FixMBR(int driveNum, int partitionNum, int write_mbr, int set_active)
/* End stuff for MBR code */
const char *program; /* Name of program */
-const char *drive; /* Drive to install to */
/*
* Check Windows version.
@@ -229,13 +234,6 @@ int libfat_readfile(intptr_t pp, void *buf, size_t secsize,
return secsize;
}
-noreturn usage(void)
-{
- fprintf(stderr,
- "Usage: syslinux.exe [-sfmar][-d directory] <drive>: [bootsecfile]\n");
- exit(1);
-}
-
int main(int argc, char *argv[])
{
HANDLE f_handle, d_handle;
@@ -245,7 +243,7 @@ int main(int argc, char *argv[])
UINT drive_type;
static unsigned char sectbuf[SECTOR_SIZE];
- char **argp, *opt;
+ char **argp;
static char drive_name[] = "\\\\.\\?:";
static char drive_root[] = "?:\\";
static char ldlinux_name[] = "?:\\ldlinux.sys";
@@ -256,16 +254,6 @@ int main(int argc, char *argv[])
int ldlinux_sectors;
uint32_t ldlinux_cluster;
int nsectors;
- const char *bootsecfile = NULL;
- const char *subdir = NULL;
-
- int force = 0; /* -f (force) option */
- int mbr = 0; /* -m (MBR) option */
- int setactive = 0; /* -a (set partition active) */
- int stupid = 0; /* -s (stupid) option */
- int raid_mode = 0; /* -r (RAID) option */
-
- (void)argc;
if (!checkver()) {
fprintf(stderr,
@@ -274,69 +262,36 @@ int main(int argc, char *argv[])
}
program = argv[0];
- drive = NULL;
-
- for (argp = argv + 1; *argp; argp++) {
- if (**argp == '-') {
- opt = *argp + 1;
- if (!*opt)
- usage();
-
- while (*opt) {
- switch (*opt) {
- case 's': /* Use "safe, slow and stupid" code */
- stupid = 1;
- break;
- case 'r': /* RAID mode */
- raid_mode = 1;
- break;
- case 'f': /* Force install */
- force = 1;
- break;
- case 'm': /* Install MBR */
- mbr = 1;
- break;
- case 'a': /* Mark this partition active */
- setactive = 1;
- break;
- case 'd':
- if (argp[1])
- subdir = *++argp;
- break;
- default:
- usage();
- break;
- }
- opt++;
- }
- } else {
- if (bootsecfile)
- usage();
- else if (drive)
- bootsecfile = *argp;
- else
- drive = *argp;
- }
- }
- if (!drive || !isalpha(drive[0]) || drive[1] != ':' || drive[2])
- usage();
+ parse_options(argc, argv, MODE_SYSLINUX_DOSWIN);
+
+ if (!opt.device || !isalpha(opt.device[0]) || opt.device[1] != ':'
+ || opt.device[2])
+ usage(EX_USAGE, MODE_SYSLINUX_DOSWIN);
+
+ if (opt.sectors || opt.heads || opt.reset_adv || opt.set_once
+ || (opt.update_only > 0) || opt.menu_save || opt.offset) {
+ fprintf(stderr,
+ "At least one specified option not yet implemented"
+ " for this installer.\n");
+ exit(1);
+ }
/* Test if drive exists */
drives = GetLogicalDrives();
- if (!(drives & (1 << (tolower(drive[0]) - 'a')))) {
- fprintf(stderr, "No such drive %c:\n", drive[0]);
+ if (!(drives & (1 << (tolower(opt.device[0]) - 'a')))) {
+ fprintf(stderr, "No such drive %c:\n", opt.device[0]);
exit(1);
}
/* Determines the drive type */
- drive_name[4] = drive[0];
- ldlinux_name[0] = drive[0];
- drive_root[0] = drive[0];
+ drive_name[4] = opt.device[0];
+ ldlinux_name[0] = opt.device[0];
+ drive_root[0] = opt.device[0];
drive_type = GetDriveType(drive_root);
/* Test for removeable media */
- if ((drive_type == DRIVE_FIXED) && (force == 0)) {
+ if ((drive_type == DRIVE_FIXED) && (opt.force == 0)) {
fprintf(stderr, "Not a removable drive (use -f to override) \n");
exit(1);
}
@@ -439,7 +394,7 @@ int main(int argc, char *argv[])
/*
* Patch ldlinux.sys and the boot sector
*/
- syslinux_patch(sectors, nsectors, stupid, raid_mode, subdir, NULL);
+ syslinux_patch(sectors, nsectors, opt.stupid_mode, opt.raid_mode, opt.directory, NULL);
/*
* Rewrite the file
@@ -453,10 +408,10 @@ int main(int argc, char *argv[])
}
/* If desired, fix the MBR */
- if (mbr || setactive) {
+ if (opt.install_mbr || opt.activate_partition) {
STORAGE_DEVICE_NUMBER sdn;
if (GetStorageDeviceNumberByHandle(d_handle, &sdn)) {
- if (!FixMBR(sdn.DeviceNumber, sdn.PartitionNumber, mbr, setactive)) {
+ if (!FixMBR(sdn.DeviceNumber, sdn.PartitionNumber, opt.install_mbr, opt.activate_partition)) {
fprintf(stderr,
"Did not successfully update the MBR; continuing...\n");
}
@@ -470,17 +425,17 @@ int main(int argc, char *argv[])
CloseHandle(f_handle);
/* Move the file to the desired location */
- if (subdir) {
- char new_ldlinux_name[strlen(subdir) + 16];
+ if (opt.directory) {
+ char new_ldlinux_name[strlen(opt.directory) + 16];
char *cp = new_ldlinux_name + 3;
const char *sd;
int slash = 1;
- new_ldlinux_name[0] = drive[0];
+ new_ldlinux_name[0] = opt.device[0];
new_ldlinux_name[1] = ':';
new_ldlinux_name[2] = '\\';
- for (sd = subdir; *sd; sd++) {
+ for (sd = opt.directory; *sd; sd++) {
char c = *sd;
if (c == '/' || c == '\\') {
@@ -520,8 +475,8 @@ int main(int argc, char *argv[])
syslinux_make_bootsect(sectbuf);
/* Write the syslinux boot sector into the boot sector */
- if (bootsecfile) {
- f_handle = CreateFile(bootsecfile, GENERIC_READ | GENERIC_WRITE,
+ if (opt.bootsecfile) {
+ f_handle = CreateFile(opt.bootsecfile, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_ARCHIVE, NULL);
diff --git a/win32/Makefile b/win32/Makefile
index a077b30c..d4133ff8 100644
--- a/win32/Makefile
+++ b/win32/Makefile
@@ -29,27 +29,31 @@ else
ifeq ($(findstring MINGW32,$(OSTYPE)),MINGW32)
WINPREFIX :=
else
-WINPREFIX := $(shell ./find-mingw.sh gcc)
+WINPREFIX := $(shell ./find-mingw32.sh gcc)
endif
WINCFLAGS := $(GCCWARN) -Wno-sign-compare -Os -fomit-frame-pointer \
-D_FILE_OFFSET_BITS=64
WINLDFLAGS := -Os -s
endif
-WINCFLAGS += -I. -I.. -I../libfat -I../libinstaller
+WINCFLAGS += -I. -I../win -I.. -I../libfat -I../libinstaller \
+ -I../libinstaller/getopt
WINCC := $(WINPREFIX)gcc
WINAR := $(WINPREFIX)ar
WINRANLIB := $(WINPREFIX)ranlib
-WINCC_IS_GOOD := $(shell $(WINCC) $(WINCFLAGS) $(WINLDFLAGS) -o hello.exe hello.c >/dev/null 2>&1 ; echo $$?)
+WINCC_IS_GOOD := $(shell $(WINCC) $(WINCFLAGS) $(WINLDFLAGS) \
+ -o hello.exe ../win/hello.c >/dev/null 2>&1 ; echo $$?)
-.SUFFIXES: .c .o .i .s .S
+.SUFFIXES: .c .obj .lib .exe .i .s .S
-SRCS = syslinux.c
+SRCS = ../win/syslinux.c
OBJS = $(patsubst %.c,%.obj,$(notdir $(SRCS)))
LIBSRC = ../libinstaller/fat.c \
../libinstaller/syslxmod.c \
+ ../libinstaller/syslxopt.c \
../libinstaller/setadv.c \
+ ../libinstaller/getopt/getopt_long.c \
../libinstaller/bootsect_bin.c \
../libinstaller/ldlinux_bin.c \
../libinstaller/mbr_bin.c \
@@ -58,7 +62,7 @@ LIBOBJS = $(patsubst %.c,%.obj,$(notdir $(LIBSRC)))
LIB = syslinux.lib
-VPATH = .:../libfat:../libinstaller
+VPATH = .:../win:../libfat:../libinstaller:../libinstaller/getopt
TARGETS = syslinux.exe
@@ -80,6 +84,7 @@ spotless: clean
installer:
$(LIB): $(LIBOBJS)
+ rm -f $@
$(WINAR) cq $@ $^
$(WINRANLIB) $@
diff --git a/win32/README b/win32/README
index a1578f91..8775cf0a 100644
--- a/win32/README
+++ b/win32/README
@@ -2,7 +2,5 @@ Building the Win32 installer requires the MinGW compiler, available at:
http://www.mingw.org/
-Prepackaged versions of the MinGW cross-compiler in RPM format for
-Linux are available at:
-
- http://mirzam.it.vu.nl/mingw/
+Prepackaged versions of the MinGW cross-compiler are now included in
+several Linux distributions, including Fedora.
diff --git a/win32/find-mingw.sh b/win32/find-mingw32.sh
index 7a4491cd..f79949c7 100755
--- a/win32/find-mingw.sh
+++ b/win32/find-mingw32.sh
@@ -4,6 +4,7 @@ cc="$1"
for prefix in \
mingw- \
+ mingw32- \
i386-pc-mingw32- \
i486-pc-mingw32- \
i586-pc-mingw32- \
diff --git a/win64/Makefile b/win64/Makefile
new file mode 100644
index 00000000..0bc746d5
--- /dev/null
+++ b/win64/Makefile
@@ -0,0 +1,92 @@
+## -----------------------------------------------------------------------
+##
+## Copyright 1998-2008 H. Peter Anvin - All Rights Reserved
+## Copyright 2010 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.
+##
+## -----------------------------------------------------------------------
+
+#
+# Makefile for SYSLINUX Win64
+#
+# This is separated out mostly so we can have a different set of Makefile
+# variables.
+#
+
+OSTYPE = $(shell uname -msr)
+# Don't know how to do a native compile here...
+WINPREFIX := $(shell ./find-mingw64.sh gcc)
+WINCFLAGS := $(GCCWARN) -Wno-sign-compare -Os -fomit-frame-pointer \
+ -D_FILE_OFFSET_BITS=64
+WINLDFLAGS := -Os -s
+
+WINCFLAGS += -I. -I../win -I.. -I../libfat -I../libinstaller \
+ -I../libinstaller/getopt
+
+WINCC := $(WINPREFIX)gcc
+WINAR := $(WINPREFIX)ar
+WINRANLIB := $(WINPREFIX)ranlib
+
+WINCC_IS_GOOD := $(shell $(WINCC) $(WINCFLAGS) $(WINLDFLAGS) \
+ -o hello.exe ../win/hello.c >/dev/null 2>&1 ; echo $$?)
+
+.SUFFIXES: .c .obj .lib .exe .i .s .S
+
+SRCS = ../win/syslinux.c
+OBJS = $(patsubst %.c,%.obj,$(notdir $(SRCS)))
+LIBSRC = ../libinstaller/fat.c \
+ ../libinstaller/syslxmod.c \
+ ../libinstaller/syslxopt.c \
+ ../libinstaller/setadv.c \
+ ../libinstaller/getopt/getopt_long.c \
+ ../libinstaller/bootsect_bin.c \
+ ../libinstaller/ldlinux_bin.c \
+ ../libinstaller/mbr_bin.c \
+ $(wildcard ../libfat/*.c)
+LIBOBJS = $(patsubst %.c,%.obj,$(notdir $(LIBSRC)))
+
+LIB = syslinux.lib
+
+VPATH = .:../win:../libfat:../libinstaller:../libinstaller/getopt
+
+TARGETS = syslinux64.exe
+
+ifeq ($(WINCC_IS_GOOD),0)
+all: $(TARGETS)
+else
+all:
+ rm -f $(TARGETS)
+endif
+
+tidy dist:
+ -rm -f *.o *.obj *.lib *.i *.s *.a .*.d *.tmp *_bin.c hello.exe
+
+clean: tidy
+
+spotless: clean
+ -rm -f *~ $(TARGETS)
+
+installer:
+
+$(LIB): $(LIBOBJS)
+ rm -f $@
+ $(WINAR) cq $@ $^
+ $(WINRANLIB) $@
+
+syslinux64.exe: $(OBJS) $(LIB)
+ $(WINCC) $(WINLDFLAGS) -o $@ $^
+
+
+%.obj: %.c
+ $(WINCC) $(UMAKEDEPS) $(WINCFLAGS) -c -o $@ $<
+%.i: %.c
+ $(WINCC) $(UMAKEDEPS) $(WINCFLAGS) -E -o $@ $<
+%.s: %.c
+ $(WINCC) $(UMAKEDEPS) $(WINCFLAGS) -S -o $@ $<
+
+-include .*.d *.tmp
diff --git a/win64/README b/win64/README
new file mode 100644
index 00000000..05b41607
--- /dev/null
+++ b/win64/README
@@ -0,0 +1,10 @@
+Building the Win64 installer requires the MinGW-W64 compiler,
+available at:
+
+ http://mingw-w64.sourceforge.net/
+
+For prepackaged versions of the MinGW-W64 cross-compiler for the
+Fedora Linux distribution (and possibly other RPM-based
+distributions), see:
+
+ http://lists.fedoraproject.org/pipermail/mingw/2010-May/002589.html
diff --git a/win64/find-mingw64.sh b/win64/find-mingw64.sh
new file mode 100755
index 00000000..6b620c87
--- /dev/null
+++ b/win64/find-mingw64.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+cc="$1"
+
+for prefix in \
+ mingw64- \
+ x86_64-pc-mingw64- \
+ x86_64-pc-mingw64msvc- \
+ x86_64-pc-mingw32- \
+ x86_64-pc-mingw32msvc- \
+ x86_64-mingw64- \
+ x86_64-mingw64msvc- \
+ x86_64-mingw32- \
+ x86_64-mingw32msvc- \
+ ; do
+ if "${prefix}${cc}" -v > /dev/null 2>&1; then
+ echo "$prefix"
+ exit 0
+ fi
+done
+
+# No prefix, no idea what to do now...
+echo missing-
+exit 1