Add MBR-writing options to the Win32 installer. Probably should be
authorhpa <hpa>
Wed, 22 Dec 2004 17:53:54 +0000 (17:53 +0000)
committerhpa <hpa>
Wed, 22 Dec 2004 17:53:54 +0000 (17:53 +0000)
added to the DOS installer at some point, too.

Makefile
NEWS
syslinux.h
win32/Makefile
win32/syslinux.c

index ea981b0..f0eff92 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -38,10 +38,6 @@ VERSION  = $(shell cat version)
 .c.o:
        $(CC) $(INCLUDE) $(CFLAGS) -c $<
 
-# libsyslinux.so
-LIB_SONAME = libsyslinux.so.2.2
-LIB_SO  = libsyslinux.so.$(VERSION)
-
 #
 # The BTARGET refers to objects that are derived from ldlinux.asm; we
 # like to keep those uniform for debugging reasons; however, distributors 
@@ -60,8 +56,8 @@ SOURCES = $(CSRC) *.h $(NASMSRC) *.inc
 BTARGET  = kwdhash.gen version.gen ldlinux.bss ldlinux.sys ldlinux.bin \
           pxelinux.0 mbr.bin isolinux.bin isolinux-debug.bin \
           extlinux.bin extlinux.bss extlinux.sys \
-          bootsect_bin.c ldlinux_bin.c extlinux_bss_bin.c extlinux_sys_bin.c
-          # libsyslinux.a $(LIB_SO)
+          bootsect_bin.c ldlinux_bin.c mbr_bin.c \
+          extlinux_bss_bin.c extlinux_sys_bin.c 
 BOBJECTS = $(BTARGET) dos/syslinux.com win32/syslinux.exe memdisk/memdisk
 BSUBDIRS = memdisk dos win32
 ITARGET  = copybs.com gethostip mkdiskimage
@@ -80,9 +76,9 @@ INSTALL_AUX   =       pxelinux.0 isolinux.bin isolinux-debug.bin \
                dos/syslinux.com win32/syslinux.exe \
                copybs.com memdisk/memdisk
 # Things to install in /usr/lib
-INSTALL_LIB   = $(LIB_SO) libsyslinux.a
+INSTALL_LIB   = # libsyslinux.a
 # Things to install in /usr/include
-INSTALL_INC   = syslinux.h
+INSTALL_INC   = syslinux.h
 
 # The DATE is set on the make command line when building binaries for
 # official release.  Otherwise, substitute a hex string that is pretty much
@@ -162,6 +158,9 @@ extlinux.sys: extlinux.bin
 mbr.bin: mbr.asm
        $(NASM) -f bin -l mbr.lst -o mbr.bin mbr.asm
 
+mbr_bin.c: mbr.bin bin2c.pl
+       $(PERL) bin2c.pl syslinux_mbr < $< > $@
+
 copybs.com: copybs.asm
        $(NASM) -f bin -l copybs.lst -o copybs.com copybs.asm
 
@@ -177,7 +176,7 @@ extlinux_bss_bin.c: extlinux.bss bin2c.pl
 extlinux_sys_bin.c: extlinux.sys bin2c.pl
        $(PERL) bin2c.pl extlinux_image < $< > $@
 
-libsyslinux.a: bootsect_bin.o ldlinux_bin.o syslxmod.o
+libsyslinux.a: bootsect_bin.o ldlinux_bin.o mbr_bin.o syslxmod.o
        rm -f $@
        $(AR) cq $@ $^
        $(RANLIB) $@
diff --git a/NEWS b/NEWS
index 1336ad3..defde73 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -31,7 +31,9 @@ Changes in 3.00:
          from an alternate TFTP server, or just a ::
          (e.g. ::filename), which suppresses the common pathname
          prefix.  See pxelinux.doc.
-
+       * SYSLINUX: Add an -m option to the Win32 installer (only!)
+         to write an MBR and -a to mark the partition SYSLINUX is
+         being installed on active.
 
 Changes in 2.13:
        * MEMDISK: Fix command-line parsing "brown paper bag" class
index ccfb0f0..6e4315b 100644 (file)
 /* The standard boot sector and ldlinux image */
 extern unsigned char syslinux_bootsect[];
 extern unsigned int  syslinux_bootsect_len;
+extern int           syslinux_bootsect_mtime;
 
 extern unsigned char syslinux_ldlinux[];
 extern unsigned int  syslinux_ldlinux_len;
 extern int           syslinux_ldlinux_mtime;
 
