[syslinux:elflink] installers: Install ldlinux.c32 automatically

syslinux-bot for Matt Fleming matt.fleming at intel.com
Mon Oct 22 12:54:03 PDT 2012


Commit-ID:  bda54cb680676bffa731394096956f5d10fbcfaf
Gitweb:     http://www.syslinux.org/commit/bda54cb680676bffa731394096956f5d10fbcfaf
Author:     Matt Fleming <matt.fleming at intel.com>
AuthorDate: Fri, 14 Sep 2012 15:22:29 +0100
Committer:  Matt Fleming <matt.fleming at intel.com>
CommitDate: Wed, 19 Sep 2012 10:46:41 +0100

installers: Install ldlinux.c32 automatically

Because ldlinux.c32 is required for Syslinux to function correctly, we
should be installing it automatically much like ldlinux.sys.

Signed-off-by: Matt Fleming <matt.fleming at intel.com>

---
 dos/dosexe.ld           |    6 +-
 dos/ldlinux.S           |   14 +++++-
 dos/syslinux.c          |  100 +++++++++++++++++++++----------------
 extlinux/Makefile       |    1 +
 extlinux/main.c         |   58 ++++++++++++++++++++--
 libinstaller/Makefile   |    5 ++-
 libinstaller/syslinux.h |    3 +
 linux/Makefile          |    1 +
 linux/syslinux.c        |   55 ++++++++++++++++----
 mtools/Makefile         |    1 +
 mtools/syslinux.c       |  129 +++++++++++++++++++++++++++++-----------------
 win/syslinux.c          |  123 +++++++++++++++++++++++++++++---------------
 win32/Makefile          |    1 +
 win64/Makefile          |    1 +
 14 files changed, 346 insertions(+), 152 deletions(-)

diff --git a/dos/dosexe.ld b/dos/dosexe.ld
index 76bfc75..bd6ad8b 100644
--- a/dos/dosexe.ld
+++ b/dos/dosexe.ld
@@ -26,7 +26,7 @@ SECTIONS
 	__header_size = .;
 	__payload_lma = .;
 
-	. = 0x100000000 - syslinux_ldlinux_size;
+	. = 0x100000000 - syslinux_size;
 	.payload : AT (__payload_lma) {
 		 __payload_start = .;
 		 *(.payload)
@@ -35,13 +35,13 @@ SECTIONS
 	__payload_len = ABSOLUTE(__payload_end) - ABSOLUTE(__payload_start);
 	__payload_dwords = __payload_len >> 2;
 
-	__text_lma = __payload_lma + syslinux_ldlinux_size;
+	__text_lma = __payload_lma + syslinux_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");
+ *	"syslinux_size must equal the size of .payload");
  */
 	. = 0;
 	.text : AT (__text_lma) {
diff --git a/dos/ldlinux.S b/dos/ldlinux.S
index 17a6583..9145bd7 100644
--- a/dos/ldlinux.S
+++ b/dos/ldlinux.S
@@ -1,5 +1,5 @@
 /*
- * Wrap ldlinux.sys; this needs special handling for DOS.
+ * Wrap ldlinux.sys and ldlinux.c32; this needs special handling for DOS.
  */
 
 	.section ".payload","aw"
@@ -10,6 +10,14 @@ syslinux_ldlinux:
 	.space ((syslinux_ldlinux - .) & 511)
 syslinux_ldlinux_size	= . - syslinux_ldlinux
 	.size	syslinux_ldlinux, .-syslinux_ldlinux
+	.globl	syslinux_ldlinuxc32, syslinux_ldlinuxc32_size
+syslinux_ldlinuxc32:
+	.incbin "../com32/elflink/ldlinux/ldlinux.c32"
+	.space ((syslinux_ldlinuxc32 - .) & 511)
+syslinux_ldlinuxc32_size = . - syslinux_ldlinuxc32
+	.size	syslinux_ldlinuxc32, .-syslinux_ldlinuxc32
+	.globl syslinux_size
+syslinux_size	= . - syslinux_ldlinux
 
 	.section ".rodata","a"
 	.balign	4
@@ -17,3 +25,7 @@ syslinux_ldlinux_size	= . - syslinux_ldlinux
 syslinux_ldlinux_len:
 	.long	syslinux_ldlinux_size
 	.size	syslinux_ldlinux_len, .-syslinux_ldlinux_len
+	.globl	syslinux_ldlinuxc32_len
+syslinux_ldlinuxc32_len:
+	.long	syslinux_ldlinuxc32_size
+	.size	syslinux_ldlinuxc32_len, .-syslinux_ldlinuxc32_len
diff --git a/dos/syslinux.c b/dos/syslinux.c
index fa4bf38..eb8bace 100644
--- a/dos/syslinux.c
+++ b/dos/syslinux.c
@@ -121,15 +121,15 @@ int rename(const char *oldname, const char *newname)
     return 0;
 }
 
