diff options
Diffstat (limited to 'contrib/syslinux-4.02/libinstaller')
19 files changed, 2084 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/libinstaller/Makefile b/contrib/syslinux-4.02/libinstaller/Makefile new file mode 100644 index 0000000..2beb931 --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/Makefile @@ -0,0 +1,28 @@ +# _bin.c files required by both BTARGET and ITARGET installers +BINFILES = bootsect_bin.c ldlinux_bin.c \ + mbr_bin.c gptmbr_bin.c + +PERL = perl + +all: $(BINFILES) + +bootsect_bin.c: ../core/ldlinux.bss bin2c.pl + $(PERL) bin2c.pl syslinux_bootsect < $< > $@ + +ldlinux_bin.c: ../core/ldlinux.sys bin2c.pl + $(PERL) bin2c.pl syslinux_ldlinux 512 < $< > $@ + +mbr_bin.c: ../mbr/mbr.bin bin2c.pl + $(PERL) bin2c.pl syslinux_mbr < $< > $@ + +gptmbr_bin.c: ../mbr/gptmbr.bin bin2c.pl + $(PERL) bin2c.pl syslinux_gptmbr < $< > $@ + +tidy: + rm -f $(BINFILES) + +clean: tidy + +dist: tidy + +spotless: clean diff --git a/contrib/syslinux-4.02/libinstaller/advconst.h b/contrib/syslinux-4.02/libinstaller/advconst.h new file mode 120000 index 0000000..044572b --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/advconst.h @@ -0,0 +1 @@ +../com32/include/syslinux/advconst.h
\ No newline at end of file diff --git a/contrib/syslinux-4.02/libinstaller/advio.c b/contrib/syslinux-4.02/libinstaller/advio.c new file mode 100644 index 0000000..56f607d --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/advio.c @@ -0,0 +1,162 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 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. + * + * ----------------------------------------------------------------------- */ + +/* + * advio.c + * + * Linux ADV I/O + * + * Return 0 on success, -1 on error, and set errno. + * + */ +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include "syslxint.h" +#include "syslxcom.h" + +/* + * Read the ADV from an existing instance, or initialize if invalid. + * Returns -1 on fatal errors, 0 if ADV is okay, 1 if the ADV is + * invalid, and 2 if the file does not exist. + */ +int read_adv(const char *path, const char *cfg) +{ + char *file; + int fd = -1; + struct stat st; + int err = 0; + int rv; + + rv = asprintf(&file, "%s%s%s", path, + path[0] && path[strlen(path) - 1] == '/' ? "" : "/", cfg); + + if (rv < 0 || !file) { + perror(program); + return -1; + } + + fd = open(file, O_RDONLY); + if (fd < 0) { + if (errno != ENOENT) { + err = -1; + } else { + syslinux_reset_adv(syslinux_adv); + err = 2; /* Nonexistence is not a fatal error */ + } + } else if (fstat(fd, &st)) { + err = -1; + } else if (st.st_size < 2 * ADV_SIZE) { + /* Too small to be useful */ + syslinux_reset_adv(syslinux_adv); + err = 0; /* Nothing to read... */ + } else if (xpread(fd, syslinux_adv, 2 * ADV_SIZE, + st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) { + err = -1; + } else { + /* We got it... maybe? */ + err = syslinux_validate_adv(syslinux_adv) ? 1 : 0; + } + + if (err < 0) + perror(file); + + if (fd >= 0) + close(fd); + + free(file); + + return err; +} + +/* + * Update the ADV in an existing installation. + */ +int write_adv(const char *path, const char *cfg) +{ + unsigned char advtmp[2 * ADV_SIZE]; + char *file; + int fd = -1; + struct stat st, xst; + int err = 0; + int rv; + + rv = asprintf(&file, "%s%s%s", path, + path[0] && path[strlen(path) - 1] == '/' ? "" : "/", cfg); + + if (rv < 0 || !file) { + perror(program); + return -1; + } + + fd = open(file, O_RDONLY); + if (fd < 0) { + err = -1; + } else if (fstat(fd, &st)) { + err = -1; + } else if (st.st_size < 2 * ADV_SIZE) { + /* Too small to be useful */ + err = -2; + } else if (xpread(fd, advtmp, 2 * ADV_SIZE, + st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) { + err = -1; + } else { + /* We got it... maybe? */ + err = syslinux_validate_adv(advtmp) ? -2 : 0; + if (!err) { + /* Got a good one, write our own ADV here */ + clear_attributes(fd); + + /* Need to re-open read-write */ + close(fd); + fd = open(file, O_RDWR | O_SYNC); + if (fd < 0) { + err = -1; + } else if (fstat(fd, &xst) || xst.st_ino != st.st_ino || + xst.st_dev != st.st_dev || xst.st_size != st.st_size) { + fprintf(stderr, "%s: race condition on write\n", file); + err = -2; + } + /* Write our own version ... */ + if (xpwrite(fd, syslinux_adv, 2 * ADV_SIZE, + st.st_size - 2 * ADV_SIZE) != 2 * ADV_SIZE) { + err = -1; + } + + sync(); + set_attributes(fd); + } + } + + if (err == -2) + fprintf(stderr, "%s: cannot write auxilliary data (need --update)?\n", + file); + else if (err == -1) + perror(file); + + if (fd >= 0) + close(fd); + if (file) + free(file); + + return err; +} diff --git a/contrib/syslinux-4.02/libinstaller/bin2c.pl b/contrib/syslinux-4.02/libinstaller/bin2c.pl new file mode 100755 index 0000000..07c11dd --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/bin2c.pl @@ -0,0 +1,78 @@ +#!/usr/bin/perl +## ----------------------------------------------------------------------- +## +## Copyright 1998-2008 H. Peter Anvin - All Rights Reserved +## +## 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. +## +## ----------------------------------------------------------------------- + +# +# bin2c.pl: binary file to C source converter +# + +eval { use bytes; }; +eval { binmode STDIN; }; + +($table_name, $pad) = @ARGV; + +if ( !defined($table_name) ) { + print STDERR "Usage: $0 table_name [pad] < input_file > output_file\n"; + exit 1; +} + +$pad = 1 if ($pad < 1); + +printf "unsigned char %s[] = {\n", $table_name; + +$pos = 0; +$linelen = 8; + +$total_len = 0; + +while ( ($n = read(STDIN, $data, 4096)) > 0 ) { + $total_len += $n; + for ( $i = 0 ; $i < $n ; $i++ ) { + $byte = substr($data, $i, 1); + if ( $pos >= $linelen ) { + print ",\n\t"; + $pos = 0; + } elsif ( $pos > 0 ) { + print ", "; + } else { + print "\t"; + } + printf("0x%02x", unpack("C", $byte)); + $pos++; + } +} + +$align = $total_len % $pad; +if ($align != 0) { + $n = $pad - $align; + $total_len += $n; + for ( $i = 0 ; $i < $n ; $i++ ) { + if ( $pos >= $linelen ) { + print ",\n\t"; + $pos = 0; + } elsif ( $pos > 0 ) { + print ", "; + } else { + print "\t"; + } + print '0x00'; + $pos++; + } +} + +printf "\n};\n\nconst unsigned int %s_len = %u;\n", $table_name, $total_len; + +@st = stat STDIN; + +printf "\nconst int %s_mtime = %d;\n", $table_name, $st[9]; + +exit 0; diff --git a/contrib/syslinux-4.02/libinstaller/fat.c b/contrib/syslinux-4.02/libinstaller/fat.c new file mode 100644 index 0000000..e210135 --- /dev/null +++ b/contrib/syslinux-4.02/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/contrib/syslinux-4.02/libinstaller/getopt/getopt.h b/contrib/syslinux-4.02/libinstaller/getopt/getopt.h new file mode 100644 index 0000000..a1b74b1 --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/getopt/getopt.h @@ -0,0 +1,25 @@ +#ifndef _GETOPT_H +#define _GETOPT_H + +/* (Very slightly) adapted from klibc */ + +struct option { + const char *name; + int has_arg; + int *flag; + int val; +}; + +enum { + no_argument = 0, + required_argument = 1, + optional_argument = 2, +}; + +extern char *optarg; +extern int optind, opterr, optopt; + +extern int getopt_long(int, char *const *, const char *, + const struct option *, int *); + +#endif /* _GETOPT_H */ diff --git a/contrib/syslinux-4.02/libinstaller/getopt/getopt_long.c b/contrib/syslinux-4.02/libinstaller/getopt/getopt_long.c new file mode 100644 index 0000000..cd7fef5 --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/getopt/getopt_long.c @@ -0,0 +1,152 @@ +/* + * getopt.c + * + * getopt_long(), or at least a common subset thereof: + * + * - Option reordering is not supported + * - -W foo is not supported + * - First optstring character "-" not supported. + */ + +#include <stdint.h> +#include <string.h> +#include <stddef.h> +#include <getopt.h> + +char *optarg; +int optind, opterr, optopt; +static struct getopt_private_state { + const char *optptr; + const char *last_optstring; + char *const *last_argv; +} pvt; + +static inline const char *option_matches(const char *arg_str, + const char *opt_name) +{ + while (*arg_str != '\0' && *arg_str != '=') { + if (*arg_str++ != *opt_name++) + return NULL; + } + + if (*opt_name) + return NULL; + + return arg_str; +} + +int getopt_long(int argc, char *const *argv, const char *optstring, + const struct option *longopts, int *longindex) +{ + const char *carg; + const char *osptr; + int opt; + + /* getopt() relies on a number of different global state + variables, which can make this really confusing if there is + more than one use of getopt() in the same program. This + attempts to detect that situation by detecting if the + "optstring" or "argv" argument have changed since last time + we were called; if so, reinitialize the query state. */ + + if (optstring != pvt.last_optstring || argv != pvt.last_argv || + optind < 1 || optind > argc) { + /* optind doesn't match the current query */ + pvt.last_optstring = optstring; + pvt.last_argv = argv; + optind = 1; + pvt.optptr = NULL; + } + + carg = argv[optind]; + + /* First, eliminate all non-option cases */ + + if (!carg || carg[0] != '-' || !carg[1]) + return -1; + + if (carg[1] == '-') { + const struct option *lo; + const char *opt_end = NULL; + + optind++; + + /* Either it's a long option, or it's -- */ + if (!carg[2]) { + /* It's -- */ + return -1; + } + + for (lo = longopts; lo->name; lo++) { + if ((opt_end = option_matches(carg+2, lo->name))) + break; + } + if (!opt_end) + return '?'; + + if (longindex) + *longindex = lo-longopts; + + if (*opt_end == '=') { + if (lo->has_arg) + optarg = (char *)opt_end+1; + else + return '?'; + } else if (lo->has_arg == 1) { + if (!(optarg = argv[optind])) + return '?'; + optind++; + } + + if (lo->flag) { + *lo->flag = lo->val; + return 0; + } else { + return lo->val; + } + } + + if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) { + /* Someone frobbed optind, change to new opt. */ + pvt.optptr = carg + 1; + } + + opt = *pvt.optptr++; + + if (opt != ':' && (osptr = strchr(optstring, opt))) { + if (osptr[1] == ':') { + if (*pvt.optptr) { + /* Argument-taking option with attached + argument */ + optarg = (char *)pvt.optptr; + optind++; + } else { + /* Argument-taking option with non-attached + argument */ + if (argv[optind + 1]) { + optarg = (char *)argv[optind+1]; + optind += 2; + } else { + /* Missing argument */ + optind++; + return (optstring[0] == ':') + ? ':' : '?'; + } + } + return opt; + } else { + /* Non-argument-taking option */ + /* pvt.optptr will remember the exact position to + resume at */ + if (!*pvt.optptr) + optind++; + return opt; + } + } else { + /* Unknown option */ + optopt = opt; + if (!*pvt.optptr) + optind++; + return '?'; + } +} diff --git a/contrib/syslinux-4.02/libinstaller/linux/fiemap.h b/contrib/syslinux-4.02/libinstaller/linux/fiemap.h new file mode 100644 index 0000000..d830747 --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/linux/fiemap.h @@ -0,0 +1,68 @@ +/* + * FS_IOC_FIEMAP ioctl infrastructure. + * + * Some portions copyright (C) 2007 Cluster File Systems, Inc + * + * Authors: Mark Fasheh <mfasheh@suse.com> + * Kalpak Shah <kalpak.shah@sun.com> + * Andreas Dilger <adilger@sun.com> + */ + +#ifndef _LINUX_FIEMAP_H +#define _LINUX_FIEMAP_H + +#include <linux/types.h> + +struct fiemap_extent { + __u64 fe_logical; /* logical offset in bytes for the start of + * the extent from the beginning of the file */ + __u64 fe_physical; /* physical offset in bytes for the start + * of the extent from the beginning of the disk */ + __u64 fe_length; /* length in bytes for this extent */ + __u64 fe_reserved64[2]; + __u32 fe_flags; /* FIEMAP_EXTENT_* flags for this extent */ + __u32 fe_reserved[3]; +}; + +struct fiemap { + __u64 fm_start; /* logical offset (inclusive) at + * which to start mapping (in) */ + __u64 fm_length; /* logical length of mapping which + * userspace wants (in) */ + __u32 fm_flags; /* FIEMAP_FLAG_* flags for request (in/out) */ + __u32 fm_mapped_extents;/* number of extents that were mapped (out) */ + __u32 fm_extent_count; /* size of fm_extents array (in) */ + __u32 fm_reserved; + struct fiemap_extent fm_extents[0]; /* array of mapped extents (out) */ +}; + +#define FIEMAP_MAX_OFFSET (~0ULL) + +#define FIEMAP_FLAG_SYNC 0x00000001 /* sync file data before map */ +#define FIEMAP_FLAG_XATTR 0x00000002 /* map extended attribute tree */ + +#define FIEMAP_FLAGS_COMPAT (FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR) + +#define FIEMAP_EXTENT_LAST 0x00000001 /* Last extent in file. */ +#define FIEMAP_EXTENT_UNKNOWN 0x00000002 /* Data location unknown. */ +#define FIEMAP_EXTENT_DELALLOC 0x00000004 /* Location still pending. + * Sets EXTENT_UNKNOWN. */ +#define FIEMAP_EXTENT_ENCODED 0x00000008 /* Data can not be read + * while fs is unmounted */ +#define FIEMAP_EXTENT_DATA_ENCRYPTED 0x00000080 /* Data is encrypted by fs. + * Sets EXTENT_NO_BYPASS. */ +#define FIEMAP_EXTENT_NOT_ALIGNED 0x00000100 /* Extent offsets may not be + * block aligned. */ +#define FIEMAP_EXTENT_DATA_INLINE 0x00000200 /* Data mixed with metadata. + * Sets EXTENT_NOT_ALIGNED.*/ +#define FIEMAP_EXTENT_DATA_TAIL 0x00000400 /* Multiple files in block. + * Sets EXTENT_NOT_ALIGNED.*/ +#define FIEMAP_EXTENT_UNWRITTEN 0x00000800 /* Space allocated, but + * no data (i.e. zero). */ +#define FIEMAP_EXTENT_MERGED 0x00001000 /* File does not natively + * support extents. Result + * merged for efficiency. */ +#define FIEMAP_EXTENT_SHARED 0x00002000 /* Space shared with other + * files. */ + +#endif /* _LINUX_FIEMAP_H */ diff --git a/contrib/syslinux-4.02/libinstaller/linux/loop.h b/contrib/syslinux-4.02/libinstaller/linux/loop.h new file mode 100644 index 0000000..90237a3 --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/linux/loop.h @@ -0,0 +1,96 @@ +#ifndef _LINUX_LOOP_H +#define _LINUX_LOOP_H + +/* + * include/linux/loop.h + * + * Written by Theodore Ts'o, 3/29/93. + * + * Copyright 1993 by Theodore Ts'o. Redistribution of this file is + * permitted under the GNU General Public License. + */ + +#define LO_NAME_SIZE 64 +#define LO_KEY_SIZE 32 + + +/* + * Loop flags + */ +enum { + LO_FLAGS_READ_ONLY = 1, + LO_FLAGS_USE_AOPS = 2, + LO_FLAGS_AUTOCLEAR = 4, +}; + +#include <asm/posix_types.h> /* for __kernel_old_dev_t */ +#include <linux/types.h> /* for __u64 */ +#include <linux/version.h> /* version of Linux kernel headers */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +/* We have truly ancient Linux kernel headers installed */ +typedef __kernel_dev_t __kernel_old_dev_t; +#endif + +/* Backwards compatibility version */ +struct loop_info { + int lo_number; /* ioctl r/o */ + __kernel_old_dev_t lo_device; /* ioctl r/o */ + unsigned long lo_inode; /* ioctl r/o */ + __kernel_old_dev_t lo_rdevice; /* ioctl r/o */ + int lo_offset; + int lo_encrypt_type; + int lo_encrypt_key_size; /* ioctl w/o */ + int lo_flags; /* ioctl r/o */ + char lo_name[LO_NAME_SIZE]; + unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ + unsigned long lo_init[2]; + char reserved[4]; +}; + +struct loop_info64 { + __u64 lo_device; /* ioctl r/o */ + __u64 lo_inode; /* ioctl r/o */ + __u64 lo_rdevice; /* ioctl r/o */ + __u64 lo_offset; + __u64 lo_sizelimit;/* bytes, 0 == max available */ + __u32 lo_number; /* ioctl r/o */ + __u32 lo_encrypt_type; + __u32 lo_encrypt_key_size; /* ioctl w/o */ + __u32 lo_flags; /* ioctl r/o */ + __u8 lo_file_name[LO_NAME_SIZE]; + __u8 lo_crypt_name[LO_NAME_SIZE]; + __u8 lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ + __u64 lo_init[2]; +}; + +/* + * Loop filter types + */ + +#define LO_CRYPT_NONE 0 +#define LO_CRYPT_XOR 1 +#define LO_CRYPT_DES 2 +#define LO_CRYPT_FISH2 3 /* Twofish encryption */ +#define LO_CRYPT_BLOW 4 +#define LO_CRYPT_CAST128 5 +#define LO_CRYPT_IDEA 6 +#define LO_CRYPT_DUMMY 9 +#define LO_CRYPT_SKIPJACK 10 +#define LO_CRYPT_CRYPTOAPI 18 +#define MAX_LO_CRYPT 20 + +/* + * IOCTL commands --- we will commandeer 0x4C ('L') + */ + +#define LOOP_SET_FD 0x4C00 +#define LOOP_CLR_FD 0x4C01 +#define LOOP_SET_STATUS 0x4C02 +#define LOOP_GET_STATUS 0x4C03 +#define LOOP_SET_STATUS64 0x4C04 +#define LOOP_GET_STATUS64 0x4C05 +#define LOOP_CHANGE_FD 0x4C06 +#define LOOP_SET_CAPACITY 0x4C07 + +#endif diff --git a/contrib/syslinux-4.02/libinstaller/linuxioctl.h b/contrib/syslinux-4.02/libinstaller/linuxioctl.h new file mode 100644 index 0000000..7ef919a --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/linuxioctl.h @@ -0,0 +1,47 @@ +/* + * linuxioctl.h + * + * Wrapper for Linux ioctl definitions, including workarounds + */ + +#ifndef LIBINSTALLER_LINUXIOCTL_H +#define LIBINSTALLER_LINUXIOCTL_H + +#include <sys/ioctl.h> + +#define statfs _kernel_statfs /* HACK to deal with broken 2.4 distros */ + +#include <linux/fd.h> /* Floppy geometry */ +#include <linux/hdreg.h> /* Hard disk geometry */ + +#include <linux/fs.h> /* FIGETBSZ, FIBMAP, FS_IOC_FIEMAP */ +#include <linux/msdos_fs.h> /* FAT_IOCTL_SET_ATTRIBUTES */ + +#undef SECTOR_SIZE /* Defined in msdos_fs.h for no good reason */ +#undef SECTOR_BITS +#include <linux/ext2_fs.h> /* EXT2_IOC_* */ + +#ifndef FAT_IOCTL_GET_ATTRIBUTES +# define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32) +#endif + +#ifndef FAT_IOCTL_SET_ATTRIBUTES +# define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32) +#endif + +#include <linux/fiemap.h> /* FIEMAP definitions */ + +#ifndef FS_IOC_FIEMAP +# define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap) +#endif + +#undef statfs + +#if defined(__linux__) && !defined(BLKGETSIZE64) +/* This takes a u64, but the size field says size_t. Someone screwed big. */ +# define BLKGETSIZE64 _IOR(0x12,114,size_t) +#endif + +#include <linux/loop.h> + +#endif /* LIBINSTALLER_LINUXIOCTL_H */ diff --git a/contrib/syslinux-4.02/libinstaller/setadv.c b/contrib/syslinux-4.02/libinstaller/setadv.c new file mode 100644 index 0000000..9cf6f18 --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/setadv.c @@ -0,0 +1,167 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 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. + * + * ----------------------------------------------------------------------- */ + +/* + * setadv.c + * + * (Over)write a data item in the auxilliary data vector. To + * delete an item, set its length to zero. + * + * Return 0 on success, -1 on error, and set errno. + * + */ +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <errno.h> +#include "syslxint.h" +#include "syslxcom.h" + +unsigned char syslinux_adv[2 * ADV_SIZE]; + +#define ADV_MAGIC1 0x5a2d2fa5 /* Head signature */ +#define ADV_MAGIC2 0xa3041767 /* Total checksum */ +#define ADV_MAGIC3 0xdd28bf64 /* Tail signature */ + +static void cleanup_adv(unsigned char *advbuf) +{ + int i; + uint32_t csum; + + /* Make sure both copies agree, and update the checksum */ + set_32((uint32_t *) advbuf, ADV_MAGIC1); + + csum = ADV_MAGIC2; + for (i = 8; i < ADV_SIZE - 4; i += 4) + csum -= get_32((uint32_t *) (advbuf + i)); + + set_32((uint32_t *) (advbuf + 4), csum); + set_32((uint32_t *) (advbuf + ADV_SIZE - 4), ADV_MAGIC3); + + memcpy(advbuf + ADV_SIZE, advbuf, ADV_SIZE); +} + +int syslinux_setadv(int tag, size_t size, const void *data) +{ + uint8_t *p; + size_t left; + uint8_t advtmp[ADV_SIZE]; + + if ((unsigned)tag - 1 > 254) { + errno = EINVAL; + return -1; /* Impossible tag value */ + } + + if (size > 255) { + errno = ENOSPC; /* Max 255 bytes for a data item */ + return -1; + } + + left = ADV_LEN; + p = advtmp; + memcpy(p, syslinux_adv + 2 * 4, left); /* Make working copy */ + + while (left >= 2) { + uint8_t ptag = p[0]; + size_t plen = p[1] + 2; + + if (ptag == ADV_END) + break; + + if (ptag == tag) { + /* Found our tag. Delete it. */ + + if (plen >= left) { + /* Entire remainder is our tag */ + break; + } + memmove(p, p + plen, left - plen); + } else { + /* Not our tag */ + if (plen > left) + break; /* Corrupt tag (overrun) - overwrite it */ + + left -= plen; + p += plen; + } + } + + /* Now (p, left) reflects the position to write in and how much space + we have for our data. */ + + if (size) { + if (left < size + 2) { + errno = ENOSPC; /* Not enough space for data */ + return -1; + } + + *p++ = tag; + *p++ = size; + memcpy(p, data, size); + p += size; + left -= size + 2; + } + + memset(p, 0, left); + + /* If we got here, everything went OK, commit the write */ + memcpy(syslinux_adv + 2 * 4, advtmp, ADV_LEN); + cleanup_adv(syslinux_adv); + + return 0; +} + +void syslinux_reset_adv(unsigned char *advbuf) +{ + /* Create an all-zero ADV */ + memset(advbuf + 2 * 4, 0, ADV_LEN); + cleanup_adv(advbuf); +} + +static int adv_consistent(const unsigned char *p) +{ + int i; + uint32_t csum; + + if (get_32((uint32_t *) p) != ADV_MAGIC1 || + get_32((uint32_t *) (p + ADV_SIZE - 4)) != ADV_MAGIC3) + return 0; + + csum = 0; + for (i = 4; i < ADV_SIZE - 4; i += 4) + csum += get_32((uint32_t *) (p + i)); + + return csum == ADV_MAGIC2; +} + +/* + * Verify that an in-memory ADV is consistent, making the copies consistent. + * If neither copy is OK, return -1 and call syslinux_reset_adv(). + */ +int syslinux_validate_adv(unsigned char *advbuf) +{ + if (adv_consistent(advbuf + 0 * ADV_SIZE)) { + memcpy(advbuf + ADV_SIZE, advbuf, ADV_SIZE); + return 0; + } else if (adv_consistent(advbuf + 1 * ADV_SIZE)) { + memcpy(advbuf, advbuf + ADV_SIZE, ADV_SIZE); + return 0; + } else { + syslinux_reset_adv(advbuf); + return -1; + } +} diff --git a/contrib/syslinux-4.02/libinstaller/setadv.h b/contrib/syslinux-4.02/libinstaller/setadv.h new file mode 100644 index 0000000..32bdfec --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/setadv.h @@ -0,0 +1,16 @@ +#ifndef _H_SET_ADV_ +#define _H_SET_ADV_ + +/* ADV information */ +#define ADV_SIZE 512 /* Total size */ +#define ADV_LEN (ADV_SIZE-3*4) /* Usable data size */ + +extern unsigned char syslinux_adv[2 * ADV_SIZE]; + +int syslinux_setadv(int tag, size_t size, const void *data); +void syslinux_reset_adv(unsigned char *advbuf); +int syslinux_validate_adv(unsigned char *advbuf); +int read_adv(const char *path, const char *cfg); +int write_adv(const char *path, const char *cfg); + +#endif diff --git a/contrib/syslinux-4.02/libinstaller/syslinux.h b/contrib/syslinux-4.02/libinstaller/syslinux.h new file mode 100644 index 0000000..710d30e --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/syslinux.h @@ -0,0 +1,54 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1998-2008 H. Peter Anvin - All Rights Reserved + * + * 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. + * + * ----------------------------------------------------------------------- */ + +#ifndef SYSLINUX_H +#define SYSLINUX_H + +#include <inttypes.h> +#include "advconst.h" +#include "setadv.h" + +/* The standard boot sector and ldlinux image */ +extern unsigned char syslinux_bootsect[]; +extern const unsigned int syslinux_bootsect_len; +extern const int syslinux_bootsect_mtime; + +extern unsigned char syslinux_ldlinux[]; +extern const unsigned int syslinux_ldlinux_len; +extern const int syslinux_ldlinux_mtime; + +#define boot_sector syslinux_bootsect +#define boot_sector_len syslinux_bootsect_len +#define boot_image syslinux_ldlinux +#define boot_image_len syslinux_ldlinux_len + +extern unsigned char syslinux_mbr[]; +extern const unsigned int syslinux_mbr_len; +extern const int syslinux_mbr_mtime; + +/* Sector size assumptions... */ +#define SECTOR_SHIFT 9 +#define SECTOR_SIZE (1 << SECTOR_SHIFT) + +/* This takes a boot sector and merges in the syslinux fields */ +void syslinux_make_bootsect(void *); + +/* Check to see that what we got was indeed an MS-DOS boot sector/superblock */ +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, const char *subvol); + +#endif diff --git a/contrib/syslinux-4.02/libinstaller/syslxcom.c b/contrib/syslinux-4.02/libinstaller/syslxcom.c new file mode 100644 index 0000000..b176f6d --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/syslxcom.c @@ -0,0 +1,286 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Intel Corp. - All Rights Reserved + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslxcom.c + * + * common functions for extlinux & syslinux installer + * + */ +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <getopt.h> +#include <unistd.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/mount.h> +#include <sys/vfs.h> +#include "linuxioctl.h" +#include "syslxcom.h" + +const char *program; + +int fs_type; + +#ifdef DEBUG +# define dprintf printf +#else +# define dprintf(...) ((void)0) +#endif + +#define SECTOR_SHIFT 9 + +static void die(const char *msg) +{ + fputs(msg, stderr); + exit(1); +} + +/* + * read/write wrapper functions + */ +ssize_t xpread(int fd, void *buf, size_t count, off_t offset) +{ + char *bufp = (char *)buf; + ssize_t rv; + ssize_t done = 0; + + while (count) { + rv = pread(fd, bufp, count, offset); + if (rv == 0) { + die("short read"); + } else if (rv == -1) { + if (errno == EINTR) { + continue; + } else { + die(strerror(errno)); + } + } else { + bufp += rv; + offset += rv; + done += rv; + count -= rv; + } + } + + return done; +} + +ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset) +{ + const char *bufp = (const char *)buf; + ssize_t rv; + ssize_t done = 0; + + while (count) { + rv = pwrite(fd, bufp, count, offset); + if (rv == 0) { + die("short write"); + } else if (rv == -1) { + if (errno == EINTR) { + continue; + } else { + die(strerror(errno)); + } + } else { + bufp += rv; + offset += rv; + done += rv; + count -= rv; + } + } + + return done; +} + +/* + * Set and clear file attributes + */ +void clear_attributes(int fd) +{ + struct stat st; + + if (!fstat(fd, &st)) { + switch (fs_type) { + case EXT2: + { + int flags; + + if (!ioctl(fd, EXT2_IOC_GETFLAGS, &flags)) { + flags &= ~EXT2_IMMUTABLE_FL; + ioctl(fd, EXT2_IOC_SETFLAGS, &flags); + } + break; + } + case VFAT: + { + uint32_t attr = 0x00; /* Clear all attributes */ + ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr); + break; + } + default: + break; + } + fchmod(fd, st.st_mode | S_IWUSR); + } +} + +void set_attributes(int fd) +{ + struct stat st; + + if (!fstat(fd, &st)) { + fchmod(fd, st.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)); + switch (fs_type) { + case EXT2: + { + int flags; + + if (st.st_uid == 0 && !ioctl(fd, EXT2_IOC_GETFLAGS, &flags)) { + flags |= EXT2_IMMUTABLE_FL; + ioctl(fd, EXT2_IOC_SETFLAGS, &flags); + } + break; + } + case VFAT: + { + uint32_t attr = 0x07; /* Hidden+System+Readonly */ + ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr); + break; + } + default: + break; + } + } +} + +/* New FIEMAP based mapping */ +static int sectmap_fie(int fd, sector_t *sectors, int nsectors) +{ + struct fiemap *fm; + struct fiemap_extent *fe; + unsigned int i, nsec; + sector_t sec, *secp, *esec; + struct stat st; + uint64_t maplen; + + if (fstat(fd, &st)) + return -1; + + fm = alloca(sizeof(struct fiemap) + + nsectors * sizeof(struct fiemap_extent)); + + memset(fm, 0, sizeof *fm); + + maplen = (uint64_t)nsectors << SECTOR_SHIFT; + if (maplen > (uint64_t)st.st_size) + maplen = st.st_size; + + fm->fm_start = 0; + fm->fm_length = maplen; + fm->fm_flags = FIEMAP_FLAG_SYNC; + fm->fm_extent_count = nsectors; + + if (ioctl(fd, FS_IOC_FIEMAP, fm)) + return -1; + + memset(sectors, 0, nsectors * sizeof *sectors); + esec = sectors + nsectors; + + fe = fm->fm_extents; + + if (fm->fm_mapped_extents < 1 || + !(fe[fm->fm_mapped_extents-1].fe_flags & FIEMAP_EXTENT_LAST)) + return -1; + + for (i = 0; i < fm->fm_mapped_extents; i++) { + if (fe->fe_flags & FIEMAP_EXTENT_LAST) { + /* If this is the *final* extent, pad the length */ + fe->fe_length = (fe->fe_length + SECTOR_SIZE - 1) + & ~(SECTOR_SIZE - 1); + } + + if ((fe->fe_logical | fe->fe_physical| fe->fe_length) & + (SECTOR_SIZE - 1)) + return -1; + + if (fe->fe_flags & (FIEMAP_EXTENT_UNKNOWN| + FIEMAP_EXTENT_DELALLOC| + FIEMAP_EXTENT_ENCODED| + FIEMAP_EXTENT_DATA_ENCRYPTED| + FIEMAP_EXTENT_UNWRITTEN)) + return -1; + + secp = sectors + (fe->fe_logical >> SECTOR_SHIFT); + sec = fe->fe_physical >> SECTOR_SHIFT; + nsec = fe->fe_length >> SECTOR_SHIFT; + + while (nsec--) { + if (secp >= esec) + break; + *secp++ = sec++; + } + + fe++; + } + + return 0; +} + +/* Legacy FIBMAP based mapping */ +static int sectmap_fib(int fd, sector_t *sectors, int nsectors) +{ + unsigned int blk, nblk; + unsigned int i; + unsigned int blksize; + sector_t sec; + + /* Get block size */ + if (ioctl(fd, FIGETBSZ, &blksize)) + return -1; + + /* Number of sectors per block */ + blksize >>= SECTOR_SHIFT; + + nblk = 0; + while (nsectors) { + blk = nblk++; + if (ioctl(fd, FIBMAP, &blk)) + return -1; + + sec = (sector_t)blk * blksize; + for (i = 0; i < blksize; i++) { + *sectors++ = sec++; + if (! --nsectors) + break; + } + } + + return 0; +} + +/* + * Produce file map + */ +int sectmap(int fd, sector_t *sectors, int nsectors) +{ + if (!sectmap_fie(fd, sectors, nsectors)) + return 0; + + return sectmap_fib(fd, sectors, nsectors); +} diff --git a/contrib/syslinux-4.02/libinstaller/syslxcom.h b/contrib/syslinux-4.02/libinstaller/syslxcom.h new file mode 100644 index 0000000..39ca09d --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/syslxcom.h @@ -0,0 +1,22 @@ +#ifndef _H_SYSLXCOM_ +#define _H_SYSLXCOM_ + +#include "syslinux.h" + +/* Global fs_type for handling fat, ext2/3/4 and btrfs */ +enum filesystem { + NONE, + EXT2, + BTRFS, + VFAT, +}; + +extern int fs_type; +extern const char *program; +ssize_t xpread(int fd, void *buf, size_t count, off_t offset); +ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset); +void clear_attributes(int fd); +void set_attributes(int fd); +int sectmap(int fd, sector_t *sectors, int nsectors); + +#endif diff --git a/contrib/syslinux-4.02/libinstaller/syslxint.h b/contrib/syslinux-4.02/libinstaller/syslxint.h new file mode 100644 index 0000000..14a7fc2 --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/syslxint.h @@ -0,0 +1,246 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * 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. + * + * ----------------------------------------------------------------------- */ + +#ifndef SYSLXINT_H +#define SYSLXINT_H + +#include "syslinux.h" + +#if defined(__386__) || defined(__i386__) || defined(__x86_64__) +# define X86_MEM 1 /* Littleendian and unaligned safe */ +#else +# define X86_MEM 0 +#endif + +/* + * Access functions for littleendian numbers, possibly misaligned. + */ +static inline uint8_t get_8(const uint8_t * p) +{ + return *p; +} + +static inline uint16_t get_16(const uint16_t * p) +{ +#if X86_MEM + /* Littleendian and unaligned-capable */ + return *p; +#else + const uint8_t *pp = (const uint8_t *)p; + return pp[0] + ((uint16_t)pp[1] << 8); +#endif +} + +static inline uint32_t get_32(const uint32_t * p) +{ +#if X86_MEM + /* Littleendian and unaligned-capable */ + return *p; +#else + const uint16_t *pp = (const uint16_t *)p; + return get_16(pp[0]) + (uint32_t)get_16(pp[1]); +#endif +} + +static inline uint64_t get_64(const uint64_t * p) +{ +#if X86_MEM + /* Littleendian and unaligned-capable */ + return *p; +#else + const uint32_t *pp = (const uint32_t *)p; + return get_32(pp[0]) + (uint64_t)get_32(pp[1]); +#endif +} + +static inline void set_8(uint8_t *p, uint8_t v) +{ + *p = v; +} + +static inline void set_16(uint16_t *p, uint16_t v) +{ +#if X86_MEM + /* Littleendian and unaligned-capable */ + *p = v; +#else + uint8_t *pp = (uint8_t *) p; + pp[0] = (v & 0xff); + pp[1] = ((v >> 8) & 0xff); +#endif +} + +static inline void set_32(uint32_t *p, uint32_t v) +{ +#if X86_MEM + /* Littleendian and unaligned-capable */ + *p = v; +#else + uint8_t *pp = (uint8_t *) p; + pp[0] = (v & 0xff); + pp[1] = ((v >> 8) & 0xff); + pp[2] = ((v >> 16) & 0xff); + pp[3] = ((v >> 24) & 0xff); +#endif +} + +static inline void set_64(uint64_t *p, uint64_t v) +{ +#if X86_MEM + /* Littleendian and unaligned-capable */ + *p = v; +#else + uint32_t *pp = (uint32_t *) p; + set_32(pp[0], v); + set_32(pp[1], v >> 32); +#endif +} + +/* + * Special handling for the MS-DOS derivative: syslinux_ldlinux + * is a "far" object... + */ +#ifdef __MSDOS__ + +static inline __attribute__ ((const)) +uint16_t ds(void) +{ + uint16_t v; + asm("movw %%ds,%0":"=rm"(v)); + return v; +} + +static inline void *set_fs(const void *p) +{ + uint16_t seg; + + seg = ds() + ((size_t) p >> 4); + asm volatile ("movw %0,%%fs"::"rm" (seg)); + return (void *)((size_t) p & 0xf); +} + +uint8_t get_8_sl(const uint8_t * p); +uint16_t get_16_sl(const uint16_t * p); +uint32_t get_32_sl(const uint32_t * p); +uint64_t get_64_sl(const uint64_t * p); +void set_8_sl(uint8_t * p, uint8_t v); +void set_16_sl(uint16_t * p, uint16_t v); +void set_32_sl(uint32_t * p, uint32_t v); +void set_64_sl(uint64_t * p, uint64_t v); +void memcpy_to_sl(void *dst, const void *src, size_t len); +void memcpy_from_sl(void *dst, const void *src, size_t len); + +#else + +/* Sane system ... */ +#define get_8_sl(x) get_8(x) +#define get_16_sl(x) get_16(x) +#define get_32_sl(x) get_32(x) +#define get_64_sl(x) get_64(x) +#define set_8_sl(x,y) set_8(x,y) +#define set_16_sl(x,y) set_16(x,y) +#define set_32_sl(x,y) set_32(x,y) +#define set_64_sl(x,y) set_64(x,y) +#define memcpy_to_sl(d,s,l) memcpy(d,s,l) +#define memcpy_from_sl(d,s,l) memcpy(d,s,l) + +#endif + +#define LDLINUX_MAGIC 0x3eb202fe + +/* Patch area for disk-based installers */ +struct patch_area { + uint32_t magic; /* LDLINUX_MAGIC */ + uint32_t instance; /* Per-version value */ + uint16_t data_sectors; + uint16_t adv_sectors; + uint32_t dwords; + uint32_t checksum; + uint16_t maxtransfer; + uint16_t epaoffset; /* Pointer to the extended patch area */ +}; + +struct ext_patch_area { + uint16_t advptroffset; /* ADV pointers */ + uint16_t diroffset; /* Current directory field */ + uint16_t dirlen; /* Length of current directory field */ + uint16_t subvoloffset; /* Subvolume field */ + uint16_t subvollen; /* Length of subvolume field */ + uint16_t secptroffset; /* Sector extent pointers */ + uint16_t secptrcnt; /* Number of sector extent pointers */ + + uint16_t sect1ptr0; /* Boot sector offset of sector 1 ptr LSW */ + uint16_t sect1ptr1; /* Boot sector offset of sector 1 ptr MSW */ + uint16_t raidpatch; /* Boot sector RAID mode patch pointer */ +}; + +/* Sector extent */ +struct syslinux_extent { + uint64_t lba; + uint16_t len; +} __attribute__((packed)); + +/* 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; + + union { + struct { + uint8_t DriveNumber; + uint8_t Reserved1; + uint8_t BootSignature; + uint32_t VolumeID; + char VolumeLabel[11]; + char FileSysType[8]; + uint8_t Code[448]; + } __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[420]; + } __attribute__ ((packed)) bs32; + } __attribute__ ((packed)); + + uint16_t bsSignature; +} __attribute__ ((packed)); + +#define bsHead bsJump +#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)) + +#endif /* SYSLXINT_H */ diff --git a/contrib/syslinux-4.02/libinstaller/syslxmod.c b/contrib/syslinux-4.02/libinstaller/syslxmod.c new file mode 100644 index 0000000..a68f19f --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/syslxmod.c @@ -0,0 +1,197 @@ +/* ----------------------------------------------------------------------- * + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslxmod.c - Code to provide a SYSLINUX code set to an installer. + */ + +#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" + + +/* + * 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); +} + +/* + * This patches the boot sector and the beginning of ldlinux.sys + * based on an ldlinux.sys sector map passed in. Typically this is + * handled by writing ldlinux.sys, mapping it, and then overwrite it + * with the patched version. If this isn't safe to do because of + * an OS which does block reallocation, then overwrite it with + * direct access since the location is known. + * + * Returns the number of modified bytes in ldlinux.sys if successful, + * otherwise -1. + */ +#define NADV 2 + +int syslinux_patch(const sector_t *sectp, int nsectors, + int stupid, int raid_mode, + const char *subdir, const char *subvol) +{ + struct patch_area *patcharea; + struct ext_patch_area *epa; + struct syslinux_extent *ex; + uint32_t *wp; + int nsect = ((boot_image_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT) + 2; + uint32_t csum; + int i, dw, nptrs; + struct boot_sector *sbs = (struct boot_sector *)boot_sector; + uint64_t *advptrs; + + if (nsectors < nsect) + return -1; /* The actual file is too small for content */ + + /* 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 (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); + + /* Handle Stupid mode */ + if (stupid) { + /* 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]); + + /* Poke in the base directory path */ + if (subdir) { + int sublen = strlen(subdir) + 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), 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); + + 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; +} diff --git a/contrib/syslinux-4.02/libinstaller/syslxopt.c b/contrib/syslinux-4.02/libinstaller/syslxopt.c new file mode 100644 index 0000000..18a6baa --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/syslxopt.c @@ -0,0 +1,267 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Intel Corp. - All Rights Reserved + * + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * syslxopt.c + * + * parse cmdline for extlinux and syslinux installer + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <getopt.h> +#include <sysexits.h> +#include "../version.h" +#include "syslxcom.h" +#include "syslxopt.h" + +/* These are the options we can set their values */ +struct sys_options opt = { + .sectors = 0, + .heads = 0, + .raid_mode = 0, + .stupid_mode = 0, + .reset_adv = 0, + .set_once = NULL, + .update_only = -1, + .directory = NULL, + .device = NULL, + .offset = 0, + .menu_save = NULL, + .install_mbr = 0, + .activate_partition = 0, + .force = 0, + .bootsecfile = NULL, +}; + +const struct option long_options[] = { + {"force", 0, NULL, 'f'}, /* DOS/Win32/mtools only */ + {"install", 0, NULL, 'i'}, + {"directory", 1, NULL, 'd'}, + {"offset", 1, NULL, 't'}, + {"update", 0, NULL, 'U'}, + {"zipdrive", 0, NULL, 'z'}, + {"sectors", 1, NULL, 'S'}, + {"stupid", 0, NULL, 's'}, + {"heads", 1, NULL, 'H'}, + {"raid-mode", 0, NULL, 'r'}, + {"version", 0, NULL, 'v'}, + {"help", 0, NULL, 'h'}, + {"once", 1, NULL, OPT_ONCE}, + {"clear-once", 0, NULL, 'O'}, + {"reset-adv", 0, NULL, OPT_RESET_ADV}, + {"menu-save", 1, NULL, 'M'}, + {"mbr", 0, NULL, 'm'}, /* DOS/Win32 only */ + {"active", 0, NULL, 'a'}, /* DOS/Win32 only */ + {0, 0, 0, 0} +}; + +const char short_options[] = "t:fid:UuzS:H:rvho:OM:ma"; + +void __attribute__ ((noreturn)) usage(int rv, enum syslinux_mode mode) +{ + switch (mode) { + case MODE_SYSLINUX: + /* For unmounted fs installation (syslinux) */ + fprintf(stderr, + "Usage: %s [options] device\n" + " --offset -t Offset of the file system on the device \n" + " --directory -d Directory for installation target\n", + program); + break; + + case MODE_EXTLINUX: + /* Mounted fs installation (extlinux) */ + /* Actually extlinux can also use -d to provide a directory too... */ + fprintf(stderr, + "Usage: %s [options] directory\n", + program); + break; + + case MODE_SYSLINUX_DOSWIN: + /* For fs installation under Windows (syslinux.exe) */ + fprintf(stderr, + "Usage: %s [options] <drive>: [bootsecfile]\n" + " --directory -d Directory for installation target\n", + program); + break; + } + + fprintf(stderr, + " --install -i Install over the current bootsector\n" + " --update -U Update a previous EXTLINUX installation\n" + " --zip -z Force zipdrive geometry (-H 64 -S 32)\n" + " --sectors=# -S Force the number of sectors per track\n" + " --heads=# -H Force number of heads\n" + " --stupid -s Slow, safe and stupid mode\n" + " --raid -r Fall back to the next device on boot failure\n" + " --once=... %s Execute a command once upon boot\n" + " --clear-once -O Clear the boot-once command\n" + " --reset-adv Reset auxilliary data\n", + mode == MODE_SYSLINUX ? " " : "-o"); + /* Have to chop this roughly in half for the DOS installer for some reason */ + fprintf(stderr, + " --menu-save= -M Set the label to select as default on the next boot\n" + " --mbr -m Install an MBR (DOS/Win32 installers only)\n" + " --active -a Mark partition as active (DOS/Win32 installers only)\n" + " --force -f Ignore precautions (DOS/Win32/mtools installers only)\n" + "\n" + " Note: geometry is determined at boot time for devices which\n" + " are considered hard disks by the BIOS. Unfortunately, this is\n" + " not possible for devices which are considered floppy disks,\n" + " which includes zipdisks and LS-120 superfloppies.\n" + "\n" + " The -z option is useful for USB devices which are considered\n" + " hard disks by some BIOSes and zipdrives by other BIOSes."); + + exit(rv); +} + +void parse_options(int argc, char *argv[], enum syslinux_mode mode) +{ + int o; + + program = argv[0]; + while ((o = getopt_long(argc, argv, short_options, + long_options, NULL)) != EOF) { + switch (o) { + case 'f': + opt.force = 1; + break; + case 'z': + opt.heads = 64; + opt.sectors = 32; + break; + case 'S': + opt.sectors = strtoul(optarg, NULL, 0); + if (opt.sectors < 1 || opt.sectors > 63) { + fprintf(stderr, + "%s: invalid number of sectors: %u (must be 1-63)\n", + program, opt.sectors); + exit(EX_USAGE); + } + break; + case 'H': + opt.heads = strtoul(optarg, NULL, 0); + if (opt.heads < 1 || opt.heads > 256) { + fprintf(stderr, + "%s: invalid number of heads: %u (must be 1-256)\n", + program, opt.heads); + exit(EX_USAGE); + } + break; + case 'r': + opt.raid_mode = 1; + break; + case 's': + opt.stupid_mode = 1; + break; + case 'i': + opt.update_only = 0; + break; + case 'u': + case 'U': + opt.update_only = 1; + break; + case 'h': + usage(0, mode); + break; + case 'o': + if (mode == MODE_SYSLINUX) { + fprintf(stderr, "%s: -o will change meaning in a future version, use -t or --offset\n", program); + goto opt_offset; + } + /* else fall through */ + case OPT_ONCE: + opt.set_once = optarg; + break; + case 't': + opt_offset: + opt.offset = strtoul(optarg, NULL, 0); + break; + case 'O': + opt.set_once = ""; + break; + case 'd': + opt.directory = optarg; + break; + case OPT_RESET_ADV: + opt.reset_adv = 1; + break; + case 'M': + opt.menu_save = optarg; + break; + case 'm': + opt.install_mbr = 1; + break; + case 'a': + opt.activate_partition = 1; + break; + case 'v': + fprintf(stderr, + "%s " VERSION_STR " Copyright 1994-" YEAR_STR + " H. Peter Anvin et al\n", program); + exit(0); + default: + fprintf(stderr, "%s: Unknown option: -%c\n", program, optopt); + usage(EX_USAGE, mode); + } + } + + switch (mode) { + case MODE_SYSLINUX: + case MODE_SYSLINUX_DOSWIN: + opt.device = argv[optind++]; + break; + case MODE_EXTLINUX: + if (!opt.directory) + opt.directory = argv[optind++]; + break; + } + + if (argv[optind] && (mode == MODE_SYSLINUX_DOSWIN)) + /* Allow for the boot-sector argument */ + opt.bootsecfile = argv[optind++]; + if (argv[optind]) + usage(EX_USAGE, mode); /* Excess arguments */ +} + +/* + * Make any user-specified ADV modifications in memory + */ +int modify_adv(void) +{ + int rv = 0; + + if (opt.reset_adv) + syslinux_reset_adv(syslinux_adv); + + if (opt.set_once) { + if (syslinux_setadv(ADV_BOOTONCE, strlen(opt.set_once), opt.set_once)) { + fprintf(stderr, "%s: not enough space for boot-once command\n", + program); + rv = -1; + } + } + if (opt.menu_save) { + if (syslinux_setadv(ADV_MENUSAVE, strlen(opt.menu_save), opt.menu_save)) { + fprintf(stderr, "%s: not enough space for menu-save label\n", + program); + rv = -1; + } + } + + return rv; +} diff --git a/contrib/syslinux-4.02/libinstaller/syslxopt.h b/contrib/syslinux-4.02/libinstaller/syslxopt.h new file mode 100644 index 0000000..bcbe035 --- /dev/null +++ b/contrib/syslinux-4.02/libinstaller/syslxopt.h @@ -0,0 +1,43 @@ +#ifndef _H_SYSLXOPT_ +#define _H_SYSLXOPT_ + +/* These are the options we can set and their values */ +struct sys_options { + unsigned int sectors; + unsigned int heads; + int raid_mode; + int stupid_mode; + int reset_adv; + const char *set_once; + int update_only; + const char *directory; + const char *device; + unsigned int offset; + const char *menu_save; + int force; + int install_mbr; + int activate_partition; + const char *bootsecfile; +}; + +enum long_only_opt { + OPT_NONE, + OPT_RESET_ADV, + OPT_ONCE, +}; + +enum syslinux_mode { + MODE_SYSLINUX, /* Unmounted filesystem */ + MODE_EXTLINUX, + MODE_SYSLINUX_DOSWIN, +}; + +void __attribute__ ((noreturn)) usage(int rv, enum syslinux_mode mode); +void parse_options(int argc, char *argv[], enum syslinux_mode mode); +int modify_adv(void); + +extern struct sys_options opt; +extern const struct option long_options[]; +extern const char short_options[]; + +#endif |