+extern unsigned char syslinux_mbr[];
+extern unsigned int  syslinux_mbr_len;
+extern int           syslinux_mbr_mtime;
+
 /* This switches the boot sector to "stupid mode" */
 void syslinux_make_stupid(void);
 
index 3c335b7..cb9ee78 100644 (file)
@@ -47,7 +47,8 @@ CC_IS_GOOD := $(shell $(CC) $(CFLAGS) $(LDFLAGS) -o hello.exe hello.c >/dev/null
 
 .SUFFIXES: .c .o .i .s .S
 
-SRCS     = syslinux.c ../syslxmod.c ../bootsect_bin.c ../ldlinux_bin.c $(wildcard ../libfat/*.c)
+SRCS     = syslinux.c ../syslxmod.c ../bootsect_bin.c ../ldlinux_bin.c \
+          ../mbr_bin.c $(wildcard ../libfat/*.c)
 OBJS     = $(patsubst %.c,%.o,$(notdir $(SRCS)))
 
 VPATH = .:..:../libfat
@@ -62,7 +63,7 @@ all:
 endif
 
 tidy:
-       -rm -f *.o *.i *.s *.a .*.d
+       -rm -f *.o *.i *.s *.a .*.d *_bin.c
 
 clean: tidy
 
@@ -74,6 +75,7 @@ installer:
 syslinux.exe: $(OBJS)
        $(CC) $(LDFLAGS) -o $@ $^
 
+
 %.o: %.c
        $(CC) -Wp,-MT,$@,-MMD,.$@.d $(CFLAGS) -c -o $@ $<
 %.i: %.c
index 53fb362..8cbea7c 100644 (file)
 #include "syslinux.h"
 #include "libfat.h"
 
+void error(char* msg);
+
+/* Begin stuff for MBR code */
+
+#include <winioctl.h>
+
+#define SECTOR_SIZE 512
+#define PART_TABLE  0x1be
+#define PART_SIZE   0x10
+#define PART_COUNT  4
+#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
+typedef struct _STORAGE_DEVICE_NUMBER {
+  DEVICE_TYPE  DeviceType;
+  ULONG  DeviceNumber;
+  ULONG  PartitionNumber;
+} STORAGE_DEVICE_NUMBER, *PSTORAGE_DEVICE_NUMBER;
+
+BOOL GetStorageDeviceNumberByHandle( HANDLE handle, const STORAGE_DEVICE_NUMBER *sdn ) {
+  BOOL result = FALSE;
+  DWORD count;
+  
+  if ( DeviceIoControl( handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL,
+                       0, (LPVOID)sdn, sizeof( *sdn ), &count, NULL ) ) {
+    result = TRUE;
+  }
+  else {
+    error("GetDriveNumber: DeviceIoControl failed.");
+  }
+  
+  return( result );
+}
+
+int GetBytesPerSector( HANDLE drive ) {
+  int result = 0;
+  DISK_GEOMETRY g;
+  DWORD count;
+  
+  if ( DeviceIoControl( drive, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
+                       &g, sizeof( g ), &count, NULL ) ) {
+    result = g.BytesPerSector;
+  }
+  
+  return( result );
+}
+
+BOOL FixMBR(int driveNum, int partitionNum, int write_mbr, int set_active) {
+  BOOL result = TRUE;
+  HANDLE drive;
+  
+  char driveName[128];
+  
+  sprintf( driveName, "\\\\.\\PHYSICALDRIVE%d", driveNum );
+  
+  drive = CreateFile( driveName,
+                     GENERIC_READ | GENERIC_WRITE,
+                     FILE_SHARE_WRITE | FILE_SHARE_READ,
+                     NULL,
+                     OPEN_EXISTING,
+                     0,
+                     NULL );
+  
+  if( drive == INVALID_HANDLE_VALUE ) {
+    error("Accessing physical drive");
+    result = FALSE;
+  }
+  
+  if( result ) {
+    unsigned char sector[SECTOR_SIZE];
+    DWORD howMany;
+    
+    if( GetBytesPerSector( drive ) != SECTOR_SIZE ) {
+      fprintf(stderr, "Error: Sector size of this drive is %d; must be %d\n",
+             GetBytesPerSector( drive ), SECTOR_SIZE );
+      result = FALSE;
+    }
+    
+    if ( result ) {
+      if ( ReadFile( drive, sector, sizeof( sector ), &howMany, NULL ) == 0 ) {
+       error("Reading raw drive");
+       result = FALSE;
+      } else if ( howMany != sizeof( sector ) ) {
+       fprintf(stderr, "Error: ReadFile on drive only got %d of %d bytes\n",
+               (int)howMany, sizeof( sector ) );
+       result = FALSE;
+      }
+    }
+    
+    // Copy over the MBR code if specified (-m)
+    if ( write_mbr ) {
+      if ( result ) {
+       if ( syslinux_mbr_len >= PART_TABLE ) {
+         fprintf(stderr, "Error: MBR will not fit; not writing\n" );
+         result = FALSE;
+       } else {
+         memcpy( sector, syslinux_mbr, syslinux_mbr_len );
+       }
+      }
+    }
+    
+    // Check that our partition is active if specified (-a)
+    if ( set_active ) {
+      if ( sector[ PART_TABLE + ( PART_SIZE * ( partitionNum - 1 ) ) ] != 0x80 ) {
+       int p;
+       for ( p = 0; p < PART_COUNT; p++ )
+         sector[ PART_TABLE + ( PART_SIZE * p ) ] = ( p == partitionNum - 1 ? 0x80 : 0 );
+      }
+    }
+
+    if ( result ) {
+      SetFilePointer( drive, 0, NULL, FILE_BEGIN );
+      
+      if ( WriteFile( drive, sector, sizeof( sector ), &howMany, NULL ) == 0 ) {
+       error("Writing MBR");
+       result = FALSE;
+      } else if ( howMany != sizeof( sector ) ) {
+       fprintf(stderr, "Error: WriteFile on drive only wrote %d of %d bytes\n",
+               (int)howMany, sizeof( sector ) );
+       result = FALSE;
+      }
+    }
+    
+    if( !CloseHandle( drive ) ) {
+      error("CloseFile on drive");
+      result = FALSE;
+    }
+  }
+  
+  return( result );
+}
+
+/* End stuff for MBR code */
+
 char *program;                 /* Name of program */
 char *drive;                   /* Drive to install to */
 
@@ -32,7 +167,7 @@ char *drive;                 /* Drive to install to */
  * On Windows Me/98/95 you cannot open a directory, physical disk, or
  * volume using CreateFile.
  */
-int checkver()
+int checkver(void)
 {
   OSVERSIONINFO osvi;
 
@@ -91,7 +226,7 @@ int libfat_readfile(intptr_t pp, void *buf, size_t secsize, libfat_sector_t sect
 
 void usage(void)
 {
-  fprintf(stderr, "Usage: syslinux.exe [-sf] <drive>:\n");
+  fprintf(stderr, "Usage: syslinux.exe [-sfma] <drive>:\n");
   exit(1);
 }
 
@@ -115,6 +250,8 @@ int main(int argc, char *argv[])
   int nsectors;
 
   int force = 0;               /* -f (force) option */
+  int mbr = 0;                 /* -m (MBR) option */
+  int setactive = 0;           /* -a (set partition active) */
 
   (void)argc;
 
@@ -135,8 +272,12 @@ int main(int argc, char *argv[])
       while ( *opt ) {
        if ( *opt == 's' ) {
          syslinux_make_stupid();       /* Use "safe, slow and stupid" code */
-        } else if ( *opt == 'f' ) {
-          force = 1;                    /* Force install */
+       } else if ( *opt == 'f' ) {
+         force = 1;                    /* Force install */
+       } else if ( *opt == 'm' ) {
+         mbr = 1;                      /* Install MBR */
+       } else if ( *opt == 'a' ) {
+         setactive = 1;                /* Mark this partition active */
        } else {
          usage();
        }
@@ -271,6 +412,18 @@ int main(int argc, char *argv[])
     exit(1);
   }
 
+  /* If desired, fix the MBR */
+  if( mbr || setactive ) {
+    STORAGE_DEVICE_NUMBER sdn;
+    if( GetStorageDeviceNumberByHandle( f_handle, &sdn ) ) {
+      if( !FixMBR(sdn.DeviceNumber, sdn.PartitionNumber, mbr, setactive) ) {
+        fprintf(stderr, "Did not successfully update the MBR; continuing...\n");
+      }
+    } else {
+      fprintf(stderr, "Could not find device number for updating MBR; continuing...\n");
+    }
+  }
+
   /* Close file */ 
   CloseHandle(f_handle);