-ssize_t write_ldlinux(int fd)
+ssize_t write_file_seg(int fd, unsigned char *buf, const unsigned int len)
 {
-    uint16_t ldlinux_seg = ((size_t)syslinux_ldlinux >> 4) + ds();
+    uint16_t seg = ((size_t)buf >> 4) + ds();
     uint32_t offset = 0;
     uint16_t rv;
     uint8_t err;
 
-    while (offset < syslinux_ldlinux_len) {
-	uint32_t chunk = syslinux_ldlinux_len - offset;
+    while (offset < len) {
+	uint32_t chunk = len - offset;
 	if (chunk > 32768)
 	    chunk = 32768;
 	asm volatile ("pushw %%ds ; "
@@ -137,7 +137,7 @@ ssize_t write_ldlinux(int fd)
 		      "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))));
+		      "SD" ((uint16_t)(seg + (offset >> 4))));
 	if (err || rv == 0)
 	    die("file write error");
 	offset += rv;
@@ -583,11 +583,53 @@ static void adjust_mbr(int device, int writembr, int set_active)
     write_mbr(device, sectbuf);
 }
 
+static void move_file(int dev_fd, char *pathname, char *filename)
+{
+    char new_name[160];
+    char *cp = new_name + 3;
+    const char *sd;
+    int slash = 1;
+
+    new_name[0] = dev_fd | 0x40;
+    new_name[1] = ':';
+    new_name[2] = '\\';
+
+    for (sd = opt.directory; *sd; sd++) {
+	char c = *sd;
+
+	if (c == '/' || c == '\\') {
+	    if (slash)
+		continue;
+	    c = '\\';
+	    slash = 1;
+	} else {
+	    slash = 0;
+	}
+
+	*cp++ = c;
+    }
+
+    /* Skip if subdirectory == root */
+    if (cp > new_name + 3) {
+	if (!slash)
+	    *cp++ = '\\';
+
+	memcpy(cp, filename, 12);
+
+	set_attributes(pathname, 0);
+	if (rename(pathname, new_name))
+	    set_attributes(pathname, 0x07);
+	else
+	    set_attributes(new_name, 0x07);
+    }
+}
+
 int main(int argc, char *argv[])
 {
     static unsigned char sectbuf[SECTOR_SIZE];
     int dev_fd, fd;
     static char ldlinux_name[] = "@:\\ldlinux.sys";
+    static char ldlinuxc32_name[] = "@:\\ldlinux.c32";
     struct libfat_filesystem *fs;
     libfat_sector_t s, *secp;
     libfat_sector_t *sectors;
@@ -647,14 +689,21 @@ int main(int argc, char *argv[])
     }
 
     ldlinux_name[0] = dev_fd | 0x40;
+    ldlinuxc32_name[0] = dev_fd | 0x40;
 
     set_attributes(ldlinux_name, 0);
     fd = creat(ldlinux_name, 0);	/* SYSTEM HIDDEN READONLY */
-    write_ldlinux(fd);
+    write_file_seg(fd, syslinux_ldlinux, syslinux_ldlinux_len);
     write_file(fd, syslinux_adv, 2 * ADV_SIZE);
     close(fd);
     set_attributes(ldlinux_name, 0x07);	/* SYSTEM HIDDEN READONLY */
 
+    set_attributes(ldlinuxc32_name, 0);
+    fd = creat(ldlinuxc32_name, 0);		/* SYSTEM HIDDEN READONLY */
+    write_file_seg(fd, syslinux_ldlinuxc32, syslinux_ldlinuxc32_len);
+    close(fd);
+    set_attributes(ldlinuxc32_name, 0x07);	/* SYSTEM HIDDEN READONLY */
+
     /*
      * Now, use libfat to create a block map.  This probably
      * should be changed to use ioctl(...,FIBMAP,...) since
@@ -681,43 +730,8 @@ int main(int argc, char *argv[])
      * If requested, move ldlinux.sys
      */
     if (opt.directory) {
-	char new_ldlinux_name[160];
-	char *cp = new_ldlinux_name + 3;
-	const char *sd;
-	int slash = 1;
-
-	new_ldlinux_name[0] = dev_fd | 0x40;
-	new_ldlinux_name[1] = ':';
-	new_ldlinux_name[2] = '\\';
-
-	for (sd = opt.directory; *sd; sd++) {
-	    char c = *sd;
-
-	    if (c == '/' || c == '\\') {
-		if (slash)
-		    continue;
-		c = '\\';
-		slash = 1;
-	    } else {
-		slash = 0;
-	    }
-
-	    *cp++ = c;
-	}
-
-	/* Skip if subdirectory == root */
-	if (cp > new_ldlinux_name + 3) {
-	    if (!slash)
-		*cp++ = '\\';
-
-	    memcpy(cp, "ldlinux.sys", 12);
-
-	    set_attributes(ldlinux_name, 0);
-	    if (rename(ldlinux_name, new_ldlinux_name))
-		set_attributes(ldlinux_name, 0x07);
-	    else
-		set_attributes(new_ldlinux_name, 0x07);
-	}
+	move_file(dev_fd, ldlinux_name, "ldlinux.sys");
+	move_file(dev_fd, ldlinuxc32_name, "ldlinux.c32");
     }
 
     /*
diff --git a/extlinux/Makefile b/extlinux/Makefile
index 6cde574..f20a71d 100644
--- a/extlinux/Makefile
+++ b/extlinux/Makefile
@@ -32,6 +32,7 @@ SRCS     = main.c \
 	   ../libinstaller/setadv.c \
 	   ../libinstaller/advio.c \
 	   ../libinstaller/bootsect_bin.c \
+	   ../libinstaller/ldlinuxc32_bin.c \
 	   ../libinstaller/ldlinux_bin.c
 OBJS	 = $(patsubst %.c,%.o,$(notdir $(SRCS)))
 
diff --git a/extlinux/main.c b/extlinux/main.c
index d7a239e..d1a9048 100644
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -398,16 +398,18 @@ int install_bootblock(int fd, const char *device)
 
 int ext2_fat_install_file(const char *path, int devfd, struct stat *rst)
 {
-    char *file, *oldfile;
+    char *file, *oldfile, *c32file;
     int fd = -1, dirfd = -1;
     int modbytes;
-    int r1, r2;
+    int r1, r2, r3;
 
     r1 = asprintf(&file, "%s%sldlinux.sys",
 		  path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
     r2 = asprintf(&oldfile, "%s%sextlinux.sys",
 		  path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
-    if (r1 < 0 || !file || r2 < 0 || !oldfile) {
+    r3 = asprintf(&c32file, "%s%sldlinux.c32",
+		  path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
+    if (r1 < 0 || !file || r2 < 0 || !oldfile || r3 < 0 || !c32file) {
 	perror(program);
 	return 1;
     }
@@ -474,8 +476,22 @@ int ext2_fat_install_file(const char *path, int devfd, struct stat *rst)
 	unlink(oldfile);
     }
 
+    fd = open(c32file, O_WRONLY | O_TRUNC | O_CREAT | O_SYNC,
+	      S_IRUSR | S_IRGRP | S_IROTH);
+    if (fd < 0) {
+	perror(c32file);
+	goto bail;
+    }
+
+    r3 = xpwrite(fd, syslinux_ldlinuxc32, syslinux_ldlinuxc32_len, 0);
+    if (r3 != syslinux_ldlinuxc32_len) {
+	fprintf(stderr, "%s: write failure on %s\n", program, c32file);
+	goto bail;
+    }
+
     free(file);
     free(oldfile);
+    free(c32file);
     return 0;
 
 bail:
@@ -486,6 +502,7 @@ bail:
 
     free(file);
     free(oldfile);
+    free(c32file);
     return 1;
 }
 
@@ -494,6 +511,9 @@ bail:
    since the cow feature of btrfs will move the ldlinux.sys every where */
 int btrfs_install_file(const char *path, int devfd, struct stat *rst)
 {
+    char *file;
+    int fd, rv;
+
     patch_file_and_bootblock(-1, path, devfd);
     if (xpwrite(devfd, boot_image, boot_image_len, BTRFS_EXTLINUX_OFFSET)
 		!= boot_image_len) {
@@ -511,7 +531,37 @@ int btrfs_install_file(const char *path, int devfd, struct stat *rst)
 	perror(path);
 	return 1;
     }
-    return 0;
+
+    /*
+     * Note that we *can* install ldinux.c32 as a regular file because
+     * it doesn't need to be within the first 64K. The Syslinux core
+     * has enough smarts to search the btrfs dirs and find this file.
+     */
+    rv = asprintf(&file, "%s%sldlinux.c32",
+		  path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
+    if (rv < 0 || !file) {
+	perror(program);
+	return 1;
+    }
+
+    fd = open(file, O_WRONLY | O_TRUNC | O_CREAT | O_SYNC,
+	      S_IRUSR | S_IRGRP | S_IROTH);
+    if (fd < 0) {
+	perror(file);
+	free(file);
+	return 1;
+    }
+
+    rv = xpwrite(fd, syslinux_ldlinuxc32, syslinux_ldlinuxc32_len, 0);
+    if (rv != (int)syslinux_ldlinuxc32_len) {
+	fprintf(stderr, "%s: write failure on %s\n", program, file);
+	rv = 1;
+    } else
+	rv = 0;
+
+    close(fd);
+    free(file);
+    return rv;
 }
 
 /*
diff --git a/libinstaller/Makefile b/libinstaller/Makefile
index e67a468..63446a1 100644
--- a/libinstaller/Makefile
+++ b/libinstaller/Makefile
@@ -1,6 +1,6 @@
 # _bin.c files required by both BTARGET and ITARGET installers
 BINFILES = bootsect_bin.c ldlinux_bin.c \
-	   mbr_bin.c gptmbr_bin.c
+	   mbr_bin.c gptmbr_bin.c ldlinuxc32_bin.c
 
 PERL	 = perl
 
@@ -18,6 +18,9 @@ mbr_bin.c: ../mbr/mbr.bin bin2c.pl
 gptmbr_bin.c: ../mbr/gptmbr.bin bin2c.pl
 	$(PERL) bin2c.pl syslinux_gptmbr < $< > $@
 
+ldlinuxc32_bin.c: ../com32/elflink/ldlinux/ldlinux.c32 bin2c.pl
+	$(PERL) bin2c.pl syslinux_ldlinuxc32 < $< > $@
+
 tidy:
 	rm -f $(BINFILES)
 
diff --git a/libinstaller/syslinux.h b/libinstaller/syslinux.h
index 8b86f88..f60a066 100644
--- a/libinstaller/syslinux.h
+++ b/libinstaller/syslinux.h
@@ -26,6 +26,9 @@ extern unsigned char syslinux_ldlinux[];
 extern const unsigned int syslinux_ldlinux_len;
 extern const int syslinux_ldlinux_mtime;
 
+extern unsigned char syslinux_ldlinuxc32[];
+extern const unsigned int syslinux_ldlinuxc32_len;
+
 #define boot_sector	syslinux_bootsect
 #define boot_sector_len syslinux_bootsect_len
 #define boot_image	syslinux_ldlinux
diff --git a/linux/Makefile b/linux/Makefile
index 08a3ed4..d7facaf 100644
--- a/linux/Makefile
+++ b/linux/Makefile
@@ -31,6 +31,7 @@ SRCS     = syslinux.c \
            ../libinstaller/fs.c \
            ../libinstaller/syslxmod.c \
 	   ../libinstaller/bootsect_bin.c \
+	   ../libinstaller/ldlinuxc32_bin.c \
 	   ../libinstaller/ldlinux_bin.c
 OBJS	 = $(patsubst %.c,%.o,$(notdir $(SRCS)))
 
diff --git a/linux/syslinux.c b/linux/syslinux.c
index 4b13b7f..f4749ea 100755
--- a/linux/syslinux.c
+++ b/linux/syslinux.c
@@ -238,6 +238,24 @@ int modify_existing_adv(const char *path)
     return 0;
 }
 
+int do_open_file(char *name)
+{
+    int fd;
+
+    if ((fd = open(name, O_RDONLY)) >= 0) {
+	uint32_t zero_attr = 0;
+	ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &zero_attr);
+	close(fd);
+    }
+
+    unlink(name);
+    fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0444);
+    if (fd < 0)
+	perror(opt.device);
+
+    return fd;
+}
+
 int main(int argc, char *argv[])
 {
     static unsigned char sectbuf[SECTOR_SIZE];
@@ -253,7 +271,7 @@ int main(int argc, char *argv[])
     const char *errmsg;
     int mnt_cookie;
     int patch_sectors;
-    int i;
+    int i, rv;
 
     mypid = getpid();
     umask(077);
@@ -408,16 +426,8 @@ int main(int argc, char *argv[])
     if (modify_adv() < 0)
 	exit(1);
 
-    if ((fd = open(ldlinux_name, O_RDONLY)) >= 0) {
-	uint32_t zero_attr = 0;
-	ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &zero_attr);
-	close(fd);
-    }
-
-    unlink(ldlinux_name);
-    fd = open(ldlinux_name, O_WRONLY | O_CREAT | O_TRUNC, 0444);
+    fd = do_open_file(ldlinux_name);
     if (fd < 0) {
-	perror(opt.device);
 	err = 1;
 	goto umount;
     }
@@ -451,6 +461,31 @@ int main(int argc, char *argv[])
     close(fd);
     sync();
 
+    sprintf(ldlinux_name, "%sldlinux.c32", ldlinux_path);
+    fd = do_open_file(ldlinux_name);
+    if (fd < 0) {
+	err = 1;
+	goto umount;
+    }
+
+    rv = xpwrite(fd, syslinux_ldlinuxc32, syslinux_ldlinuxc32_len, 0);
+    if (rv != (int)syslinux_ldlinuxc32_len) {
+	fprintf(stderr, "%s: write failure on %s\n", program, ldlinux_name);
+	exit(1);
+    }
+
+    fsync(fd);
+    /*
+     * Set the attributes
+     */
+    {
+	uint32_t attr = 0x07;	/* Hidden+System+Readonly */
+	ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
+    }
+
+    close(fd);
+    sync();
+
 umount:
     do_umount(mntpath, mnt_cookie);
     sync();
diff --git a/mtools/Makefile b/mtools/Makefile
index 78cea1e..6df18b5 100755
--- a/mtools/Makefile
+++ b/mtools/Makefile
@@ -14,6 +14,7 @@ SRCS     = syslinux.c \
 	   ../libinstaller/setadv.c \
 	   ../libinstaller/bootsect_bin.c \
 	   ../libinstaller/ldlinux_bin.c \
+	   ../libinstaller/ldlinuxc32_bin.c \
 	   $(wildcard ../libfat/*.c)
 OBJS	 = $(patsubst %.c,%.o,$(notdir $(SRCS)))
 
diff --git a/mtools/syslinux.c b/mtools/syslinux.c
index c65021b..f43b5a5 100755
--- a/mtools/syslinux.c
+++ b/mtools/syslinux.c
@@ -125,6 +125,64 @@ int libfat_xpread(intptr_t pp, void *buf, size_t secsize,
     return xpread(pp, buf, secsize, offset);
 }
 
+static int move_file(char *filename)
+{
+    char target_file[4096], command[5120];
+    char *cp = target_file, *ep = target_file + sizeof target_file - 16;
+    const char *sd;
+    int slash = 1;
+    int status;
+
+    cp += sprintf(cp, "'s:/");
+    for (sd = opt.directory; *sd; sd++) {
+	if (*sd == '/' || *sd == '\\') {
+	    if (slash)
+		continue;	/* Remove duplicated slashes */
+	    slash = 1;
+	} else if (*sd == '\'' || *sd == '!') {
+	    slash = 0;
+	    if (cp < ep)
+		*cp++ = '\'';
+	    if (cp < ep)
+		*cp++ = '\\';
+	    if (cp < ep)
+		*cp++ = *sd;
+	    if (cp < ep)
+		*cp++ = '\'';
+	    continue;
+	} else {
+	    slash = 0;
+	}
+
+	if (cp < ep)
+	    *cp++ = *sd;
+    }
+    if (!slash)
+	*cp++ = '/';
+    sprintf(cp, "%s'", filename);
+
+    /* This command may fail legitimately */
+    sprintf(command, "mattrib -h -r -s %s 2>/dev/null", target_file);
+    status = system(command);
+    (void)status;		/* Keep _FORTIFY_SOURCE happy */
+
+    sprintf(command, "mmove -D o -D O s:/%s %s", filename, target_file);
+    status = system(command);
+
+    if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+	fprintf(stderr,
+		"%s: warning: unable to move %s\n", program, filename);
+
+	sprintf(command, "mattrib +r +h +s s:/%s", filename);
+	status = system(command);
+    } else {
+	sprintf(command, "mattrib +r +h +s %s", target_file);
+	status = system(command);
+    }
+
+    return status;
+}
+
 int main(int argc, char *argv[])
 {
     static unsigned char sectbuf[SECTOR_SIZE];
@@ -284,63 +342,38 @@ int main(int argc, char *argv[])
 
     /* Move ldlinux.sys to the desired location */
     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 = opt.directory; *sd; sd++) {
-	    if (*sd == '/' || *sd == '\\') {
-		if (slash)
-		    continue;	/* Remove duplicated slashes */
-		slash = 1;
-	    } else if (*sd == '\'' || *sd == '!') {
-		slash = 0;
-		if (cp < ep)
-		    *cp++ = '\'';
-		if (cp < ep)
-		    *cp++ = '\\';
-		if (cp < ep)
-		    *cp++ = *sd;
-		if (cp < ep)
-		    *cp++ = '\'';
-		continue;
-	    } else {
-		slash = 0;
-	    }
-
-	    if (cp < ep)
-		*cp++ = *sd;
-	}
-	if (!slash)
-	    *cp++ = '/';
-	strcpy(cp, "ldlinux.sys'");
+	status = move_file("ldlinux.sys");
+    } else {
+	status = system("mattrib +r +h +s s:/ldlinux.sys");
+    }
 
