diff options
author | H. Peter Anvin <hpa@zytor.com> | 2010-06-20 17:01:15 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2010-06-20 17:07:52 -0700 |
commit | 2ef260d392537d22c927735e6b9e78b02d36bb7b (patch) | |
tree | 2613b5e58834702827a0523df98b2fc24683f9b2 | |
parent | 8cf2a1fb42a61f6d19afee86f52ff260fabd1cfa (diff) | |
download | syslinux-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/Makefile | 7 | ||||
-rw-r--r-- | core/extlinux.asm | 38 | ||||
-rw-r--r-- | core/ldlinux.asm | 4 | ||||
-rw-r--r-- | dos/Makefile | 1 | ||||
-rw-r--r-- | dos/syslinux.c | 2 | ||||
-rw-r--r-- | dosutil/mdiskchk.com | bin | 8184 -> 8246 bytes | |||
-rw-r--r-- | extlinux/Makefile | 5 | ||||
-rw-r--r-- | extlinux/fat.h | 57 | ||||
-rw-r--r-- | extlinux/main.c | 210 | ||||
-rw-r--r-- | libinstaller/Makefile | 7 | ||||
-rw-r--r-- | libinstaller/fat.c | 129 | ||||
-rw-r--r-- | libinstaller/syslinux.h | 3 | ||||
-rw-r--r-- | libinstaller/syslxint.h | 2 | ||||
-rw-r--r-- | libinstaller/syslxmod.c | 114 | ||||
-rw-r--r-- | linux/Makefile | 5 | ||||
-rw-r--r-- | linux/syslinux.c | 2 | ||||
-rw-r--r-- | mtools/Makefile | 1 | ||||
-rw-r--r-- | mtools/syslinux.c | 2 | ||||
-rw-r--r-- | win32/Makefile | 1 | ||||
-rw-r--r-- | win32/syslinux.c | 2 |
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 Binary files differindex 5a6cc8e7..b18a187c 100644 --- a/dosutil/mdiskchk.com +++ b/dosutil/mdiskchk.com 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(§buf->bsMedia) != 0xF0 && get_8(§buf->bsMedia) < 0xF8) + return "invalid media signature (not a FAT filesystem?)"; + + sectorsize = get_16(§buf->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(§buf->bsSecPerClust); + if (clustersize == 0 || (clustersize & (clustersize - 1))) + return "impossible cluster size"; + + sectors = get_16(§buf->bsSectors); + sectors = sectors ? sectors : get_32(§buf->bsHugeSectors); + + dsectors = sectors - get_16(§buf->bsResSectors); + + fatsectors = get_16(§buf->bsFATsecs); + fatsectors = fatsectors ? fatsectors : get_32(§buf->bs32.FATSz32); + fatsectors *= get_8(§buf->bsFATs); + dsectors -= fatsectors; + + rootdirents = get_16(§buf->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(§buf->bsFATsecs)) + return "zero FAT sectors (FAT12/16)"; + + if (get_8(§buf->bs16.BootSignature) == 0x29) { + if (!memcmp(§buf->bs16.FileSysType, "FAT12 ", 8)) { + if (clusters >= 0xFF5) + return "more than 4084 clusters but claims FAT12"; + } else if (!memcmp(§buf->bs16.FileSysType, "FAT16 ", 8)) { + if (clusters < 0xFF5) + return "less than 4084 clusters but claims FAT16"; + } else if (!memcmp(§buf->bs16.FileSysType, "FAT32 ", 8)) { + return "less than 65525 clusters but claims FAT32"; + } else if (memcmp(§buf->bs16.FileSysType, "FAT ", 8)) { + static char fserr[] = + "filesystem type \"????????\" not supported"; + memcpy(fserr + 17, §buf->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(§buf->bs32.BootSignature) != 0x29 || + memcmp(§buf->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(§buf->bsMedia) != 0xF0 && get_8(§buf->bsMedia) < 0xF8) - return "invalid media signature (not a FAT filesystem?)"; - - sectorsize = get_16(§buf->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(§buf->bsSecPerClust); - if (clustersize == 0 || (clustersize & (clustersize - 1))) - return "impossible cluster size"; - - sectors = get_16(§buf->bsSectors); - sectors = sectors ? sectors : get_32(§buf->bsHugeSectors); - - dsectors = sectors - get_16(§buf->bsResSectors); - - fatsectors = get_16(§buf->bsFATsecs); - fatsectors = fatsectors ? fatsectors : get_32(§buf->bs32.FATSz32); - fatsectors *= get_8(§buf->bsFATs); - dsectors -= fatsectors; - - rootdirents = get_16(§buf->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(§buf->bsFATsecs)) - return "zero FAT sectors (FAT12/16)"; - - if (get_8(§buf->bs16.BootSignature) == 0x29) { - if (!memcmp(§buf->bs16.FileSysType, "FAT12 ", 8)) { - if (clusters >= 0xFF5) - return "more than 4084 clusters but claims FAT12"; - } else if (!memcmp(§buf->bs16.FileSysType, "FAT16 ", 8)) { - if (clusters < 0xFF5) - return "less than 4084 clusters but claims FAT16"; - } else if (!memcmp(§buf->bs16.FileSysType, "FAT32 ", 8)) { - return "less than 65525 clusters but claims FAT32"; - } else if (memcmp(§buf->bs16.FileSysType, "FAT ", 8)) { - static char fserr[] = - "filesystem type \"????????\" not supported"; - memcpy(fserr + 17, §buf->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(§buf->bs32.BootSignature) != 0x29 || - memcmp(§buf->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 |