Allow the user to override the extlinux detected geometry; add online help
authorhpa <hpa>
Wed, 5 Jan 2005 01:01:29 +0000 (01:01 +0000)
committerhpa <hpa>
Wed, 5 Jan 2005 01:01:29 +0000 (01:01 +0000)
Makefile
NEWS
extlinux/extlinux.c
version.pl

index 5f5c35e..f6927c0 100644 (file)
--- 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 bb8180b..9692d43 100644 (file)
--- 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.
index b186ec9..5d1733e 100644 (file)
@@ -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>
 #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);
 }
index fa09e40..39d42a0 100755 (executable)
@@ -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);