-	/* This command may fail legitimately */
-	sprintf(command, "mattrib -h -r -s %s 2>/dev/null", target_file);
-	status = system(command);
-	(void)status;		/* Keep _FORTIFY_SOURCE happy */
+    if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+	fprintf(stderr,
+		"%s: warning: failed to set system bit on ldlinux.sys\n",
+		program);
+    }
 
-	sprintf(command, "mmove -D o -D O s:/ldlinux.sys %s", target_file);
-	status = system(command);
+    /* This command may fail legitimately */
+    status = system("mattrib -h -r -s s:/ldlinux.c32 2>/dev/null");
+    (void)status;		/* Keep _FORTIFY_SOURCE happy */
 
-	if (!WIFEXITED(status) || WEXITSTATUS(status)) {
-	    fprintf(stderr,
-		    "%s: warning: unable to move ldlinux.sys\n", program);
+    mtp = popen("mcopy -D o -D O -o - s:/ldlinux.c32", "w");
+    if (!mtp ||	fwrite(syslinux_ldlinuxc32, 1, syslinux_ldlinuxc32_len, mtp)
+	!= syslinux_ldlinuxc32_len ||
+	(status = pclose(mtp), !WIFEXITED(status) || WEXITSTATUS(status))) {
+	die("failed to create ldlinux.c32");
+    }
 
-	    status = system("mattrib +r +h +s s:/ldlinux.sys");
-	} else {
-	    sprintf(command, "mattrib +r +h +s %s", target_file);
-	    status = system(command);
-	}
+    /* Move ldlinux.c32 to the desired location */
+    if (opt.directory) {
+	status = move_file("ldlinux.c32");
     } else {
-	status = system("mattrib +r +h +s s:/ldlinux.sys");
+	status = system("mattrib +r +h +s s:/ldlinux.c32");
     }
 
     if (!WIFEXITED(status) || WEXITSTATUS(status)) {
 	fprintf(stderr,
-		"%s: warning: failed to set system bit on ldlinux.sys\n",
+		"%s: warning: failed to set system bit on ldlinux.c32\n",
 		program);
     }
 
