summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-06-20 17:01:15 -0700
committerH. Peter Anvin <hpa@zytor.com>2010-06-20 17:07:52 -0700
commit2ef260d392537d22c927735e6b9e78b02d36bb7b (patch)
tree2613b5e58834702827a0523df98b2fc24683f9b2
parent8cf2a1fb42a61f6d19afee86f52ff260fabd1cfa (diff)
downloadsyslinux-2ef260d392537d22c927735e6b9e78b02d36bb7b.tar.gz
Merge syslinux/extlinux patch code and core code
Merge the SYSLINUX and EXTLINUX patching code and core code, removing EXTLINUX as a separate derivative. All the disk-based systems now use the same code. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--core/Makefile7
-rw-r--r--core/extlinux.asm38
-rw-r--r--core/ldlinux.asm4
-rw-r--r--dos/Makefile1
-rw-r--r--dos/syslinux.c2
-rw-r--r--dosutil/mdiskchk.combin8184 -> 8246 bytes
-rw-r--r--extlinux/Makefile5
-rw-r--r--extlinux/fat.h57
-rw-r--r--extlinux/main.c210
-rw-r--r--libinstaller/Makefile7
-rw-r--r--libinstaller/fat.c129
-rw-r--r--libinstaller/syslinux.h3
-rw-r--r--libinstaller/syslxint.h2
-rw-r--r--libinstaller/syslxmod.c114
-rw-r--r--linux/Makefile5
-rw-r--r--linux/syslinux.c2
-rw-r--r--mtools/Makefile1
-rw-r--r--mtools/syslinux.c2
-rw-r--r--win32/Makefile1
-rw-r--r--win32/syslinux.c2
20 files changed, 190 insertions, 402 deletions
diff --git a/core/Makefile b/core/Makefile
index 166f0e4e..1330fb9e 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -33,7 +33,6 @@ CODEPAGE = cp865
# The targets to build in this directory...
BTARGET = kwdhash.gen \
- extlinux.bin extlinux.bss extlinux.sys \
ldlinux.bss ldlinux.sys ldlinux.bin \
isolinux.bin isolinux-debug.bin pxelinux.0
@@ -109,12 +108,6 @@ ldlinux.bss: ldlinux.bin
ldlinux.sys: ldlinux.bin
dd if=$< of=$@ bs=512 skip=1
-extlinux.bss: extlinux.bin
- dd if=$< of=$@ bs=512 count=1
-
-extlinux.sys: extlinux.bin
- dd if=$< of=$@ bs=512 skip=1
-
codepage.cp: ../codepage/$(CODEPAGE).cp
cp -f $< $@
diff --git a/core/extlinux.asm b/core/extlinux.asm
deleted file mode 100644
index 95385765..00000000
--- a/core/extlinux.asm
+++ /dev/null
@@ -1,38 +0,0 @@
-; -*- fundamental -*- (asm-mode sucks)
-; ****************************************************************************
-;
-; extlinux.asm
-;
-; A program to boot Linux kernels off an ext2/ext3 filesystem.
-;
-; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
-; Copyright 2009 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.
-;
-; ****************************************************************************
-
-%define IS_EXTLINUX 1
-%include "head.inc"
-
-;
-; Some semi-configurable constants... change on your own risk.
-;
-my_id equ extlinux_id
-
- section .rodata
- alignz 4
-ROOT_FS_OPS:
- extern vfat_fs_ops
- dd vfat_fs_ops
- extern ext2_fs_ops
- dd ext2_fs_ops
- extern btrfs_fs_ops
- dd btrfs_fs_ops
- dd 0
-
-%include "diskfs.inc"
diff --git a/core/ldlinux.asm b/core/ldlinux.asm
index 23540ea5..f62f55b2 100644
--- a/core/ldlinux.asm
+++ b/core/ldlinux.asm
@@ -35,6 +35,10 @@ my_id equ syslinux_id
ROOT_FS_OPS:
extern vfat_fs_ops
dd vfat_fs_ops
+ extern ext2_fs_ops
+ dd ext2_fs_ops
+ extern btrfs_fs_ops
+ dd btrfs_fs_ops
dd 0
%include "diskfs.inc"
diff --git a/dos/Makefile b/dos/Makefile
index 73925711..d4d20c7d 100644
--- a/dos/Makefile
+++ b/dos/Makefile
@@ -26,6 +26,7 @@ INCLUDES = -include code16.h -nostdinc -iwithprefix include \
-I. -I.. -I../libfat -I ../libinstaller
SRCS = syslinux.c \
+ ../libinstaller/fat.c \
../libinstaller/syslxmod.c \
../libinstaller/bootsect_bin.c \
../libinstaller/ldlinux_bin.c \
diff --git a/dos/syslinux.c b/dos/syslinux.c
index 94517e8f..5dc34836 100644
--- a/dos/syslinux.c
+++ b/dos/syslinux.c
@@ -755,7 +755,7 @@ int main(int argc, char *argv[])
/*
* Patch ldlinux.sys and the boot sector
*/
- i = syslinux_patch(sectors, nsectors, stupid, raid_mode, subdir);
+ i = syslinux_patch(sectors, nsectors, stupid, raid_mode, subdir, NULL);
patch_sectors = (i + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
/*
diff --git a/dosutil/mdiskchk.com b/dosutil/mdiskchk.com
index 5a6cc8e7..b18a187c 100644
--- a/dosutil/mdiskchk.com
+++ b/dosutil/mdiskchk.com
Binary files differ
diff --git a/extlinux/Makefile b/extlinux/Makefile
index ab92c2c6..2501a454 100644
--- a/extlinux/Makefile
+++ b/extlinux/Makefile
@@ -24,11 +24,12 @@ CFLAGS = $(GCCWARN) -Wno-sign-compare -D_FILE_OFFSET_BITS=64 \
LDFLAGS = # -s
SRCS = main.c \
+ ../libinstaller/syslxmod.c \
../libinstaller/syslxopt.c \
../libinstaller/syslxcom.c \
../libinstaller/setadv.c \
- ../libinstaller/extlinux_bss_bin.c \
- ../libinstaller/extlinux_sys_bin.c
+ ../libinstaller/bootsect_bin.c \
+ ../libinstaller/ldlinux_bin.c
OBJS = $(patsubst %.c,%.o,$(notdir $(SRCS)))
.SUFFIXES: .c .o .i .s .S
diff --git a/extlinux/fat.h b/extlinux/fat.h
index dd5a362a..5d13402d 100644
--- a/extlinux/fat.h
+++ b/extlinux/fat.h
@@ -2,61 +2,6 @@
#define _H_FAT_
#define MSDOS_SUPER_MAGIC 0x4d44 /* MD */
-#if 0
-/* FAT bootsector format, also used by other disk-based derivatives */
-struct boot_sector {
- uint8_t bsJump[3];
- char bsOemName[8];
- uint16_t bsBytesPerSec;
- uint8_t bsSecPerClust;
- uint16_t bsResSectors;
- uint8_t bsFATs;
- uint16_t bsRootDirEnts;
- uint16_t bsSectors;
- uint8_t bsMedia;
- uint16_t bsFATsecs;
- uint16_t bsSecPerTrack;
- uint16_t bsHeads;
- uint32_t bsHiddenSecs;
- uint32_t bsHugeSectors;
+/* The rest is defined in syslxint.h */
- union {
- struct {
- uint8_t DriveNumber;
- uint8_t Reserved1;
- uint8_t BootSignature;
- uint32_t VolumeID;
- char VolumeLabel[11];
- char FileSysType[8];
- uint8_t Code[442];
- } __attribute__ ((packed)) bs16;
- struct {
- uint32_t FATSz32;
- uint16_t ExtFlags;
- uint16_t FSVer;
- uint32_t RootClus;
- uint16_t FSInfo;
- uint16_t BkBootSec;
- uint8_t Reserved0[12];
- uint8_t DriveNumber;
- uint8_t Reserved1;
- uint8_t BootSignature;
- uint32_t VolumeID;
- char VolumeLabel[11];
- char FileSysType[8];
- uint8_t Code[414];
- } __attribute__ ((packed)) bs32;
- } __attribute__ ((packed));
-
- uint32_t NextSector; /* Pointer to the first unused sector */
- uint16_t MaxTransfer; /* Max sectors per transfer */
- uint16_t bsSignature;
-} __attribute__ ((packed));
-
-#define bsHead bsJump
-#define bsHeadLen offsetof(struct boot_sector, bsOemName)
-#define bsCode bs32.Code /* The common safe choice */
-#define bsCodeLen (offsetof(struct boot_sector, bsSignature) - \
- offsetof(struct boot_sector, bsCode))
-#endif
#endif
diff --git a/extlinux/main.c b/extlinux/main.c
index cf9840dd..c0a37ef1 100644
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -14,7 +14,7 @@
/*
* extlinux.c
*
- * Install the extlinux boot block on an fat, ext2/3/4 and btrfs filesystem
+ * Install the syslinux boot block on an fat, ext2/3/4 and btrfs filesystem
*/
#define _GNU_SOURCE /* Enable everything */
@@ -73,26 +73,6 @@ typedef uint64_t u64;
#define BTRFS_SUBVOL_MAX 256 /* By btrfs specification */
static char subvol[BTRFS_SUBVOL_MAX];
-/*
- * Boot block
- */
-extern unsigned char extlinux_bootsect[];
-extern unsigned int extlinux_bootsect_len;
-#undef boot_block
-#undef boot_block_len
-#define boot_block extlinux_bootsect
-#define boot_block_len extlinux_bootsect_len
-
-/*
- * Image file
- */
-extern unsigned char extlinux_image[];
-extern unsigned int extlinux_image_len;
-#undef boot_image
-#undef boot_image_len
-#define boot_image extlinux_image
-#define boot_image_len extlinux_image_len
-
#define BTRFS_ADV_OFFSET (BTRFS_EXTLINUX_OFFSET + boot_image_len)
/*
@@ -185,61 +165,6 @@ int get_geometry(int devfd, uint64_t totalbytes, struct hd_geometry *geo)
}
/*
- * Generate sector extents
- */
-static void generate_extents(struct syslinux_extent *ex, int nptrs,
- const sector_t *sectp, int nsect)
-{
- uint32_t addr = 0x7c00 + 2*SECTOR_SIZE;
- uint32_t base;
- sector_t sect, lba;
- unsigned int len;
-
- len = lba = base = 0;
-
- memset(ex, 0, nptrs * sizeof *ex);
-
- while (nsect) {
- sect = *sectp++;
-
- if (len && sect == lba + len &&
- ((addr ^ (base + len * SECTOR_SIZE)) & 0xffff0000) == 0) {
- /* We can add to the current extent */
- len++;
- goto next;
- }
-
- if (len) {
- set_64_sl(&ex->lba, lba);
- set_16_sl(&ex->len, len);
- ex++;
- }
-
- base = addr;
- lba = sect;
- len = 1;
-
- next:
- addr += SECTOR_SIZE;
- nsect--;
- }
-
- if (len) {
- set_64_sl(&ex->lba, lba);
- set_16_sl(&ex->len, len);
- ex++;
- }
-}
-
-/*
- * Form a pointer based on a 16-bit patcharea/epa field
- */
-static inline void *ptr(void *img, uint16_t *offset_p)
-{
- return (char *)img + get_16_sl(offset_p);
-}
-
-/*
* Query the device geometry and put it into the boot sector.
* Map the file and put the map in the boot sector and file.
* Stick the "current directory" inode number into the file.
@@ -253,15 +178,9 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
sector_t *sectp;
uint64_t totalbytes, totalsectors;
int nsect;
- uint32_t *wp;
struct boot_sector *sbs;
- struct patch_area *patcharea;
- struct ext_patch_area *epa;
- struct syslinux_extent *ex;
- int i, dw, nptrs;
- uint32_t csum;
char *dirpath, *subpath, *xdirpath, *xsubpath;
- uint64_t *advptrs;
+ int rv;
dirpath = realpath(dir, NULL);
if (!dirpath || stat(dir, &dirst)) {
@@ -318,7 +237,7 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
early bootstrap share code with the FAT version. */
dprintf("heads = %u, sect = %u\n", geo.heads, geo.sectors);
- sbs = (struct boot_sector *)boot_block;
+ sbs = (struct boot_sector *)syslinux_bootsect;
totalsectors = totalbytes >> SECTOR_SHIFT;
if (totalsectors >= 65536) {
@@ -333,7 +252,7 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
set_16(&sbs->bsHeads, geo.heads);
set_32(&sbs->bsHiddenSecs, geo.start);
- /* Construct the boot file */
+ /* Construct the boot file map */
dprintf("directory inode = %lu\n", (unsigned long)dirst.st_ino);
nsect = (boot_image_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
@@ -348,92 +267,15 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
int i;
for (i = 0; i < nsect; i++)
- *(sectp + i) = BTRFS_EXTLINUX_OFFSET/SECTOR_SIZE + i;
+ sectp[i] = BTRFS_EXTLINUX_OFFSET/SECTOR_SIZE + i;
}
- /* Search for LDLINUX_MAGIC to find the patch area */
- for (wp = (uint32_t *) boot_image; get_32_sl(wp) != LDLINUX_MAGIC;
- wp++)
- ;
- patcharea = (struct patch_area *)wp;
- epa = ptr(boot_image, &patcharea->epaoffset);
-
- /* First sector need pointer in boot sector */
- set_32(ptr(sbs, &epa->sect1ptr0), sectp[0]);
- set_32(ptr(sbs, &epa->sect1ptr1), sectp[0] >> 32);
- sectp++;
-
- /* Handle RAID mode */
- if (opt.raid_mode) {
- /* Patch in INT 18h = CD 18 */
- set_16(ptr(sbs, &epa->raidpatch), 0x18CD);
- }
-
- /* Set up the totals */
- dw = boot_image_len >> 2; /* COMPLETE dwords, excluding ADV */
- set_16_sl(&patcharea->data_sectors, nsect - 2); /* Not including ADVs */
- set_16_sl(&patcharea->adv_sectors, 2); /* ADVs need 2 sectors */
- set_32_sl(&patcharea->dwords, dw);
-
- /* Stupid mode? */
- if (opt.stupid_mode) {
- /* Access only one sector at a time */
- set_16_sl(&patcharea->maxtransfer, 1);
- }
-
- /* Set the sector extents */
- ex = ptr(boot_image, &epa->secptroffset);
- nptrs = get_16_sl(&epa->secptrcnt);
-
- if (nsect > nptrs) {
- /* Not necessarily an error in this case, but a general problem */
- fprintf(stderr, "Insufficient extent space, build error!\n");
- exit(1);
- }
-
- /* -1 for the pointer in the boot sector, -2 for the two ADVs */
- generate_extents(ex, nptrs, sectp, nsect-1-2);
-
- /* ADV pointers */
- advptrs = ptr(boot_image, &epa->advptroffset);
- set_64_sl(&advptrs[0], sectp[nsect-1-2]);
- set_64_sl(&advptrs[1], sectp[nsect-1-1]);
+ /* Create the modified image in memory */
+ rv = syslinux_patch(sectp, nsect, opt.stupid_mode,
+ opt.raid_mode, subpath, subvol);
- /* Poke in the base directory path */
- if (subpath) {
- int sublen = strlen(subpath) + 1;
- if (get_16_sl(&epa->dirlen) < sublen) {
- fprintf(stderr, "Subdirectory path too long... aborting install!\n");
- exit(1);
- }
- memcpy_to_sl(ptr(boot_image, &epa->diroffset), subpath, sublen);
- }
free(dirpath);
-
- /* Poke in the subvolume information */
- if (1 /* subvol */) {
- int sublen = strlen(subvol) + 1;
- if (get_16_sl(&epa->subvollen) < sublen) {
- fprintf(stderr, "Subvol name too long... aborting install!\n");
- exit(1);
- }
- memcpy_to_sl(ptr(boot_image, &epa->subvoloffset), subvol, sublen);
- }
-
- /* Now produce a checksum */
- set_32_sl(&patcharea->checksum, 0);
-
- csum = LDLINUX_MAGIC;
- for (i = 0, wp = (uint32_t *) boot_image; i < dw; i++, wp++)
- csum -= get_32_sl(wp); /* Negative checksum */
-
- set_32_sl(&patcharea->checksum, csum);
-
- /*
- * Assume all bytes modified. This can be optimized at the expense
- * of keeping track of what the highest modified address ever was.
- */
- return dw << 2;
+ return rv;
}
/*
@@ -503,7 +345,7 @@ int install_bootblock(int fd, const char *device)
return 1;
}
if (fs_type == VFAT) {
- struct boot_sector *sbs = (struct boot_sector *)extlinux_bootsect;
+ struct boot_sector *sbs = (struct boot_sector *)syslinux_bootsect;
if (xpwrite(fd, &sbs->bsHead, bsHeadLen, 0) != bsHeadLen ||
xpwrite(fd, &sbs->bsCode, bsCodeLen,
offsetof(struct boot_sector, bsCode)) != bsCodeLen) {
@@ -511,7 +353,8 @@ int install_bootblock(int fd, const char *device)
return 1;
}
} else {
- if (xpwrite(fd, boot_block, boot_block_len, 0) != boot_block_len) {
+ if (xpwrite(fd, syslinux_bootsect, syslinux_bootsect_len, 0)
+ != syslinux_bootsect_len) {
perror("writing bootblock");
return 1;
}
@@ -526,7 +369,7 @@ int ext2_fat_install_file(const char *path, int devfd, struct stat *rst)
int fd = -1, dirfd = -1;
int modbytes;
- asprintf(&file, "%s%sextlinux.sys",
+ asprintf(&file, "%s%sldlinux.sys",
path, path[0] && path[strlen(path) - 1] == '/' ? "" : "/");
if (!file) {
perror(program);
@@ -597,9 +440,9 @@ bail:
return 1;
}
-/* btrfs has to install the extlinux.sys in the first 64K blank area, which
+/* btrfs has to install the ldlinux.sys in the first 64K blank area, which
is not managered by btrfs tree, so actually this is not installed as files.
- since the cow feature of btrfs will move the extlinux.sys every where */
+ 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)
{
patch_file_and_bootblock(-1, path, devfd);
@@ -631,14 +474,17 @@ int install_file(const char *path, int devfd, struct stat *rst)
return 1;
}
-/* EXTLINUX installs the string 'EXTLINUX' at offset 3 in the boot
- sector; this is consistent with FAT filesystems. */
+/*
+ * SYSLINUX installs the string 'SYSLINUX' at offset 3 in the boot
+ * sector; this is consistent with FAT filesystems. Earlier versions
+ * would install the string "EXTLINUX" instead, handle both.
+ */
int already_installed(int devfd)
{
char buffer[8];
xpread(devfd, buffer, 8, 3);
- return !memcmp(buffer, "EXTLINUX", 8);
+ return !memcmp(buffer, "SYSLINUX", 8) || !memcmp(buffer, "EXTLINUX", 8);
}
#ifdef __KLIBC__
@@ -843,7 +689,7 @@ static int open_device(const char *path, struct stat *st, const char **_devname)
static int ext_read_adv(const char *path, const char *cfg, int devfd)
{
- if (fs_type == BTRFS) { /* btrfs "extlinux.sys" is in 64k blank area */
+ if (fs_type == BTRFS) { /* btrfs "ldlinux.sys" is in 64k blank area */
if (xpread(devfd, syslinux_adv, 2 * ADV_SIZE,
BTRFS_ADV_OFFSET) != 2 * ADV_SIZE) {
perror("btrfs writing adv");
@@ -856,7 +702,7 @@ static int ext_read_adv(const char *path, const char *cfg, int devfd)
static int ext_write_adv(const char *path, const char *cfg, int devfd)
{
- if (fs_type == BTRFS) { /* btrfs "extlinux.sys" is in 64k blank area */
+ if (fs_type == BTRFS) { /* btrfs "ldlinux.sys" is in 64k blank area */
if (xpwrite(devfd, syslinux_adv, 2 * ADV_SIZE,
BTRFS_ADV_OFFSET) != 2 * ADV_SIZE) {
perror("writing adv");
@@ -878,7 +724,7 @@ int install_loader(const char *path, int update_only)
return 1;
if (update_only && !already_installed(devfd)) {
- fprintf(stderr, "%s: no previous extlinux boot sector found\n",
+ fprintf(stderr, "%s: no previous syslinux boot sector found\n",
program);
close(devfd);
return 1;
@@ -887,7 +733,7 @@ int install_loader(const char *path, int update_only)
/* Read a pre-existing ADV, if already installed */
if (opt.reset_adv)
syslinux_reset_adv(syslinux_adv);
- else if (ext_read_adv(path, "extlinux.sys", devfd) < 0) {
+ else if (ext_read_adv(path, "ldlinux.sys", devfd) < 0) {
close(devfd);
return 1;
}
@@ -896,7 +742,7 @@ int install_loader(const char *path, int update_only)
return 1;
}
- /* Install extlinux.sys */
+ /* Install ldlinux.sys */
if (install_file(path, devfd, &fst)) {
close(devfd);
return 1;
@@ -929,7 +775,7 @@ int modify_existing_adv(const char *path)
if (opt.reset_adv)
syslinux_reset_adv(syslinux_adv);
- else if (ext_read_adv(path, "extlinux.sys", devfd) < 0) {
+ else if (ext_read_adv(path, "ldlinux.sys", devfd) < 0) {
close(devfd);
return 1;
}
@@ -937,7 +783,7 @@ int modify_existing_adv(const char *path)
close(devfd);
return 1;
}
- if (ext_write_adv(path, "extlinux.sys", devfd) < 0) {
+ if (ext_write_adv(path, "ldlinux.sys", devfd) < 0) {
close(devfd);
return 1;
}
diff --git a/libinstaller/Makefile b/libinstaller/Makefile
index 82c1990e..2beb9315 100644
--- a/libinstaller/Makefile
+++ b/libinstaller/Makefile
@@ -1,6 +1,5 @@
# _bin.c files required by both BTARGET and ITARGET installers
BINFILES = bootsect_bin.c ldlinux_bin.c \
- extlinux_bss_bin.c extlinux_sys_bin.c \
mbr_bin.c gptmbr_bin.c
PERL = perl
@@ -13,12 +12,6 @@ bootsect_bin.c: ../core/ldlinux.bss bin2c.pl
ldlinux_bin.c: ../core/ldlinux.sys bin2c.pl
$(PERL) bin2c.pl syslinux_ldlinux 512 < $< > $@
-extlinux_bss_bin.c: ../core/extlinux.bss bin2c.pl
- $(PERL) bin2c.pl extlinux_bootsect < $< > $@
-
-extlinux_sys_bin.c: ../core/extlinux.sys bin2c.pl
- $(PERL) bin2c.pl extlinux_image 512 < $< > $@
-
mbr_bin.c: ../mbr/mbr.bin bin2c.pl
$(PERL) bin2c.pl syslinux_mbr < $< > $@
diff --git a/libinstaller/fat.c b/libinstaller/fat.c
new file mode 100644
index 00000000..e2101353
--- /dev/null
+++ b/libinstaller/fat.c
@@ -0,0 +1,129 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1998-2008 H. Peter Anvin - All Rights Reserved
+ * 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
+ * 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * fat.c - Initial sanity check for FAT-based installers
+ */
+
+#define _XOPEN_SOURCE 500 /* Required on glibc 2.x */
+#define _BSD_SOURCE
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "syslinux.h"
+#include "syslxint.h"
+
+void syslinux_make_bootsect(void *bs)
+{
+ struct boot_sector *bootsect = bs;
+ const struct boot_sector *sbs =
+ (const struct boot_sector *)boot_sector;
+
+ memcpy(&bootsect->bsHead, &sbs->bsHead, bsHeadLen);
+ memcpy(&bootsect->bsCode, &sbs->bsCode, bsCodeLen);
+}
+
+/*
+ * Check to see that what we got was indeed an MS-DOS boot sector/superblock;
+ * Return NULL if OK and otherwise an error message;
+ */
+const char *syslinux_check_bootsect(const void *bs)
+{
+ int veryold;
+ int sectorsize;
+ long long sectors, fatsectors, dsectors;
+ long long clusters;
+ int rootdirents, clustersize;
+ const struct boot_sector *sectbuf = bs;
+
+ veryold = 0;
+
+ /* Must be 0xF0 or 0xF8..0xFF */
+ if (get_8(&sectbuf->bsMedia) != 0xF0 && get_8(&sectbuf->bsMedia) < 0xF8)
+ return "invalid media signature (not a FAT filesystem?)";
+
+ sectorsize = get_16(&sectbuf->bsBytesPerSec);
+ if (sectorsize == SECTOR_SIZE)
+ ; /* ok */
+ else if (sectorsize >= 512 && sectorsize <= 4096 &&
+ (sectorsize & (sectorsize - 1)) == 0)
+ return "unsupported sectors size";
+ else
+ return "impossible sector size";
+
+ clustersize = get_8(&sectbuf->bsSecPerClust);
+ if (clustersize == 0 || (clustersize & (clustersize - 1)))
+ return "impossible cluster size";
+
+ sectors = get_16(&sectbuf->bsSectors);
+ sectors = sectors ? sectors : get_32(&sectbuf->bsHugeSectors);
+
+ dsectors = sectors - get_16(&sectbuf->bsResSectors);
+
+ fatsectors = get_16(&sectbuf->bsFATsecs);
+ fatsectors = fatsectors ? fatsectors : get_32(&sectbuf->bs32.FATSz32);
+ fatsectors *= get_8(&sectbuf->bsFATs);
+ dsectors -= fatsectors;
+
+ rootdirents = get_16(&sectbuf->bsRootDirEnts);
+ dsectors -= (rootdirents + sectorsize / 32 - 1) / sectorsize;
+
+ if (dsectors < 0)
+ return "negative number of data sectors";
+
+ if (fatsectors == 0)
+ return "zero FAT sectors";
+
+ clusters = dsectors / clustersize;
+
+ if (clusters < 0xFFF5) {
+ /* FAT12 or FAT16 */
+
+ if (!get_16(&sectbuf->bsFATsecs))
+ return "zero FAT sectors (FAT12/16)";
+
+ if (get_8(&sectbuf->bs16.BootSignature) == 0x29) {
+ if (!memcmp(&sectbuf->bs16.FileSysType, "FAT12 ", 8)) {
+ if (clusters >= 0xFF5)
+ return "more than 4084 clusters but claims FAT12";
+ } else if (!memcmp(&sectbuf->bs16.FileSysType, "FAT16 ", 8)) {
+ if (clusters < 0xFF5)
+ return "less than 4084 clusters but claims FAT16";
+ } else if (!memcmp(&sectbuf->bs16.FileSysType, "FAT32 ", 8)) {
+ return "less than 65525 clusters but claims FAT32";
+ } else if (memcmp(&sectbuf->bs16.FileSysType, "FAT ", 8)) {
+ static char fserr[] =
+ "filesystem type \"????????\" not supported";
+ memcpy(fserr + 17, &sectbuf->bs16.FileSysType, 8);
+ return fserr;
+ }
+ }
+ } else if (clusters < 0x0FFFFFF5) {
+ /*
+ * FAT32...
+ *
+ * Moving the FileSysType and BootSignature was a lovely stroke
+ * of M$ idiocy...
+ */
+ if (get_8(&sectbuf->bs32.BootSignature) != 0x29 ||
+ memcmp(&sectbuf->bs32.FileSysType, "FAT32 ", 8))
+ return "missing FAT32 signature";
+ } else {
+ return "impossibly large number of clusters";
+ }
+
+ return NULL;
+}
diff --git a/libinstaller/syslinux.h b/libinstaller/syslinux.h
index bf2b716a..710d30e5 100644
--- a/libinstaller/syslinux.h
+++ b/libinstaller/syslinux.h
@@ -48,6 +48,7 @@ const char *syslinux_check_bootsect(const void *bs);
/* This patches the boot sector and ldlinux.sys based on a sector map */
typedef uint64_t sector_t;
int syslinux_patch(const sector_t *sectors, int nsectors,
- int stupid, int raid_mode, const char *subdir);
+ int stupid, int raid_mode,
+ const char *subdir, const char *subvol);
#endif
diff --git a/libinstaller/syslxint.h b/libinstaller/syslxint.h
index 3af7c3d7..f16c2e5c 100644
--- a/libinstaller/syslxint.h
+++ b/libinstaller/syslxint.h
@@ -238,7 +238,7 @@ struct boot_sector {
} __attribute__ ((packed));
#define bsHead bsJump
-#define bsHeadLen offsetof(struct boot_sector, bsOemName)
+#define bsHeadLen offsetof(struct boot_sector, bsBytesPerSec)
#define bsCode bs32.Code /* The common safe choice */
#define bsCodeLen (offsetof(struct boot_sector, bsSignature) - \
offsetof(struct boot_sector, bsCode))
diff --git a/libinstaller/syslxmod.c b/libinstaller/syslxmod.c
index 6f5adca5..a68f19fb 100644
--- a/libinstaller/syslxmod.c
+++ b/libinstaller/syslxmod.c
@@ -26,107 +26,6 @@
#include "syslinux.h"
#include "syslxint.h"
-void syslinux_make_bootsect(void *bs)
-{
- struct boot_sector *bootsect = bs;
- const struct boot_sector *sbs =
- (const struct boot_sector *)boot_sector;
-
- memcpy(&bootsect->bsHead, &sbs->bsHead, bsHeadLen);
- memcpy(&bootsect->bsCode, &sbs->bsCode, bsCodeLen);
-}
-
-/*
- * Check to see that what we got was indeed an MS-DOS boot sector/superblock;
- * Return NULL if OK and otherwise an error message;
- */
-const char *syslinux_check_bootsect(const void *bs)
-{
- int veryold;
- int sectorsize;
- long long sectors, fatsectors, dsectors;
- long long clusters;
- int rootdirents, clustersize;
- const struct boot_sector *sectbuf = bs;
-
- veryold = 0;
-
- /* Must be 0xF0 or 0xF8..0xFF */
- if (get_8(&sectbuf->bsMedia) != 0xF0 && get_8(&sectbuf->bsMedia) < 0xF8)
- return "invalid media signature (not a FAT filesystem?)";
-
- sectorsize = get_16(&sectbuf->bsBytesPerSec);
- if (sectorsize == SECTOR_SIZE)
- ; /* ok */
- else if (sectorsize >= 512 && sectorsize <= 4096 &&
- (sectorsize & (sectorsize - 1)) == 0)
- return "unsupported sectors size";
- else
- return "impossible sector size";
-
- clustersize = get_8(&sectbuf->bsSecPerClust);
- if (clustersize == 0 || (clustersize & (clustersize - 1)))
- return "impossible cluster size";
-
- sectors = get_16(&sectbuf->bsSectors);
- sectors = sectors ? sectors : get_32(&sectbuf->bsHugeSectors);
-
- dsectors = sectors - get_16(&sectbuf->bsResSectors);
-
- fatsectors = get_16(&sectbuf->bsFATsecs);
- fatsectors = fatsectors ? fatsectors : get_32(&sectbuf->bs32.FATSz32);
- fatsectors *= get_8(&sectbuf->bsFATs);
- dsectors -= fatsectors;
-
- rootdirents = get_16(&sectbuf->bsRootDirEnts);
- dsectors -= (rootdirents + sectorsize / 32 - 1) / sectorsize;
-
- if (dsectors < 0)
- return "negative number of data sectors";
-
- if (fatsectors == 0)
- return "zero FAT sectors";
-
- clusters = dsectors / clustersize;
-
- if (clusters < 0xFFF5) {
- /* FAT12 or FAT16 */
-
- if (!get_16(&sectbuf->bsFATsecs))
- return "zero FAT sectors (FAT12/16)";
-
- if (get_8(&sectbuf->bs16.BootSignature) == 0x29) {
- if (!memcmp(&sectbuf->bs16.FileSysType, "FAT12 ", 8)) {
- if (clusters >= 0xFF5)
- return "more than 4084 clusters but claims FAT12";
- } else if (!memcmp(&sectbuf->bs16.FileSysType, "FAT16 ", 8)) {
- if (clusters < 0xFF5)
- return "less than 4084 clusters but claims FAT16";
- } else if (!memcmp(&sectbuf->bs16.FileSysType, "FAT32 ", 8)) {
- return "less than 65525 clusters but claims FAT32";
- } else if (memcmp(&sectbuf->bs16.FileSysType, "FAT ", 8)) {
- static char fserr[] =
- "filesystem type \"????????\" not supported";
- memcpy(fserr + 17, &sectbuf->bs16.FileSysType, 8);
- return fserr;
- }
- }
- } else if (clusters < 0x0FFFFFF5) {
- /*
- * FAT32...
- *
- * Moving the FileSysType and BootSignature was a lovely stroke
- * of M$ idiocy...
- */
- if (get_8(&sectbuf->bs32.BootSignature) != 0x29 ||
- memcmp(&sectbuf->bs32.FileSysType, "FAT32 ", 8))
- return "missing FAT32 signature";
- } else {
- return "impossibly large number of clusters";
- }
-
- return NULL;
-}
/*
* Generate sector extents
@@ -197,7 +96,8 @@ static inline void *ptr(void *img, uint16_t *offset_p)
#define NADV 2
int syslinux_patch(const sector_t *sectp, int nsectors,
- int stupid, int raid_mode, const char *subdir)
+ int stupid, int raid_mode,
+ const char *subdir, const char *subvol)
{
struct patch_area *patcharea;
struct ext_patch_area *epa;
@@ -270,6 +170,16 @@ int syslinux_patch(const sector_t *sectp, int nsectors,
memcpy_to_sl(ptr(boot_image, &epa->diroffset), subdir, sublen);
}
+ /* Poke in the subvolume information */
+ if (subvol) {
+ int sublen = strlen(subvol) + 1;
+ if (get_16_sl(&epa->subvollen) < sublen) {
+ fprintf(stderr, "Subvol name too long... aborting install!\n");
+ exit(1);
+ }
+ memcpy_to_sl(ptr(boot_image, &epa->subvoloffset), subvol, sublen);
+ }
+
/* Now produce a checksum */
set_32_sl(&patcharea->checksum, 0);
diff --git a/linux/Makefile b/linux/Makefile
index 9bf56d12..c3877f23 100644
--- a/linux/Makefile
+++ b/linux/Makefile
@@ -17,15 +17,16 @@
topdir = ..
include $(topdir)/MCONFIG
-OPTFLAGS = -g -Os
+OPTFLAGS = -g -O0 -Dalloca=malloc
INCLUDES = -I. -I.. -I../libinstaller
CFLAGS = $(GCCWARN) -D_FILE_OFFSET_BITS=64 $(OPTFLAGS) $(INCLUDES)
-LDFLAGS = -s
+LDFLAGS =
SRCS = syslinux.c \
../libinstaller/syslxopt.c \
../libinstaller/syslxcom.c \
../libinstaller/setadv.c \
+ ../libinstaller/fat.c \
../libinstaller/syslxmod.c \
../libinstaller/bootsect_bin.c \
../libinstaller/ldlinux_bin.c
diff --git a/linux/syslinux.c b/linux/syslinux.c
index 20de62ae..7152d2bc 100644
--- a/linux/syslinux.c
+++ b/linux/syslinux.c
@@ -474,7 +474,7 @@ umount:
* Patch ldlinux.sys and the boot sector
*/
i = syslinux_patch(sectors, ldlinux_sectors, opt.stupid_mode,
- opt.raid_mode, subdir);
+ opt.raid_mode, subdir, NULL);
patch_sectors = (i + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
/*
diff --git a/mtools/Makefile b/mtools/Makefile
index 91b68527..5f08b2d3 100644
--- a/mtools/Makefile
+++ b/mtools/Makefile
@@ -7,6 +7,7 @@ CFLAGS = $(GCCWARN) -D_FILE_OFFSET_BITS=64 $(OPTFLAGS) $(INCLUDES)
LDFLAGS = -s
SRCS = syslinux.c \
+ ../libinstaller/fat.c \
../libinstaller/syslxmod.c \
../libinstaller/bootsect_bin.c \
../libinstaller/ldlinux_bin.c \
diff --git a/mtools/syslinux.c b/mtools/syslinux.c
index 2b82b33e..0f4ccf9c 100644
--- a/mtools/syslinux.c
+++ b/mtools/syslinux.c
@@ -267,7 +267,7 @@ 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);
+ i = syslinux_patch(sectors, nsectors, stupid, raid_mode, subdir, NULL);
patch_sectors = (i + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
/* Write the now-patched first sectors of ldlinux.sys */
diff --git a/win32/Makefile b/win32/Makefile
index a0be1d46..af95b2e6 100644
--- a/win32/Makefile
+++ b/win32/Makefile
@@ -45,6 +45,7 @@ WINCC_IS_GOOD := $(shell $(WINCC) $(WINCFLAGS) $(WINLDFLAGS) -o hello.exe hello.
.SUFFIXES: .c .o .i .s .S
SRCS = syslinux.c \
+ ../libinstaller/fat.c \
../libinstaller/syslxmod.c \
../libinstaller/bootsect_bin.c \
../libinstaller/ldlinux_bin.c \
diff --git a/win32/syslinux.c b/win32/syslinux.c
index bd042739..297b97b5 100644
--- a/win32/syslinux.c
+++ b/win32/syslinux.c
@@ -433,7 +433,7 @@ int main(int argc, char *argv[])
/*
* Patch ldlinux.sys and the boot sector
*/
- syslinux_patch(sectors, nsectors, stupid, raid_mode, subdir);
+ syslinux_patch(sectors, nsectors, stupid, raid_mode, subdir, NULL);
/*
* Rewrite the file