From 8f5add1754284c4e0f6162797b20b5d08b2e2882 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Sun, 31 Oct 2010 19:51:33 +0100 Subject: rework installation scripts for block devices Avoid sfdisk, parted and chroot to be more portable. Compile Host grub in target/tools, only used for ibmx40 target right now. Add pt - partition table manager from OpenWrt with some additions and portability fixes. Cfgfs support missing, coming soon. --- scripts/install-rb532.sh | 152 +++++++++++++++++++++++++++ scripts/install.sh | 200 ++++++++--------------------------- target/ibmx40/Makefile | 8 +- target/tools/grub/Makefile | 24 +++++ tools/adk/Makefile | 6 +- tools/adk/pt.c | 256 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 488 insertions(+), 158 deletions(-) create mode 100755 scripts/install-rb532.sh create mode 100644 target/tools/grub/Makefile create mode 100644 tools/adk/pt.c diff --git a/scripts/install-rb532.sh b/scripts/install-rb532.sh new file mode 100755 index 000000000..9011388c7 --- /dev/null +++ b/scripts/install-rb532.sh @@ -0,0 +1,152 @@ +#!/usr/bin/env bash +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +if [ $(id -u) -ne 0 ];then + printf "Installation is only possible as root\n" + exit 1 +fi + +printf "Checking if sfdisk is installed" +sfdisk=$(which sfdisk) + +if [ ! -z $sfdisk -a -x $sfdisk ];then + printf "...okay\n" +else + printf "...failed\n" + exit 1 +fi + +printf "Checking if parted is installed" +parted=$(which parted) + +if [ ! -z $parted -a -x $parted ];then + printf "...okay\n" +else + printf "...failed\n" + exit 1 +fi + +printf "Checking if mke2fs is installed" +mke2fs=$(which mke2fs) + +if [ ! -z $mke2fs -a -x $mke2fs ];then + printf "...okay\n" +else + printf "...failed\n" + exit 1 +fi + +printf "Checking if tune2fs is installed" +tune2fs=$(which tune2fs) + +if [ ! -z $tune2fs -a -x $tune2fs ];then + printf "...okay\n" +else + printf "...failed\n" + exit 1 +fi + +if [ -z $1 ];then + printf "Please give your compact flash or USB device as first parameter\n" + exit 1 +else + if [ -z $2 ];then + printf "Please give your install tar archive as second parameter\n" + exit 2 + fi + if [ -f $2 ];then + printf "Installing $2 on $1\n" + else + printf "$2 is not a file, Exiting\n" + exit 1 + fi + if [ -z $3 ];then + printf "Please give the kernel as third parameter\n" + exit 2 + fi + if [ -f $3 ];then + printf "Installing $3 on $1\n" + else + printf "$3 is not a file, Exiting\n" + exit 1 + fi + if [ -b $1 ];then + printf "Using $1 as CF/USB disk for installation\n" + printf "This will destroy all data on $1, are you sure?\n" + printf "Type "y" to continue\n" + read y + if [ "$y" = "y" ];then + $sfdisk -l $1 2>&1 |grep 'No medium' + if [ $? -eq 0 ];then + exit 1 + else + printf "Starting with installation\n" + fi + else + printf "Exiting.\n" + exit 1 + fi + else + printf "Sorry $1 is not a block device\n" + exit 1 + fi +fi + + +if [ $(mount | grep $1| wc -l) -ne 0 ];then + printf "Block device $1 is in use, please umount first.\n" + exit 1 +fi + + +if [ $($sfdisk -l $1 2>/dev/null|grep Empty|wc -l) -ne 4 ];then + printf "Partitions already exist, should I wipe them?\n" + printf "Type y to continue\n" + read y + if [ $y = "y" ];then + printf "Wiping existing partitions\n" + dd if=/dev/zero of=$1 bs=512 count=1 >/dev/null 2>&1 + else + printf "Exiting.\n" + exit 1 + fi +fi + +printf "Create partition and filesystem for rb532\n" +rootpart=${1}2 +$parted -s $1 mklabel msdos +sleep 2 +maxsize=$(env LC_ALL=C $parted $1 -s unit cyl print |awk '/^Disk/ { print $3 }'|sed -e 's/cyl//') +rootsize=$(($maxsize-2)) + +$parted -s $1 unit cyl mkpart primary ext2 0 1 +$parted -s $1 unit cyl mkpart primary ext2 1 $rootsize +$parted -s $1 unit cyl mkpart primary fat32 $rootsize $maxsize +$parted -s $1 set 1 boot on +$sfdisk --change-id $1 1 27 +$sfdisk --change-id $1 3 88 +sleep 2 +$mke2fs ${1}2 +sync +dd if=$3 of=${1}1 bs=2048 +sync +sleep 2 +$tune2fs -c 0 -i 0 -m 1 ${rootpart} >/dev/null +if [ $? -eq 0 ];then + printf "Successfully disabled filesystem checks on ${rootpart}\n" +else + printf "Disabling filesystem checks failed, Exiting.\n" + exit 1 +fi + +tmp=$(mktemp -d) +mount -t ext2 ${rootpart} $tmp +printf "Extracting install archive\n" +tar -C $tmp -xzpf $2 +printf "Fixing permissions\n" +chmod 1777 $tmp/tmp +chmod 4755 $tmp/bin/busybox +umount $tmp +printf "Successfully installed.\n" +exit 0 diff --git a/scripts/install.sh b/scripts/install.sh index b436767a5..3e07a7181 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1,26 +1,11 @@ #!/usr/bin/env bash -if [ $(id -u) -ne 0 ];then - printf "Installation is only possible as root\n" - exit 1 -fi - -printf "Checking if sfdisk is installed" -sfdisk=$(which sfdisk) - -if [ ! -z $sfdisk -a -x $sfdisk ];then - printf "...okay\n" -else - printf "...failed\n" - exit 1 -fi +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. -printf "Checking if parted is installed" -parted=$(which parted) +TOPDIR=$(pwd) -if [ ! -z $parted -a -x $parted ];then - printf "...okay\n" -else - printf "...failed\n" +if [ $(id -u) -ne 0 ];then + printf "Installation is only possible as root\n" exit 1 fi @@ -34,27 +19,17 @@ else exit 1 fi -printf "Checking if tune2fs is installed" -tune2fs=$(which tune2fs) - -if [ ! -z $tune2fs -a -x $tune2fs ];then - printf "...okay\n" -else - printf "...failed\n" - exit 1 -fi - cfgfs=1 -rb532=0 -while getopts "nr" option +quiet=0 +while getopts "nq" option do case $option in + q) + quiet=1 + ;; n) cfgfs=0 ;; - r) - rb532=1 - ;; *) printf "Option not recognized\n" exit 1 @@ -78,33 +53,12 @@ else printf "$2 is not a file, Exiting\n" exit 1 fi - if [ $rb532 -eq 1 ];then - if [ -z $3 ];then - printf "Please give the kernel as third parameter\n" - exit 2 - fi - if [ -f $3 ];then - printf "Installing $3 on $1\n" - else - printf "$3 is not a file, Exiting\n" - exit 1 - fi - fi if [ -b $1 ];then printf "Using $1 as CF/USB disk for installation\n" - printf "This will destroy all data on $1, are you sure?\n" - printf "Type "y" to continue\n" - read y - if [ "$y" = "y" ];then - $sfdisk -l $1 2>&1 |grep 'No medium' - if [ $? -eq 0 ];then - exit 1 - else - printf "Starting with installation\n" - fi - else - printf "Exiting.\n" - exit 1 + if [ $quiet -eq 0 ];then + printf "This will destroy all data on $1, are you sure?\n" + printf "Type "y" to continue\n" + read y fi else printf "Sorry $1 is not a block device\n" @@ -112,26 +66,11 @@ else fi fi - if [ $(mount | grep $1| wc -l) -ne 0 ];then printf "Block device $1 is in use, please umount first.\n" exit 1 fi - -if [ $($sfdisk -l $1 2>/dev/null|grep Empty|wc -l) -ne 4 ];then - printf "Partitions already exist, should I wipe them?\n" - printf "Type y to continue\n" - read y - if [ $y = "y" ];then - printf "Wiping existing partitions\n" - dd if=/dev/zero of=$1 bs=512 count=1 >/dev/null 2>&1 - else - printf "Exiting.\n" - exit 1 - fi -fi - case $2 in wrap*) speed=38400 @@ -141,102 +80,51 @@ case $2 in ;; esac -if [ $rb532 -ne 0 ];then - printf "Create partition and filesystem for rb532\n" - rootpart=${1}2 - $parted -s $1 mklabel msdos - sleep 2 - maxsize=$(env LC_ALL=C $parted $1 -s unit cyl print |awk '/^Disk/ { print $3 }'|sed -e 's/cyl//') - rootsize=$(($maxsize-2)) - - $parted -s $1 unit cyl mkpart primary ext2 0 1 - $parted -s $1 unit cyl mkpart primary ext2 1 $rootsize - $parted -s $1 unit cyl mkpart primary fat32 $rootsize $maxsize - $parted -s $1 set 1 boot on - $sfdisk --change-id $1 1 27 - $sfdisk --change-id $1 3 88 - sleep 2 - $mke2fs ${1}2 - sync - dd if=$3 of=${1}1 bs=2048 - sync -else - rootpart=${1}1 - if [ $cfgfs -eq 0 ];then - printf "Create partition and filesystem without cfgfs\n" -$sfdisk $1 << EOF -,,L -; -; -; -y -EOF - $mke2fs ${rootpart} - else - printf "Create partition and filesystem with cfgfs\n" - $parted -s $1 mklabel msdos - sleep 2 - maxsize=$(env LC_ALL=C $parted $1 -s unit cyl print |awk '/^Disk/ { print $3 }'|sed -e 's/cyl//') - rootsize=$(($maxsize-2)) - - $parted -s $1 unit cyl mkpart primary ext2 0 $rootsize - $parted -s $1 unit cyl mkpart primary fat32 $rootsize $maxsize - $parted -s $1 set 1 boot on - $sfdisk --change-id $1 2 88 - $mke2fs ${1}1 - fi -fi - -if [ $? -eq 0 ];then - printf "Successfully created partition ${rootpart}\n" -else - printf "Partition creation failed, Exiting.\n" - exit 1 -fi - -sleep 2 -$tune2fs -c 0 -i 0 -m 1 ${rootpart} >/dev/null -if [ $? -eq 0 ];then - printf "Successfully disabled filesystem checks on ${rootpart}\n" -else - printf "Disabling filesystem checks failed, Exiting.\n" - exit 1 -fi - +rootpart=${1}1 +pt=$TOPDIR/bin/tools/pt +# get sector size from block device +maxsector=$(sudo $pt -g $1) +head=16 +sect=63 +rsize=$(($maxsector / 2)) + +printf "Creating partition table ...\n" +table=$(mktemp) +# generate partition table +$pt -o $table -s $sect -h $head -p ${rsize}K +# write partition table to block device +dd if=$table of=$1 bs=512 count=1 2> /dev/null +printf "Creating ext2 filesystem ...\n" +$mke2fs -q ${1}1 + +printf "Extracting install archive ...\n" tmp=$(mktemp -d) mount -t ext2 ${rootpart} $tmp -printf "Extracting install archive\n" tar -C $tmp -xzpf $2 -printf "Fixing permissions\n" +printf "Fixing permissions ...\n" chmod 1777 $tmp/tmp chmod 4755 $tmp/bin/busybox -if [ $rb532 -eq 0 ];then - printf "Installing GRUB bootloader\n" - mkdir -p $tmp/boot/grub - mount -o bind /dev $tmp/dev - chroot $tmp mount -t proc /proc /proc - chroot $tmp mount -t sysfs /sys /sys +printf "Installing GRUB bootloader ...\n" +mkdir -p $tmp/boot/grub cat << EOF > $tmp/boot/grub/grub.cfg set default=0 set timeout=1 -serial --unit=0 --speed=$speed -terminal_output serial -terminal_input serial +terminal_output console +terminal_input console menuentry "GNU/Linux (OpenADK)" { insmod ext2 set root=(hd0,1) - linux /boot/vmlinuz-adk root=/dev/sda1 ro init=/init console=ttyS0,$speed console=tty0 panic=10 + linux /boot/vmlinuz-adk init=/init } EOF - chroot $tmp grub-install $1 - umount $tmp/proc - umount $tmp/sys - umount $tmp/dev -fi - +./bin/tools/sbin/grub-install \ + --grub-setup=./bin/tools/sbin/grub-setup \ + --grub-mkimage=./bin/tools/bin/grub-mkimage \ + --grub-mkdevicemap=./bin/tools/sbin/grub-mkdevicemap \ + --no-floppy --root-directory=$tmp $1 umount $tmp - printf "Successfully installed.\n" +rm -rf $tmp exit 0 diff --git a/target/ibmx40/Makefile b/target/ibmx40/Makefile index 3c95fc2d1..b50a864fc 100644 --- a/target/ibmx40/Makefile +++ b/target/ibmx40/Makefile @@ -7,6 +7,12 @@ include $(TOPDIR)/mk/modules.mk include $(TOPDIR)/mk/kernel-build.mk include $(TOPDIR)/mk/image.mk +$(TOOLS_BUILD_DIR): + mkdir -p $(TOOLS_BUILD_DIR) + +tools-compile: $(TOOLS_BUILD_DIR) + $(MAKE) -C ../tools/grub prepare compile install + KERNEL:=$(LINUX_DIR)/arch/x86/boot/bzImage createinitcrypt: @@ -26,7 +32,7 @@ imageinstall: $(BIN_DIR)/$(ROOTFSTARBALL) @echo "The RootFS tarball is: $(BIN_DIR)/$(ROOTFSTARBALL)" endif ifeq ($(FS),usb) -imageinstall: $(BIN_DIR)/$(ROOTFSTARBALL) +imageinstall: tools-compile $(BIN_DIR)/$(ROOTFSTARBALL) @echo "The RootFS tarball is: $(BIN_DIR)/$(ROOTFSTARBALL)" @echo "To install everything to USB use scripts/install.sh" endif diff --git a/target/tools/grub/Makefile b/target/tools/grub/Makefile new file mode 100644 index 000000000..95d7b2397 --- /dev/null +++ b/target/tools/grub/Makefile @@ -0,0 +1,24 @@ +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +include $(TOPDIR)/rules.mk + +PKG_NAME:= grub +PKG_VERSION:= 1.98 +PKG_RELEASE:= 1 +PKG_MD5SUM:= c0bcf60e524739bb64e3a2d4e3732a59 +PKG_SITES:= ftp://alpha.gnu.org/gnu/grub/ + +include ../rules.mk + +$(WRKBUILD)/.compiled: ${WRKDIST}/.prepared + cd $(WRKBUILD) && ./configure --prefix=$(TOPDIR)/bin/tools + $(MAKE) -C $(WRKBUILD) + touch $@ + +$(TOPDIR)/bin/tools/bin/grub-install: $(WRKBUILD)/.compiled + $(MAKE) -C $(WRKBUILD) install + +install: $(TOPDIR)/bin/tools/bin/grub-install + +include $(TOPDIR)/mk/tools.mk diff --git a/tools/adk/Makefile b/tools/adk/Makefile index 3f2048e68..fd1d0e2c0 100644 --- a/tools/adk/Makefile +++ b/tools/adk/Makefile @@ -9,6 +9,10 @@ ${TOPDIR}/bin/tools/depmaker: ${TOPDIR}/bin/tools/pkgrebuild: $(HOSTCC) -o $(TOPDIR)/bin/tools/pkgrebuild pkgrebuild.c strmap.c -install: ${TOPDIR}/bin/tools/depmaker ${TOPDIR}/bin/tools/pkgrebuild +${TOPDIR}/bin/tools/pt: + $(HOSTCC) -o $(TOPDIR)/bin/tools/pt pt.c + +install: ${TOPDIR}/bin/tools/depmaker ${TOPDIR}/bin/tools/pkgrebuild \ + $(TOPDIR)/bin/tools/pt include $(TOPDIR)/mk/tools.mk diff --git a/tools/adk/pt.c b/tools/adk/pt.c new file mode 100644 index 000000000..e98550b31 --- /dev/null +++ b/tools/adk/pt.c @@ -0,0 +1,256 @@ +/* + * pt - partition table utility + * Copyright (C) 2010 by Waldemar Brodkorb + * + * just adds some required code to ptgen - partition table generator + * Copyright (C) 2006 by Felix Fietkau + * + * uses parts of afdisk + * Copyright (C) 2002 by David Roetzel + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__linux__) +#include +#endif + +#if defined(__APPLE__) +#include +#define BLKGETSIZE DKIOCGETBLOCKCOUNT +#endif + +#define bswap16(x) ( \ + ((((x) )&(unsigned int)0xff)<< 8) \ + |((((x)>> 8)&(unsigned int)0xff) ) \ +) + +#if __BYTE_ORDER == __BIG_ENDIAN +#define cpu_to_le16(x) bswap16(x) +#elif __BYTE_ORDER == __LITTLE_ENDIAN +#define cpu_to_le16(x) (x) +#else +#error unknown endianness! +#endif + +/* Partition table entry */ +struct pte { + unsigned char active; + unsigned char chs_start[3]; + unsigned char type; + unsigned char chs_end[3]; + unsigned int start; + unsigned int length; +}; + +struct partinfo { + unsigned long size; + int type; +}; + +int verbose = 0; +int active = 1; +int heads = -1; +int sectors = -1; +struct partinfo parts[4]; +char *filename = NULL; + +/* + * get the sector size of the block device + * + * print the sector size + */ + +static void getmaxsize(char *device) { + int fd; + unsigned long maxsectors=0; + + fd = open(device, O_RDONLY); + ioctl(fd, BLKGETSIZE, &maxsectors); + printf("%lu\n", maxsectors); + close(fd); +} + +/* + * parse the size argument, which is either + * a simple number (K assumed) or + * K, M or G + * + * returns the size in KByte + */ +static long to_kbytes(const char *string) { + int exp = 0; + long result; + char *end; + + result = strtoul(string, &end, 0); + switch (tolower(*end)) { + case 'k' : + case '\0' : exp = 0; break; + case 'm' : exp = 1; break; + case 'g' : exp = 2; break; + default: return 0; + } + + if (*end) + end++; + + if (*end) { + fprintf(stderr, "garbage after end of number\n"); + return 0; + } + + /* result: number + 1024^(exp) */ + return result * ((2 << ((10 * exp) - 1)) ?: 1); +} + +/* convert the sector number into a CHS value for the partition table */ +static void to_chs(long sect, unsigned char chs[3]) { + int c,h,s; + + s = (sect % sectors) + 1; + sect = sect / sectors; + h = sect % heads; + sect = sect / heads; + c = sect; + + chs[0] = h; + chs[1] = s | ((c >> 2) & 0xC0); + chs[2] = c & 0xFF; + + return; +} + +/* round the sector number up to the next cylinder */ +static inline unsigned long round_to_cyl(long sect) { + int cyl_size = heads * sectors; + + return sect + cyl_size - (sect % cyl_size); +} + +/* check the partition sizes and write the partition table */ +static int gen_ptable(int nr) +{ + struct pte pte[4]; + unsigned long sect = 0; + unsigned int start, len; + int i, fd, ret = -1; + + memset(pte, 0, sizeof(struct pte) * 4); + for (i = 0; i < nr; i++) { + if (!parts[i].size) { + fprintf(stderr, "Invalid size in partition %d!\n", i); + return -1; + } + pte[i].active = ((i + 1) == active) ? 0x80 : 0; + pte[i].type = parts[i].type; + pte[i].start = cpu_to_le16(start = sect + sectors); + sect = round_to_cyl(start + parts[i].size * 2); + pte[i].length = cpu_to_le16(len = sect - start); + to_chs(start, pte[i].chs_start); + to_chs(start + len - 1, pte[i].chs_end); + if (verbose) + fprintf(stderr, "Partition %d: start=%u, end=%u, size=%u\n", i, start * 512, (start + len) * 512, len * 512); + } + + if ((fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) { + fprintf(stderr, "Can't open output file '%s'\n",filename); + return -1; + } + + lseek(fd, 446, SEEK_SET); + if (write(fd, pte, sizeof(struct pte) * 4) != sizeof(struct pte) * 4) { + fprintf(stderr, "write failed.\n"); + goto fail; + } + lseek(fd, 510, SEEK_SET); + if (write(fd, "\x55\xaa", 2) != 2) { + fprintf(stderr, "write failed.\n"); + goto fail; + } + + ret = 0; +fail: + close(fd); + return ret; +} + +static void usage(char *prog) +{ + fprintf(stderr, "Usage: %s [-v] -h -s -o [-a 0..4] [[-t ] -p ...] \n", prog); + fprintf(stderr, "Usage: %s -g \n", prog); + exit(1); +} + +int main (int argc, char **argv) +{ + char type = 0x83; + int ch; + int part = 0; + + while ((ch = getopt(argc, argv, "h:s:p:a:t:o:vg:")) != -1) { + switch (ch) { + case 'o': + filename = optarg; + break; + case 'v': + verbose++; + break; + case 'h': + heads = (int) strtoul(optarg, NULL, 0); + break; + case 's': + sectors = (int) strtoul(optarg, NULL, 0); + break; + case 'p': + if (part > 3) { + fprintf(stderr, "Too many partitions\n"); + exit(1); + } + parts[part].size = to_kbytes(optarg); + parts[part++].type = type; + break; + case 't': + type = (char) strtoul(optarg, NULL, 16); + break; + case 'a': + active = (int) strtoul(optarg, NULL, 0); + if ((active < 0) || (active > 4)) + active = 0; + break; + case 'g': + getmaxsize(optarg); + exit(0); + case '?': + default: + usage(argv[0]); + } + } + argc -= optind; + if (argc || (heads <= 0) || (sectors <= 0) || !filename) + usage(argv[0]); + + return gen_ptable(part); +} -- cgit v1.2.3