diff --git a/win/syslinux.c b/win/syslinux.c
index 669450e..f8e2780 100644
--- a/win/syslinux.c
+++ b/win/syslinux.c
@@ -236,6 +236,53 @@ int libfat_readfile(intptr_t pp, void *buf, size_t secsize,
     return secsize;
 }
 
+static void move_file(char *pathname, char *filename)
+{
+    char new_name[strlen(opt.directory) + 16];
+    char *cp = new_name + 3;
+    const char *sd;
+    int slash = 1;
+
+    new_name[0] = opt.device[0];
+    new_name[1] = ':';
+    new_name[2] = '\\';
+
+    for (sd = opt.directory; *sd; sd++) {
+	char c = *sd;
+
+	if (c == '/' || c == '\\') {
+	    if (slash)
+		continue;
+	    c = '\\';
+	    slash = 1;
+	} else {
+	    slash = 0;
+	}
+
+	*cp++ = c;
+    }
+
+    /* Skip if subdirectory == root */
+    if (cp > new_name + 3) {
+	if (!slash)
+	    *cp++ = '\\';
+
+	memcpy(cp, filename, 12);
+
+	/* Delete any previous file */
+	SetFileAttributes(pathname, FILE_ATTRIBUTE_NORMAL);
+	DeleteFile(pathname);
+	if (!MoveFile(pathname, new_name))
+	    SetFileAttributes(pathname, FILE_ATTRIBUTE_READONLY |
+			      FILE_ATTRIBUTE_SYSTEM |
+			      FILE_ATTRIBUTE_HIDDEN);
+	else
+	    SetFileAttributes(new_name, FILE_ATTRIBUTE_READONLY |
+			      FILE_ATTRIBUTE_SYSTEM |
+			      FILE_ATTRIBUTE_HIDDEN);
+    }
+}
+
 int main(int argc, char *argv[])
 {
     HANDLE f_handle, d_handle;
@@ -249,6 +296,7 @@ int main(int argc, char *argv[])
     static char drive_name[] = "\\\\.\\?:";
     static char drive_root[] = "?:\\";
     static char ldlinux_name[] = "?:\\ldlinux.sys";
+    static char ldlinuxc32_name[] = "?:\\ldlinux.c32";
     const char *errmsg;
     struct libfat_filesystem *fs;
     libfat_sector_t s, *secp;
@@ -290,6 +338,7 @@ int main(int argc, char *argv[])
     /* Determines the drive type */
     drive_name[4] = opt.device[0];
     ldlinux_name[0] = opt.device[0];
+    ldlinuxc32_name[0] = opt.device[0];
     drive_root[0] = opt.device[0];
     drive_type = GetDriveType(drive_root);
 
@@ -340,10 +389,12 @@ int main(int argc, char *argv[])
     /* Change to normal attributes to enable deletion */
     /* Just ignore error if the file do not exists */
     SetFileAttributes(ldlinux_name, FILE_ATTRIBUTE_NORMAL);
+    SetFileAttributes(ldlinuxc32_name, FILE_ATTRIBUTE_NORMAL);
 
     /* Delete the file */
     /* Just ignore error if the file do not exists */
     DeleteFile(ldlinux_name);
+    DeleteFile(ldlinuxc32_name);
 
     /* Initialize the ADV -- this should be smarter */
     syslinux_reset_adv(syslinux_adv);
@@ -463,52 +514,40 @@ map_done:
     CloseHandle(f_handle);
 
     /* Move the file to the desired location */
-    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] = opt.device[0];
-	new_ldlinux_name[1] = ':';
-	new_ldlinux_name[2] = '\\';
-
-	for (sd = opt.directory; *sd; sd++) {
-	    char c = *sd;
-
-	    if (c == '/' || c == '\\') {
-		if (slash)
-		    continue;
-		c = '\\';
-		slash = 1;
-	    } else {
-		slash = 0;
-	    }
+    if (opt.directory)
+	move_file(ldlinux_name, "ldlinux.sys");
 
-	    *cp++ = c;
-	}
+    f_handle = CreateFile(ldlinuxc32_name, GENERIC_READ | GENERIC_WRITE,
+			  FILE_SHARE_READ | FILE_SHARE_WRITE,
+			  NULL, CREATE_ALWAYS,
+			  FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM |
+			  FILE_ATTRIBUTE_HIDDEN, NULL);
 
