summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhpa <hpa>2005-01-05 01:01:29 +0000
committerhpa <hpa>2005-01-05 01:01:29 +0000
commit80717f76b561e490cf862c87be2e3ef1e5596b37 (patch)
treed5b7b3359e765ea6c2647962c5270034df29f65b
parent76508a9bc942a693dc8ac773fc471501580d7bbf (diff)
downloadsyslinux-80717f76b561e490cf862c87be2e3ef1e5596b37.tar.gz
Allow the user to override the extlinux detected geometry; add online help
-rw-r--r--Makefile8
-rw-r--r--NEWS7
-rw-r--r--extlinux/extlinux.c118
-rwxr-xr-xversion.pl11
4 files changed, 124 insertions, 20 deletions
diff --git a/Makefile b/Makefile
index 5f5c35ec..f6927c0f 100644
--- a/Makefile
+++ b/Makefile
@@ -59,7 +59,8 @@ BINFILES = bootsect_bin.c ldlinux_bin.c mbr_bin.c \
# syslinux.exe is BTARGET so as to not require everyone to have the
# mingw suite installed
-BTARGET = kwdhash.gen version.gen ldlinux.bss ldlinux.sys ldlinux.bin \
+BTARGET = kwdhash.gen version.gen version.h \
+ ldlinux.bss ldlinux.sys ldlinux.bin \
pxelinux.0 mbr.bin isolinux.bin isolinux-debug.bin \
extlinux.bin extlinux.bss extlinux.sys
BOBJECTS = $(BTARGET) dos/syslinux.com win32/syslinux.exe memdisk/memdisk
@@ -113,7 +114,10 @@ installer: installer-local
installer-local: $(ITARGET) $(BINFILES)
version.gen: version version.pl
- $(PERL) version.pl version
+ $(PERL) version.pl $< $@ '%define'
+
+version.h: version version.pl
+ $(PERL) version.pl $< $@ '#define'
kwdhash.gen: keywords genhash.pl
$(PERL) genhash.pl < keywords > kwdhash.gen
diff --git a/NEWS b/NEWS
index bb8180bc..9692d434 100644
--- a/NEWS
+++ b/NEWS
@@ -14,7 +14,12 @@ Changes in 3.02:
work better over a serial console (speed, and readability on
monochrome terminal emulators.)
* New CONSOLE directive to control output on the video console
- (useful for dealing with some broken serial-forwarding BIOSes.)
+ (useful for dealing with some broken serial-forwarding
+ BIOSes.)
+ * New com32 module "ethersel" for searching for an Ethernet
+ card and selecting the proper version of Etherboot.
+ * EXTLINUX: Allow the user to override the detected geometry.
+ Add help.
Changes in 3.01:
* EXTLINUX, SYSLINUX: Fix compile errors on some systems.
diff --git a/extlinux/extlinux.c b/extlinux/extlinux.c
index b186ec9a..5d1733e6 100644
--- a/extlinux/extlinux.c
+++ b/extlinux/extlinux.c
@@ -27,6 +27,8 @@
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
+#include <getopt.h>
+#include <sysexits.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -37,12 +39,58 @@
#include <linux/hdreg.h> /* Hard disk geometry */
#include <linux/fs.h> /* FIGETBSZ, FIBMAP */
+#include "../version.h"
+
#ifdef DEBUG
# define dprintf printf
#else
# define dprintf(...) ((void)0)
#endif
+/* Global option handling */
+
+/* These are the options we can set and their values */
+struct my_options {
+ unsigned int sectors;
+ unsigned int heads;
+} opt = {
+ .sectors = 0,
+ .heads = 0,
+};
+
+static void __attribute__((noreturn)) usage(int rv)
+{
+ fprintf(stderr,
+ "Usage: %s [options] directory\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"
+ "\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",
+ program);
+
+ exit(rv);
+}
+
+static const struct option long_options[] = {
+ { "zipdrive", 0, NULL, 'z' },
+ { "sectors", 1, NULL, 'S' },
+ { "heads", 1, NULL, 'H' },
+ { "version", 0, NULL, 'v' },
+ { "help", 0, NULL, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+static const char short_options[] = "zS:H:vh";
+
+
+
#if defined(__linux__) && !defined(BLKGETSIZE64)
/* This takes a u64, but the size field says size_t. Someone screwed big. */
# define BLKGETSIZE64 _IOR(0x12,114,size_t)
@@ -358,12 +406,14 @@ get_geometry(int devfd, uint64_t totalbytes, struct hd_geometry *geo)
what zipdisks use, so this would help if someone has a USB key that
they're booting in USB-ZIP mode. */
- geo->heads = 64;
- geo->sectors = 32;
- geo->cylinders = totalbytes/(64*32*512);
+ geo->heads = opt.heads ?: 64;
+ geo->sectors = opt.sectors ?: 32;
+ geo->cylinders = totalbytes/(geo->heads*geo->sectors << SECTOR_SHIFT);
geo->start = 0;
- fprintf(stderr, "Warning: unable to obtain device geometry (defaulting to %d heads, %d sectors)\n",
- geo->heads, geo->sectors);
+
+ if ( !opt.sectors && !opt.heads )
+ fprintf(stderr, "Warning: unable to obtain device geometry (defaulting to %d heads, %d sectors)\n",
+ geo->heads, geo->sectors);
return 1;
}
@@ -384,6 +434,7 @@ patch_file_and_bootblock(int fd, int dirfd, int devfd)
unsigned char *p, *patcharea;
int i, dw;
uint32_t csum;
+ unsigned int sectors, heads;
if ( fstat(dirfd, &dirst) ) {
perror("fstat dirfd");
@@ -393,10 +444,15 @@ patch_file_and_bootblock(int fd, int dirfd, int devfd)
totalbytes = get_size(devfd);
get_geometry(devfd, totalbytes, &geo);
+ if ( opt.heads )
+ geo.heads = opt.heads;
+ if ( opt.sectors )
+ geo.sectors = opt.sectors;
+
/* Patch this into a fake FAT superblock. This isn't because
FAT is a good format in any way, it's because it lets the
early bootstrap share code with the FAT version. */
- dprintf("cyl = %u, heads = %u, sect = %u\n", geo.cylinders, geo.heads, geo.sectors);
+ dprintf("heads = %u, sect = %u\n", geo.heads, geo.sectors);
totalsectors = totalbytes >> SECTOR_SHIFT;
if ( totalsectors >= 65536 ) {
@@ -570,7 +626,7 @@ install_file(char *path, int devfd, struct stat *rst)
}
int
-install_loader(char *path)
+install_loader(const char *path, unsigned int sectors, unsigned int heads)
{
struct stat st, dst, fst;
struct mntent *mnt = NULL;
@@ -648,11 +704,49 @@ int
main(int argc, char *argv[])
{
program = argv[0];
-
- if ( argc != 2 ) {
- fprintf(stderr, "Usage: %s directory\n", program);
- exit(1);
+ int opt;
+ unsigned long a;
+ const char *directory;
+
+ while ( (opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != EOF ) {
+ switch ( opt ) {
+ case 'z':
+ opt.heads = 64;
+ opt.sectors = 32;
+ break;
+ case 'S':
+ opt.sectors = strtoul(optarg, NULL, 0);
+ if ( opt.sectors < 1 || opt.sectors > 63 ) {
+ fprintf(stderr, "%s: invalid number of sectors: %u (must be 1-63)\n",
+ program, opt.sectors);
+ exit(EX_USAGE);
+ }
+ break;
+ case 'H':
+ opt.heads = strtoul(optarg, NULL, 0);
+ if ( opt.heads < 1 || opt.heads > 256 ) {
+ fprintf(stderr, "%s: invalid number of heads: %u (must be 1-256)\n",
+ program, opt.heads);
+ exit(EX_USAGE);
+ }
+ break;
+ case 'h':
+ usage(0);
+ break;
+ case 'v':
+ fputs("extlinux " VERSION "\n", stderr);
+ exit(0);
+ default:
+ fprintf(stderr, "%s: Unknown option: %c\n", optopt);
+ exit(EX_USAGE);
+ }
}
- return install_loader(argv[1]);
+ directory = argv[optind];
+
+ if ( !directory )
+ usage(EX_USAGE);
+
+ return install_loader(directory);
}
diff --git a/version.pl b/version.pl
index fa09e40d..39d42a03 100755
--- a/version.pl
+++ b/version.pl
@@ -5,7 +5,7 @@
use Fcntl;
-$vfile = $ARGV[0];
+($vfile, $vout, $def) = $ARGV[0];
sysopen(VERSION, $vfile, O_RDONLY) or die "$0: Cannot open $vfile\n";
$version = <VERSION>;
chomp $version;
@@ -16,10 +16,11 @@ unless ( $version =~ /^([0-9]+)\.([0-9]+)$/ ) {
}
$vma = $1+0; $vmi = $2+0;
-open(VI, "> version.gen") or die "$0: Cannot create version.gen\n";
-print VI "%define VERSION \"$version\"\n";
-print VI "%define VER_MAJOR $vma\n";
-print VI "%define VER_MINOR $vmi\n";
+sysopen(VI, $vout, O_WRONLY|O_CREAT|O_TRUNC)
+ or die "$0: Cannot create $vout: $!\n";
+print VI "$def VERSION \"$version\"\n";
+print VI "$def VER_MAJOR $vma\n";
+print VI "$def VER_MINOR $vmi\n";
close(VI);