-	/* Skip if subdirectory == root */
-	if (cp > new_ldlinux_name + 3) {
-	    if (!slash)
-		*cp++ = '\\';
-
-	    memcpy(cp, "ldlinux.sys", 12);
-
-	    /* Delete any previous file */
-	    SetFileAttributes(new_ldlinux_name, FILE_ATTRIBUTE_NORMAL);
-	    DeleteFile(new_ldlinux_name);
-	    if (!MoveFile(ldlinux_name, new_ldlinux_name))
-		SetFileAttributes(ldlinux_name, FILE_ATTRIBUTE_READONLY |
-				  FILE_ATTRIBUTE_SYSTEM |
-				  FILE_ATTRIBUTE_HIDDEN);
-	    else
-		SetFileAttributes(new_ldlinux_name, FILE_ATTRIBUTE_READONLY |
-				  FILE_ATTRIBUTE_SYSTEM |
-				  FILE_ATTRIBUTE_HIDDEN);
-	}
+    if (f_handle == INVALID_HANDLE_VALUE) {
+	error("Unable to create ldlinux.c32");
+	exit(1);
+    }
+
+    /* Write ldlinux.c32 file */
+    if (!WriteFile(f_handle, syslinux_ldlinuxc32, syslinux_ldlinuxc32_len,
+		   &bytes_written, NULL) ||
+	bytes_written != syslinux_ldlinuxc32_len) {
+	error("Could not write ldlinux.c32");
+	exit(1);
+    }
+
+    /* Now flush the media */
+    if (!FlushFileBuffers(f_handle)) {
+	error("FlushFileBuffers failed");
+	exit(1);
     }
 
+    CloseHandle(f_handle);
+
+    /* Move the file to the desired location */
+    if (opt.directory)
+	move_file(ldlinuxc32_name, "ldlinux.c32");
+
     /* Make the syslinux boot sector */
     syslinux_make_bootsect(sectbuf, fs_type);
 
diff --git a/win32/Makefile b/win32/Makefile
index f960998..9ff8a45 100644
--- a/win32/Makefile
+++ b/win32/Makefile
@@ -56,6 +56,7 @@ LIBSRC   = ../libinstaller/fs.c \
 	   ../libinstaller/getopt/getopt_long.c \
 	   ../libinstaller/bootsect_bin.c \
 	   ../libinstaller/ldlinux_bin.c \
+	   ../libinstaller/ldlinuxc32_bin.c \
 	   ../libinstaller/mbr_bin.c \
 	   $(wildcard ../libfat/*.c)
 LIBOBJS  = $(patsubst %.c,%.obj,$(notdir $(LIBSRC)))
diff --git a/win64/Makefile b/win64/Makefile
index fe60793..50132d4 100644
--- a/win64/Makefile
+++ b/win64/Makefile
@@ -46,6 +46,7 @@ LIBSRC   = ../libinstaller/fs.c \
 	   ../libinstaller/getopt/getopt_long.c \
 	   ../libinstaller/bootsect_bin.c \
 	   ../libinstaller/ldlinux_bin.c \
+	   ../libinstaller/ldlinuxc32_bin.c \
 	   ../libinstaller/mbr_bin.c \
 	   $(wildcard ../libfat/*.c)
 LIBOBJS  = $(patsubst %.c,%.obj,$(notdir $(LIBSRC)))


More information about the Syslinux-commits mailing list