diff options
author | John Lane <john@lane.uk.net> | 2012-08-22 23:35:31 +0100 |
---|---|---|
committer | John Lane <john@lane.uk.net> | 2012-08-22 23:35:31 +0100 |
commit | 02352f3e032b049a5d8d3636e10ef111c3f3c4e9 (patch) | |
tree | bd182921663311941f693d553b7b238e6984857e | |
download | rpi-utils-02352f3e032b049a5d8d3636e10ef111c3f3c4e9.zip rpi-utils-02352f3e032b049a5d8d3636e10ef111c3f3c4e9.tar.gz rpi-utils-02352f3e032b049a5d8d3636e10ef111c3f3c4e9.tar.bz2 |
Initial Commit
-rw-r--r-- | .gitignore | 12 | ||||
-rw-r--r-- | LICENSE | 24 | ||||
-rw-r--r-- | README.md | 38 | ||||
-rw-r--r-- | archbuild/README.md | 25 | ||||
-rw-r--r-- | archbuild/archbuild | 44 | ||||
-rw-r--r-- | archbuild/commands | 39 | ||||
-rwxr-xr-x | archbuild/source_files/cmdline.txt | 1 | ||||
-rw-r--r-- | archbuild/source_files/inittab | 49 | ||||
-rw-r--r-- | archbuild/source_files/locale.gen | 4 | ||||
-rw-r--r-- | archbuild/source_files/mirrorlist | 30 | ||||
-rw-r--r-- | archbuild/source_files/securetty | 16 | ||||
-rw-r--r-- | archbuild/unmount | 8 | ||||
-rw-r--r-- | disk/README.md | 22 | ||||
-rwxr-xr-x | disk/rpi_mkimage | 659 | ||||
-rwxr-xr-x | disk/rpi_mount | 82 | ||||
-rwxr-xr-x | disk/rpi_umount | 51 | ||||
-rw-r--r-- | emulator/README.md | 44 | ||||
-rwxr-xr-x | emulator/boot | 22 | ||||
-rwxr-xr-x | emulator/setup | 31 | ||||
-rw-r--r-- | scrapbook/CONTENTS.md | 24 | ||||
-rw-r--r-- | scrapbook/HowTo_Install_GRUB_into_a_disk_image.pdf | bin | 0 -> 58715 bytes | |||
-rw-r--r-- | scrapbook/HowTo_Mount_Image.md | 49 | ||||
-rw-r--r-- | scrapbook/HowTo_Pacman_Keyring_Entropy.md | 15 | ||||
-rw-r--r-- | scrapbook/Notes_Formatting_SD.md | 16 | ||||
-rwxr-xr-x | scrapbook/build | 53 | ||||
-rwxr-xr-x | scrapbook/mkpartitions | 7 |
26 files changed, 1365 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..93e4932 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# Generic files to ignore +*.un~ +*.swp + +# Specifially ignore emulator images +emulator/*img +emulator/*raw +emulator/kernel-qemu + +# Specifically ignore disk images +disk/*img +disk/myimage @@ -0,0 +1,24 @@ +Copyright (c) 2012 John Lane + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +http://www.opensource.org/licenses/mit-license.php diff --git a/README.md b/README.md new file mode 100644 index 0000000..ce1407d --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# Raspberry-Pi Utilities + +This is a collection of things to do with the Raspberry Pi that are made available +to the community in the hope they are useful to others. + +## ArchBuild + +ArchBuild will build a new root filesystem for the Raspberry Pi. Use it instead of +the official image if you want to tweak the installation. + +## Kernel + +Building a custom kernel. + +## Disk + +Some tools that can help with managing disks (or other storage devices, e.g: sd card) +and disk images. + +## ScrapBook + +A collection of notes, scripts and other things that may be of interest. Basically, +anything I have found useful will end up in here if they don't fit in anywhere +else. See the ScrapBook CONTENTS file details of what's there. + +## Colophon + +### Copyright + +Copyright (c) 2012 John Lane. + +### License + +This collection of Raspberry-Pi Utilities is provided under the MIT License. See LICENSE file. + +### Latest Version + +Obtain the latest version from [GitHub](https://github.com/johnlane/rpi-utils) diff --git a/archbuild/README.md b/archbuild/README.md new file mode 100644 index 0000000..5f87b28 --- /dev/null +++ b/archbuild/README.md @@ -0,0 +1,25 @@ +# Raspberry-Pi Utilities : ArchBuild + +ArchBuild will build a new root filesystem for the Raspberry Pi. Use it instead of +the official image if you want to tweak the installation. + +## Source Files + +The directory 'source_files' contains the files needed to complete the build +of a new root filesystem. This directory can be re-created using the collect +script described below. + +## Collect + +This is a simple script to collect the required files from a running raspberry-Pi +Arch Linux system. + +## ArchBuild + +This is a script to build a new baseline Arch Linux root filesystem image. It +requires that the source files directory (described above) exists. + +### Unmount + +This is a quick and dirty script to unmount the archroot created by build if, +for some reason, the build script fails uncleanly. diff --git a/archbuild/archbuild b/archbuild/archbuild new file mode 100644 index 0000000..6aaed48 --- /dev/null +++ b/archbuild/archbuild @@ -0,0 +1,44 @@ +#!/bin/bash +# +# archbuild : build an Arch Linux system (run this on the Raspberry Pi) +# + +PACMAN_MIRRORLIST=`mktemp` +PACMAN_CONF=`mktemp` +curl https://projects.archlinux.org/svntogit/packages.git/plain/trunk/pacman.conf?h=packages/pacman > "$PACMAN_CONF" +VPS_ARCH=arm +sed -i -e "s@/etc/pacman.d/mirrorlist@$PACMAN_MIRRORLIST@g" -e "s/\Architecture = auto/Architecture = "$VPS_ARCH"/g" "$PACMAN_CONF" +sed -i -e 's/^SigLevel/#SigLevel/' -e '/^#SigLevel = Optional TrustedOnly/a\SigLevel = Never' "$PACMAN_CONF" +sed -i -e 's/^CheckSpace/#CheckSpace/' "$PACMAN_CONF" +echo -e "[alarm]\nInclude = $PACMAN_MIRRORLIST" >> "$PACMAN_CONF" +country='GB' +cp /etc/pacman.d/mirrorlist $PACMAN_MIRRORLIST +VPS_PACKAGES="bash bzip2 coreutils cronie cryptsetup device-mapper dhcpcd diffutils e2fsprogs file filesystem findutils gawk gcc-libs gettext glibc grep gzip heirloom-mailx inetutils initscripts iputils jfsutils less licenses logrotate lvm2 man-db man-pages mdadm nano pacman pacman-mirrorlist pciutils perl ppp procps-ng psmisc reiserfsprogs sed shadow sysfsutils syslog-ng sysvinit tar texinfo usbutils util-linux vi wget which wpa_supplicant xfsprogs linux-raspberrypi linux-headers-raspberrypi raspberrypi-firmware" +mkarchroot -C "$PACMAN_CONF" archroot $VPS_PACKAGES +cp $PACMAN_MIRRORLIST archroot/etc/pacman.d/mirrorlist +sed -i -e "s:$PACMAN_MIRRORLIST:/etc/pacman.d/mirrorlist:" archroot/etc/pacman.conf +echo -e "root\nroot\n" | chroot archroot /usr/bin/passwd root +cp /etc/securetty archroot/etc/securetty +cp /etc/inittab archroot/etc/inittab +cp /etc/locale.gen archroot/etc/locale.gen +chroot archroot /usr/sbin/locale-gen +chroot archroot mknod -m 600 /dev/console c 5 1 +chroot archroot mknod -m 666 /dev/null c 1 3 +chroot archroot mknod -m 666 /dev/zero c 1 5 +chroot archroot yes | /usr/bin/pacman -Scc + +# +# Boot files +# +#cp /boot/bootcode.bin archroot/boot +#cp /boot/loader.bin archroot/boot +#cp /boot/arm???_start.elf archroot/boot +#cp archroot/boot/{arm224_,}start.elf +cp /boot/cmdline.txt archroot/boot + +DATE=$(date +%d-%m-%Y) +cd archroot +tar cJf ../archlinuxarm-$DATE.tar.xz ./* +cd .. +sha1sum archlinuxarm-jl-$DATE.tar.gz > archlinuxarm-$DATE.tar.gz.sha1 +rm -rf archroot* diff --git a/archbuild/commands b/archbuild/commands new file mode 100644 index 0000000..6712d05 --- /dev/null +++ b/archbuild/commands @@ -0,0 +1,39 @@ +PACMAN_MIRRORLIST=`mktemp` +PACMAN_CONF=`mktemp` +curl https://projects.archlinux.org/svntogit/packages.git/plain/trunk/pacman.conf?h=packages/pacman > "$PACMAN_CONF" +VPS_ARCH=arm +sed -i -e "s@/etc/pacman.d/mirrorlist@$PACMAN_MIRRORLIST@g" -e "s/\Architecture = auto/Architecture = "$VPS_ARCH"/g" "$PACMAN_CONF" +sed -i -e 's/^SigLevel/#SigLevel/' -e '/^#SigLevel = Optional TrustedOnly/a\SigLevel = Never' "$PACMAN_CONF" +sed -i -e 's/^CheckSpace/#CheckSpace/' "$PACMAN_CONF" +echo -e "[alarm]\nInclude = $PACMAN_MIRRORLIST" >> "$PACMAN_CONF" +country='GB' +cp /etc/pacman.d/mirrorlist $PACMAN_MIRRORLIST +VPS_PACKAGES="bash bzip2 coreutils cronie cryptsetup device-mapper dhcpcd diffutils e2fsprogs file filesystem findutils gawk gcc-libs gettext glibc grep gzip heirloom-mailx inetutils initscripts iputils jfsutils less licenses logrotate lvm2 man-db man-pages mdadm nano pacman pacman-mirrorlist pciutils perl ppp procps-ng psmisc reiserfsprogs sed shadow sysfsutils syslog-ng sysvinit tar texinfo usbutils util-linux vi wget which wpa_supplicant xfsprogs linux-raspberrypi linux-headers-raspberrypi raspberrypi-firmware" +mkarchroot -C "$PACMAN_CONF" archroot $VPS_PACKAGES +cp $PACMAN_MIRRORLIST archroot/etc/pacman.d/mirrorlist +sed -i -e "s:$PACMAN_MIRRORLIST:/etc/pacman.d/mirrorlist:" archroot/etc/pacman.conf +echo -e "root\nroot\n" | chroot archroot /usr/bin/passwd root +cp /etc/securetty archroot/etc/securetty +cp /etc/inittab archroot/etc/inittab +cp /etc/locale.gen archroot/etc/locale.gen +chroot archroot /usr/sbin/locale-gen +chroot archroot mknod -m 600 /dev/console c 5 1 +chroot archroot mknod -m 666 /dev/null c 1 3 +chroot archroot mknod -m 666 /dev/zero c 1 5 +chroot archroot yes | /usr/bin/pacman -Scc + +# +# Boot files +# +#cp /boot/bootcode.bin archroot/boot +#cp /boot/loader.bin archroot/boot +#cp /boot/arm???_start.elf archroot/boot +#cp archroot/boot/{arm224_,}start.elf +cp /boot/cmdline.txt archroot/boot + +DATE=$(date +%d-%m-%Y) +cd archroot +#tar cJf ../archlinuxarm-jl-$DATE.tar.xz ./* +cd .. +#sha1sum archlinuxarm-jl-$DATE.tar.gz > archlinuxarm-jl-$DATE.tar.gz.sha1 +#rm -rf archroot* diff --git a/archbuild/source_files/cmdline.txt b/archbuild/source_files/cmdline.txt new file mode 100755 index 0000000..34817c5 --- /dev/null +++ b/archbuild/source_files/cmdline.txt @@ -0,0 +1 @@ +smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 loglevel=2 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait diff --git a/archbuild/source_files/inittab b/archbuild/source_files/inittab new file mode 100644 index 0000000..51d9af0 --- /dev/null +++ b/archbuild/source_files/inittab @@ -0,0 +1,49 @@ +# +# /etc/inittab +# + +# Runlevels: +# 0 Halt +# 1(S) Single-user +# 2 Not used +# 3 Multi-user +# 4 Not used +# 5 X11 +# 6 Reboot + +## Only one of the following two lines can be uncommented! +# Boot to console +id:3:initdefault: +# Boot to X11 +#id:5:initdefault: + +rc::sysinit:/etc/rc.sysinit +rs:S1:wait:/etc/rc.single +rm:2345:wait:/etc/rc.multi +rh:06:wait:/etc/rc.shutdown +su:S:wait:/sbin/sulogin -p + +# -8 options fixes umlauts problem on login +#s0:12345:respawn:/sbin/agetty -8 -s 115200 ttyS0 linux +c1:2345:respawn:/sbin/agetty -8 -s 115200 tty1 +c2:2345:respawn:/sbin/agetty -8 -s 115200 ttyAMA0 +c3:2345:respawn:/sbin/agetty -8 -s 115200 tty3 +c4:2345:respawn:/sbin/agetty -8 -s 115200 tty4 +#c5:2345:respawn:/sbin/agetty -8 -s 38400 tty5 linux +#c6:2345:respawn:/sbin/agetty -8 -s 38400 tty6 linux + +# Serial Virtual Console for KVM and others VMs +#s0:2345:respawn:/sbin/agetty -8 -s 9600 ttyS0 linux + +# Hypervisor Virtual Console for Xen and KVM +#h0:2345:respawn:/sbin/agetty -8 -s 38400 hvc0 linux + +ca::ctrlaltdel:/sbin/shutdown -t3 -r now + +# Example lines for starting a login manager +x:5:respawn:/usr/bin/xdm -nodaemon +#x:5:respawn:/usr/sbin/gdm -nodaemon +#x:5:respawn:/usr/bin/kdm -nodaemon +#x:5:respawn:/usr/bin/slim >/dev/null 2>&1 + +# End of file diff --git a/archbuild/source_files/locale.gen b/archbuild/source_files/locale.gen new file mode 100644 index 0000000..5192d4b --- /dev/null +++ b/archbuild/source_files/locale.gen @@ -0,0 +1,4 @@ +en_US.UTF-8 UTF-8 +en_US ISO-8859-1 +de_DE ISO-8859-1 +de_DE@euro ISO-8859-15 diff --git a/archbuild/source_files/mirrorlist b/archbuild/source_files/mirrorlist new file mode 100644 index 0000000..1b88df8 --- /dev/null +++ b/archbuild/source_files/mirrorlist @@ -0,0 +1,30 @@ +# +# Arch Linux ARM repository mirrorlist +# Generated on 2012-06-08 +# + +## Geo-IP based mirror selection and load balancing +Server = http://mirror.archlinuxarm.org/arm/$repo + +### Mirrors by country + +### China +# Server = http://cn.mirror.archlinuxarm.org/arm/$repo + +### Finland +# Server = http://fi.mirror.archlinuxarm.org/arm/$repo + +### Germany +# Server = http://eu.mirror.archlinuxarm.org/arm/$repo +# Server = http://6.eu.mirror.archlinuxarm.org/arm/$repo + +### Netherlands +# Server = http://nl.mirror.archlinuxarm.org/arm/$repo + +### United States +## CA +# Server = http://ca.us.mirror.archlinuxarm.org/arm/$repo +## IL +# Server = http://us.mirror.archlinuxarm.org/arm/$repo +## VA +# Server = http://va.us.mirror.archlinuxarm.org/arm/$repo diff --git a/archbuild/source_files/securetty b/archbuild/source_files/securetty new file mode 100644 index 0000000..4b43ead --- /dev/null +++ b/archbuild/source_files/securetty @@ -0,0 +1,16 @@ +# +# /etc/securetty +# + +console +tty1 +#tty2 +ttyAMA0 +tty3 +tty4 +#tty5 +#tty6 +#ttyS0 +#hvc0 + +# End of file diff --git a/archbuild/unmount b/archbuild/unmount new file mode 100644 index 0000000..8d43074 --- /dev/null +++ b/archbuild/unmount @@ -0,0 +1,8 @@ +umount archroot/sys +umount archroot/proc/sys +umount archroot/proc +umount archroot/dev/shm +umount archroot/dev/pts +umount archroot/dev +umount archroot/var/cache/pacman/pkg +umount archroot/run diff --git a/disk/README.md b/disk/README.md new file mode 100644 index 0000000..fa12a8d --- /dev/null +++ b/disk/README.md @@ -0,0 +1,22 @@ +# Raspberry-Pi Utilities : Disk + +Disk utilitles for working with SD cards and images. + +Root privileges are required. + +## rpi_mkimage + +Use rpi_mkimage to prepare a fileystem image or device. see rpi_mkimage --help +for further information. + +## rpi_mount + +Use rpi_mount to mount an image or device. It first mounts the root partition and +then mounts the boot partition on top. If mounting an image, it first creates +a loop device. + +## rpi_unmount + +Use rpi_umount to unmount an image or device mounted by the mount command described +above. It also removes any loop device used to mount an image. + diff --git a/disk/rpi_mkimage b/disk/rpi_mkimage new file mode 100755 index 0000000..8f7d545 --- /dev/null +++ b/disk/rpi_mkimage @@ -0,0 +1,659 @@ +#!/usr/bin/env python2 +# +LICENSE=""" +Copyright (c) 2012 John Lane + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +http://www.opensource.org/licenses/mit-license.php +""" + +DESCRIPTION=""" +rpi_mkimg : Make a Raspberry Pi SD Card Image + +Describes and, optionally, makes a disk image with partitions +and filesystems prepared in accordance with the write and erase +geometries of the target device. Optionally copies files into +the new image from another image, directory or archive (tar file). + +Quick Start +----------- + +Those that don't want to read the detail can try this: + + $ sudo rpi_mkimg --device=sdcard --copy=image --create + +where 'sdcard' is the name of the sdcard device (e.g. mmcblk0) + and 'image' is the name of an image to copy (e.g. + archlinuxarm-13-06-2012.img) + +Detail +------ + +A device and/or an image name can be given as command-line +arguments. + +If a device is given (such as an SD card that will be used +to boot a Raspberry Pi), it will be used to set the attributes +that are used to determine the block-level layout of the image. + +If no device is given then default values are used: + + volume size = 2GiB + preferred erase size = 4MiB + +These attributes are used to define a partitioning scheme +that ensures block alignment of the partitions and the file- +systems on those partitions. Two partitions are created: + + boot : a FAT32 partition (at least 40Mb) + root : an ext4 partition + +The partitioning scheme is displayed on standard output. + +A command-line argument can be given which causes a disk image +to be created using the partitioning scheme. If this argument is +not given then this will not happen. This is to protect against +accidental writes. + +The image can be written directly onto the device or it can +be written to a file that can be subsequently transferred onto +a suitable device using 'dd'. + +If an image is specified then a new file will be created (replacing +any existing file of the same name) and the partitioning scheme +applied to it. + +If an image is not specified but a device is specified then +the partitioning scheme will be applied to the device. + +NOTE: All contents of the device or any existing image file + will be overwritten! + +If neither image nor device are specified, the create argument +is ignored and nothing will be created. + +Write permission to the image or device is required. Normally +the latter will require root permissions. + +A command-line argument can be given which will copy files into +the created image. This mounts the new image's root filesystem +and then mounts its boot filesystem on top at /boot. The copy is +then performed into the mount point. + +The files to be copied can be in another image file, directory +or archive (tar) file. + +Block Alignment +--------------- + +The attribute used to define the device's block alignment is +called preferred erase size. The actual value can be overriden +using a command line argument. + +Block alignment is performed on the partitions as well as on the +filesystems within them. + +Partitions and Filesystems +-------------------------- + +Two partitions are created in accordance with the requirements +of the Raspberry Pi: A FAT32 partition containing a FAT16 boot +filesystem and a linux partition containing an ext4 root file- +system. Both partitions and filesystems are created in such a +way that their data blocks are aligned with those of the device. + +By default: + + - the boot partition size will be 40Mb but it may be larger than + this if the device's block sizes result in larger partitions; + + - the root partition size will consume all of the + remaining space in the image; + + - the total image size will be the size of any specified device + or 2GiB. + +Default sizes may be overridden using command-line arguments: + + - specifying a minimum size for a partition will ensure that the + partition is at least that size. If this this cannot be achieved + then the programme will exit with an appropriate message. + + - specifying a maximum size for a partition will make the + partition no bigger than that maximum (subject to block alignment, + see below) and any remaining space in the image will be unused. + +Partitions may be sized larger than a specified maximum if this is +necessary to achieve block alignment. + +Operational requirements +------------------------ + +Arch Linux package requirements: + parted : to make partitions + dosfstools : to make vfat partition + python-pexpect : Python Expect used to run commands + +The loop device is used to mount image files. Ensure the "loop" kernel +module is loaded: "modprobe loop" should achieve this. + +Commands requiring privileged entitlements are executed with sudo. + + + (c) John Lane 2012-08-03. + Licensed under the MIT License. + + Part of the rpi-utilities: + https://github.com/johnlane/rpi-utils + +""" + + +# References: +# +import sys +import os +import pexpect +import argparse +import atexit +import tempfile +import pwd + +def align(sector,grain): + if args.align == True: + excess = sector%grain + sector = sector if excess == 0 else sector + grain - excess + return sector + +def print_partition_info(name,start_sector,end_sector): + + size_mib = (end_sector - start_sector + 1) * 512 / (1<<20) + + print "------------------------------------------------------------" + print " Partition '%s':" % name + print " Start sector : %d" % start_sector + print " End sector : %d" % end_sector + print " 512 byte sectors : %d" % (end_sector - start_sector + 1) + print " 1KiB Blocks : %d" % ((end_sector - start_sector + 1) / 2) + print " Size : %d MiB" % ((end_sector - start_sector + 1) * 512 / (1<<20)) + print "------------------------------------------------------------" + +def gib(n): + return (float(n)/(1<<30)) + +def mib(n): + return (float(n)/(1<<20)) + +def kib(n): + return (float(n)/(1<<10)) + +def print_bytes(label,value): + llen=len(label) + print "%s : %d bytes" % (label,value) + if value>=(1<<10) and value<(1<<20): print "%s : %g Kib" % (''.rjust(llen),kib(value)) + if value>=(1<<20): print "%s : %g Mib" % (''.rjust(llen),mib(value)) + if value>=(1<<30): print "%s : %g Gib" % (''.rjust(llen),gib(value)) + +def run_command(command): + output, exit_status = pexpect.run(command, withexitstatus=1) + output = output.strip() + return output, exit_status + +def do_or_die(command,error_message="Command Failed"): + output, exit_status = run_command(command) + if exit_status != 0: + abort("%s : %s" % (error_message, output)) + return output + +def writable_or_die(d): + if os.access(d,os.W_OK) != True: + abort("No write access to %s" % d) + +def create_loop_device(d): + loop_device = do_or_die("losetup -f","Unable to get a loop device") + debug("Setting up loop device %s for %s" % (loop_device,d)) + do_or_die("losetup -P %s %s" % (loop_device,d), "Unable to create loop device") + return loop_device + +def destroy_loop_device(d): + do_or_die("losetup -d %s" % d,"Unable to destroy loop device") + + +def abort(error_message): + sys.exit("%s. Cannot continue" % error_message) + +############################################################################################## +# A very primitive message logger +LOG_DEBUG = 'debug' +LOG_VERBOSE = 'verbose' +def verbose(message): log(LOG_VERBOSE,message) +def debug(message): log(LOG_DEBUG,message) +def log(level,message): + if args.loglevels != None and level in args.loglevels: print "(%s) %s" % (level,message) +def debug_enabled(): return args.loglevels != None and LOG_DEBUG in args.loglevels +def verbose_enabled(): return args.loglevels != None and LOG_VERBOSE in args.loglevels +############################################################################################## + +def allocate_sectors(first_sector,available_sectors,sector_alignment_grain,minimum_kb,maximum_kb,align_start=True): + min_sectors = minimum_kb / 512 + max_sectors = maximum_kb / 512 + + if minimum_kb < ( min_sectors * 512 ): min_sectors += 1 + if maximum_kb < ( max_sectors * 512 ): max_sectors += 1 + + if max_sectors == 0: max_sectors = available_sectors + + debug("requested minimum %s and maximum %s sectors" % (min_sectors,max_sectors)) + + # align the first sector except unless requested not to + start_sector = align(first_sector,sector_alignment_grain) if align_start else first_sector + + debug("allocating sectors, %d available starting at sector %d" % (available_sectors,start_sector)) + debug("starting sector %d aligned to %d" % (first_sector,start_sector)) + available_sectors -= (start_sector - first_sector) + debug("%d available sectors after front alignment" % available_sectors) + + if available_sectors < min_sectors: + abort("Unable to allocate %d sectors (%d available)" % (min_sectors,available_sectors)) + + num_sectors = max_sectors if available_sectors >= max_sectors else available_sectors + debug( "allocated %d sectors" % num_sectors) + + next_sector = start_sector + num_sectors + debug("the next free sector is %d" % next_sector) + + # Unless we've used up all sectors, align the next free sector and extend allocation + if next_sector == start_sector + available_sectors: + + # There are no more free sectors; the end sector is one less than the total number of sectors + # fdisk numbers LBA sectors from 0 but sector 0 is 'hidden' and contains the MBR. Sector + # numbers for partitions start at 1. Because there is a sector 0 the number of the last + # sector is one less than the total number of sectors. The value 'next sector' will be one + # greater than the total number of sectors, so we subtract 2 to get the last sector. + # + end_sector = next_sector - 1 + next_sector = 0 + available_sectors = 0 + + elif next_sector > start_sector + available_sectors: + + # This case should never arise + abort("Unexpected sector number %d, which is greater than the total number of sectors, %d" % (next_sector,start_sector + available_sectors)) + + else: + + # Align the next free sector; the end sector is the one before that + next_sector = align(next_sector,sector_alignment_grain) + end_sector = next_sector - 1 + + debug("start %d" % start_sector) + debug("end %d" % end_sector) + debug("num %d" % num_sectors) + debug("next %d" % next_sector) + + return start_sector, end_sector, next_sector, available_sectors - (end_sector +1 - start_sector) + +def main(name, argv): + + def cleanup(): + try: + if loop_device: destroy_loop_device(loop_device) + if copy_loop_device: destroy_loop_device(copy_loop_device) + except NameError as e: + pass # move along, nothing to do + + atexit.register(cleanup) + + # Default sizes + pes = 4<<20 # 4MiB + #wbs = 8<<10 # 8KiB (not used) + vs = 2<<30 # 2GiB + + + # Parition sizing minima/maxima + bp_size_minimum = 40<<20 # 40MiB + bp_size_maximum = 40<<20 # 40MiB + rp_size_minimum = 1<<30 # 1GiB + rp_size_maximum = 0 # No limit + + # Arguments + global args + parser = argparse.ArgumentParser(description=DESCRIPTION, formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('--license', action='store_true', default=False, dest='license', + help='show the MIT License') + parser.add_argument('-d', '--device', action='store', dest='device', + help='Specify a device name (e.g. mmcblk0)') + parser.add_argument('-i', '--image', action='store', dest='image', + help='Specify an image file name(e.g. myimage.img)') + parser.add_argument('--copy', action='store', dest='copy', + help='Copy into the image from another image, directory or archive (tar) file ') + parser.add_argument('-c', '--create', action='store_true', default=False, dest='create', + help='Create (overwrites existing data)') + parser.add_argument('-v', '--verbose', action='append_const', const=LOG_VERBOSE, dest='loglevels', + help='Enable verbose message output') + parser.add_argument('--debug', action='append_const', const=LOG_DEBUG, dest='loglevels', + help='Enable debug message output') + + parser.add_argument('--boot-minimum', action='store', dest='bp_size_minimum', + help='Override the boot partition minimum size default (%d)'%bp_size_minimum) + parser.add_argument('--boot-maximum', action='store', dest='bp_size_maximum', + help='Override the boot partition maximum size default (%d)'%bp_size_maximum) + parser.add_argument('--root-minimum', action='store', dest='rp_size_minimum', + help='Override the root partition minimum size default (%d)'%rp_size_minimum) + parser.add_argument('--root-maximum', action='store', dest='rp_size_maximum', + help='Override the root partition maximum size default (%d)'%rp_size_maximum) + + parser.add_argument('--first-sector', action='store', dest='first_sector', + help='Specify a first sector to use (default is sector 1)') + parser.add_argument('--size', action='store', dest='volume_size', + help='Specify the size of the whole disk in bytes (default is %d bytes)'%vs) + parser.add_argument('--erase-block-size', action='store', dest='erase_block_size', + help='Specify the erase block size bytes (default is %d bytes or that of the device specified with -d)'%vs) + #parser.add_argument('--write-block-size', action='store', dest='write_block_size', + # help='Specify the write block size bytes (default is %d bytes or that of the device specified with -d)'%vs) + + parser.add_argument('--no-align', action='store_false', default=True, dest='align', + help='Disable write block alignment') + parser.add_argument('--no-align-first', action='store_false', default=True, dest='align_first_partition', + help='Do not align the first partition (it will start at first-sector)') + + args = parser.parse_args() + + if args.license == True: + print LICENSE + return 0 + + if args.bp_size_minimum != None: bp_size_minimum = int(args.bp_size_minimum) + if args.bp_size_maximum != None: bp_size_maximum = int(args.bp_size_maximum) + if args.rp_size_minimum != None: rp_size_minimum = int(args.rp_size_minimum) + if args.rp_size_maximum != None: rp_size_maximum = int(args.rp_size_maximum) + + # Preferred Erase Size + if args.erase_block_size != None: + pes = int(args.erase_block_size) + elif (args.device != None): + try: + device = args.device + device_sys_path = "/sys/class/block/%s" % (device, ) + pes = int(file(device_sys_path+"/device/preferred_erase_size").read()) + print "Using device %s" % device + vss = int(file(device_sys_path+"/size").read()) + vs = vss * 512 + except IOError as e: + print "Device %s not found: Using default values." % device + else: + print "No Device specified: Using default values." + + # Write Block Size + #if args.write_block_size != None: wbs = int(args.write_block_size) + + # Volume size in sectors + if args.volume_size != None: vs = int(args.volume_size) + vss = vs / 512 # vs in sectors + + # First available sector (sector 0 is reserved for the MBR which contains the partition table) + first_sector = 1 if args.first_sector == None else int(args.first_sector) + + print "------------------------------------------------------------" + + print "Volume Size : %d sectors" % vss + print_bytes("Volume Size",vs) + + if bp_size_minimum>0: print_bytes("Boot Partition Minimum Size",bp_size_minimum) + if bp_size_maximum>0: print_bytes("Boot Partition Maximum Size",bp_size_maximum) + if rp_size_minimum>0: print_bytes("Root Partition Minimum Size",rp_size_minimum) + if rp_size_maximum>0: print_bytes("Root Partition Maximum Size",rp_size_maximum) + + #print_bytes("Write Block Size",wbs) + print_bytes("Preferred Erase Size",pes) + + # sector alignment grain in sectors (512 bytes per sector) + sector_alignment_grain = pes/512 + print "Sector Alignment Grain : %d / 512 = %d sectors" % (pes,sector_alignment_grain) + + # Total number of available sectors includes the first sector (which is sector 0) + # the unused sectors are 0 thru (first_sector -1). Sector 0 is reserved for the MBR. + available_sectors = vss - first_sector + + print "Starting at sector %d of %d total sectors" % (first_sector,vss) + print "The %d available sectors are %d thru %d" % (available_sectors,first_sector,vss-1) + print "%d sectors will be skipped (sectors 0 thru %d)" % (first_sector,first_sector-1) + + + print + print " Partition description" + + # Boot partition + bp_start_sector, bp_end_sector, next_sector, available_sectors = allocate_sectors(first_sector,available_sectors,sector_alignment_grain,bp_size_minimum,bp_size_maximum,args.align_first_partition) + print_partition_info("boot",bp_start_sector, bp_end_sector) + + # Root partition + rp_start_sector, rp_end_sector, next_sector, available_sectors = allocate_sectors(next_sector,available_sectors,sector_alignment_grain,rp_size_minimum,rp_size_maximum) + print_partition_info("root",rp_start_sector,rp_end_sector) + + # Report any unused sectors + if available_sectors > 0: + print "Partitioning scheme leaves %s sectors unused" % available_sectors + + # Only proceed if create option given + if args.create == False: + return 0 + + # must be root to go beyond here + if os.geteuid() != 0: + abort('Partitioning requires root privileges (and you are not root)') + + # Where to write data + if args.image != None: + dest = args.image + elif args.device != None: + dest = args.device + dest_device = "/dev/%s" % dest + else: + print "Nothing to Create: neither device nor image specified." + return 0 + + # If dest is an image, create the image file and set up a loop device for it + if dest == args.image: + try: + if os.path.exists(dest): os.remove(dest) # remove any old image first + if pexpect.run('/bin/bash -c "df -T . | tail -1 | awk \'{print $2}\'"').rstrip() == "ext4": + debug("Using fallocate to create %s (%d bytes)" % (dest,vs)) + pexpect.run("fallocate -l %d %s" % (vs,dest)) + else: + debug("Using truncate to create %s (%d bytes)" % (dest,vs)) + pexpect.run("truncate -s %d %s" % (vs,dest)) + + # make file owned by actual user (e.g. not root if invoked with sudo) + user = pexpect.run('logname').strip() + if user != os.environ['USER']: + uid = pwd.getpwnam(user).pw_uid + gid = pwd.getpwnam(user).pw_gid + os.chown(dest,uid,gid) + debug("Changed %s ownweship to user %s (%d:%d)" % (dest,user,uid,gid)) + + loop_device = create_loop_device(dest) + dest_device = loop_device + + dest_size = os.path.getsize("myimage") + if dest_size != vs: + os.remove(dest) + abort("Created %s has incorrect size %d (expected %d)"%(dest,dest_size,vs)) + + except IOError as e: + abort("Unable to create %s" % dest) + + # Make sure we can write to the destination + writable_or_die(dest_device) + + debug("Will write to %s as %s" % (dest,dest_device)) + + # Get user confirmation + print "About to write new partition table to %s. Any existing data will be lost!!!!" % dest + if (raw_input("Enter 'yes' to continue (anything else quits!)...") != 'yes'): + return 0 + + # Do partitioning with parted + do_or_die("parted -s %s mktable msdos" % dest_device) + do_or_die("parted -s %s unit s mkpart primary fat32 %d %d" % (dest_device,bp_start_sector,bp_end_sector)) + do_or_die("parted -s %s unit s mkpart primary ext2 %d %d" % (dest_device,rp_start_sector,rp_end_sector)) + + # Print the partition table + if verbose_enabled(): do_or_die("parted %s unit s print" % dest_device) + + # Recreate any loop device so partition devices are available + try: + if loop_device: + destroy_loop_device(loop_device) + loop_device = create_loop_device(dest) + except NameError as e: + pass # move along, nothing to do + + # Partition filesystem devices + dest_p1 = dest_device+"p1" + dest_p2 = dest_device+"p2" + + # boot filesystem to be FAT16, aligned + # + # vfat args: + # -I Don't complain about using whole device + # -F 16 FAT size is 16 bit + # -n boot volume label is 'boot' + # -s 16 sectors per cluster (16 * 512 = 8KiB) + # -v Verbose output + # -R number of sectors to reserve + + print "Creating boot filesystem" + + # Make sure we can write to the partition + writable_or_die(dest_p1) + + # Make unaligned FAT filesystem to establish FAT size + mkfs = pexpect.spawn("mkfs.vfat -I -F 16 -n boot -s 16 -v %s" % dest_p1) + if debug_enabled(): mkfs.logfile = sys.stdout + mkfs.expect('FAT size is ([0-9]+) sectors') + fat_sectors = int(mkfs.match.groups()[0]) + mkfs.expect('Volume ID is (.*), volume label (.*)') + vol_id, vol_name = mkfs.match.groups() + mkfs.expect(pexpect.EOF) + + # make aligned FAT filesystem + if args.align == True and args.align_first_partition == True: + + debug("There are %d sectors in the FAT" % fat_sectors) + + # There are two FATS, work out total size in bytes + fat_bytes = fat_sectors * 512 *2 + debug("FAT sectors total %d bytes" % fat_bytes) + + # Work out how many sectors to reserve to achieve alignment + reserved_sectors = (pes - fat_bytes) / 512 + debug("Reserve %d sectors to achieve alignment" % reserved_sectors) + + # Make aligned FAT filesystem + mkfs = pexpect.spawn("mkfs.vfat -I -F 16 -n boot -s 16 -R %d -v %s" % (reserved_sectors, dest_p1)) + if debug_enabled(): mkfs.logfile = sys.stdout + mkfs.expect('Volume ID is (.*), volume label (.*)') + vol_id, vol_name = mkfs.match.groups() + mkfs.expect(pexpect.EOF) + + print "Created volume %s id %s" % (vol_id, vol_name.strip()) + uuid = pexpect.run("blkid -o value -s UUID %s" % dest_p1).strip() + print "Volume UUID: %s" % uuid + + # root partition to be ext4, aligned + # + # ext4 args: + # -O ^has_journal disable journalling + # -E stride=2 treat 2 blocks as 1 + # stripe-width=512 + # -b + # -L root + + print "Creating root filesystem" + + # Make sure we can write to the partition + writable_or_die(dest_p2) + + ext4_block_size = 4096 + ext4_stride = 2 + ext4_stride_size = ext4_block_size * ext4_stride + ext4_stripe_width = pes / ext4_stride_size + + mkfs = pexpect.spawn("mkfs.ext4 -O ^has_journal -E stride=%d,stripe-width=%d -b %d -L root %s" % (ext4_stride, ext4_stripe_width, ext4_block_size, dest_p2)) + if debug_enabled(): mkfs.logfile = sys.stdout + mkfs.expect(pexpect.EOF) + + uuid = pexpect.run("blkid -o value -s UUID %s" % dest_p2).strip() + print "Volume UUID: %s" % uuid + + if args.copy != None: + copy = args.copy + + # Mount the image + dest_mount_point = tempfile.mkdtemp() + debug("Mounting %s on %s" % (dest_p2,dest_mount_point)) + pexpect.run("mount %s %s" % (dest_p2,dest_mount_point)) + os.mkdir(dest_mount_point+"/boot") + debug("Mounting %s on %s" % (dest_p1,dest_mount_point+"/boot")) + pexpect.run("mount %s %s" % (dest_p1,dest_mount_point+"/boot")) + + copy_type = pexpect.run("file %s" % copy).strip() + if "x86 boot sector" in copy_type: + print "Copying from image %s ..." % copy + copy_loop_device = create_loop_device(copy) + copy_boot_device = copy_loop_device+"p1" + copy_root_device = copy_loop_device+"p2" + copy_mount_point = tempfile.mkdtemp() + debug("Mounting %s on %s" % (copy_root_device,copy_mount_point)) + debug("Mounting %s on %s" % (copy_boot_device,copy_mount_point+"/boot")) + pexpect.run("mount %s %s" % (copy_root_device,copy_mount_point)) + pexpect.run("mount %s %s" % (copy_boot_device,copy_mount_point+"/boot")) + debug("Copying from %s to %s" % (copy_mount_point,dest_mount_point)) + os.system("cd %s ; cp -a * %s" % (copy_mount_point,dest_mount_point)) + debug("Unmounting %s" % copy_boot_device) + os.system("umount %s" % copy_boot_device) + debug("Unmounting %s" % copy_root_device) + os.system("umount %s" % copy_root_device) + debug("Removing directory %s" % copy_mount_point) + os.rmdir(copy_mount_point) + + elif "directory" in copy_type: + print "Copyng from directory" % copy + os.system("cd %s ; cp -a * %s" % (copy,dest_mount_point)) + elif "tar archive" in copy_type or "compressed data" in copy_type: + if "compressed data" in copy_type: print "File is compressed (assuming compressed tar file)" + print "Copying from tar file" % copy + os.system("cd %s ; tar xf %s" % (dest_mount_point, copy)) + else: + print "Don't know how to copy %s" % copy + + # Unmount the image + debug("Unmounting %s" % dest_p1) + pexpect.run("umount %s" % dest_p1) # /boot + debug("Unmounting %s" % dest_p2) + pexpect.run("umount %s" % dest_p2) # / + + print "done" + +sys.exit(main(sys.argv[0], sys.argv[1:])) diff --git a/disk/rpi_mount b/disk/rpi_mount new file mode 100755 index 0000000..a130a73 --- /dev/null +++ b/disk/rpi_mount @@ -0,0 +1,82 @@ +#!/bin/bash +# +# Mounts an RPI image or device (sdcard) +# +# usage: rpi_mount image mount_point +# + +# Copyright (c) 2012 John Lane +# +# MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# http://www.opensource.org/licenses/mit-license.php + + +if [[ $(id -u ) != 0 ]]; then + + echo "Must be root" + +elif [[ ! -d $2 ]]; then + + echo "Mount point $2 does not exist" + +else + + if [[ -b $1 ]]; then + + # mount a device + + [[ ${1:5:6} == mmcblk ]] && partition_prefix="p" + + boot_partition=${1}${partition_prefix}1 + root_partition=${1}${partition_prefix}2 + + elif [[ -f $1 ]]; then + + if [[ "$(file -b myimage | awk -F ';' '{print $1}')" == "x86 boot sector" ]]; then + + # loop mount an image + + loop_device=$(losetup -f) + + losetup -P $loop_device $1 + + boot_partition=${loop_device}p1 + root_partition=${loop_device}p2 + + fi + + fi + + if [[ ! -z "${boot_partition}" ]]; then + + mount $root_partition $2 + mkdir -p $2/boot + mount $boot_partition $2/boot + + else + echo "Don't know how to mount $1. Sorry" + fi + +fi + + diff --git a/disk/rpi_umount b/disk/rpi_umount new file mode 100755 index 0000000..02b5d56 --- /dev/null +++ b/disk/rpi_umount @@ -0,0 +1,51 @@ +#!/bin/bash +# +# Unmounts an RPI image or device (sdcard) +# +# usage: rpi_umount mount_point +# +# Copyright (c) 2012 John Lane +# +# MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# http://www.opensource.org/licenses/mit-license.php + +if [[ $(id -u ) != 0 ]]; then + + echo "Must be root" + +else + + for device_path in $(mount | grep $1 | sort | awk '{print $1}') + do + + umount $device_path + + device=$(basename $device_path) + + [[ ${device:0:4} == loop ]] && loop_device=${device_path:0:-2} + + done + + [[ -z "${loop_device}" ]] || losetup -d ${loop_device} + +fi diff --git a/emulator/README.md b/emulator/README.md new file mode 100644 index 0000000..cc6895b --- /dev/null +++ b/emulator/README.md @@ -0,0 +1,44 @@ +# Raspberry Pi Emulator + +This describes a way to run a Raspberry Pi emulator using QEMU. It is written for Arch Linux but +the techniques can be applied to other distributions. + +## Setup + +The setup script will install QEMU if it is not already installed. It will download a filesystem image, +a kernel image and set up a data disk. +Run as-is or modify it for your needs. + +Once the setup script completes, you will have + +1. QEMU installed +2. A system image +3. A ketnel image +4. A data disk image + +## Booting + +The boot script will start QEMU using the images prepared by the setup script. +Run as-is or modify it for your needs. + +## Networking + +The default network stack works. Note that using 'ping' to test the network connection will give the +impression that it isn''t working. This is because ICMP traffic does does not work and is a limitation +of the basic network stack, called SLIRP, provided by QEMU. + +## Data Disk + +The data disk image is presented as /dev/sdb. This needs to be formatted and mounted before use. +Boot the emulator and then do: + + $ mkfs.ext4 /dev/sdb + $ mount /dev/sdb /mnt + +## Acknowledgements + +Getting Raspberry Pi up and running in QEMU was quick and painless thanks to [this tutorial](http://xecdesign.com/qemu-emulating-raspberry-pi-the-easy-way). This worked first time for me with the default qemu package on Arch Linux and the archlinuxarm-13-06-2012.img. + + + + diff --git a/emulator/boot b/emulator/boot new file mode 100755 index 0000000..22fb473 --- /dev/null +++ b/emulator/boot @@ -0,0 +1,22 @@ +#!/bin/bash +# +# Boot the Raspberry Pi in QEMU +# +# Usage: boot [image] +# +# where [image] is a filesystem image to boot from. This is optional: if it is not +# given then it defaults to "archlinux-13-0-6-2012.img" which must be present in +# the current working directory. +# +# JL 2012-08-03 +# + +qemu-system-arm -machine versatilepb \ + -cpu arm1176 \ + -m 256 \ + -no-reboot \ + -serial stdio \ + -kernel kernel-qemu \ + -append "root=/dev/sda2 panic=1" \ + -hda ${1:-archlinuxarm-13-06-2012.img} \ + -hdb data_disk.raw diff --git a/emulator/setup b/emulator/setup new file mode 100755 index 0000000..d9b287d --- /dev/null +++ b/emulator/setup @@ -0,0 +1,31 @@ +#!/bin/bash +# +# Setup images for QEMU Emulator +# +# +# JL 2012-08-03 + +image="13-06-2012" + +# Install QEMU + +pacman -Q qemu > /dev/null 2>&1 || sudo pacman -S qemu + +# Get kernel image + +[[ -f kernel-qemu ]] || wget http://xecdesign.com/downloads/linux-qemu/kernel-qemu + +# Get system image + +[[ -f archlinuxarm-$image.img ]] || { + wget http://achtbaan.nikhef.nl/events/rpi/images/archlinuxarm/archlinuxarm-$image/archlinuxarm-$image.zip + unzip archlinuxarm-$image.zip + mv archlinuxarm-$image/archlinuxarm-$image.img . + rm -rf archlinuxarm-$image archlinuxarm-$image.zip +} + +# Make a data disk + +[[ -f data_disk.raw ]] || qemu-img create -f raw data_disk.raw 5G + + diff --git a/scrapbook/CONTENTS.md b/scrapbook/CONTENTS.md new file mode 100644 index 0000000..df84fdf --- /dev/null +++ b/scrapbook/CONTENTS.md @@ -0,0 +1,24 @@ +# Raspberry Pi Scrapbook Contents + +## HowTos + +1. How to mount Raspberry Pi images + (HowTo_Mount_Image.md) + +2. How to provide entropy for pacman-key + (HowTo_Pacman_Keyring_Entropy) + +3. How to install Grub into a disk image + (source: http://www.sidebranch.com/papers/How%20To%20Install%20GRUB%20into%20a%20disk%20image.pdf) + +## Notes + +1. Notes on Formatting SD cards. A collection of links to some online information. + (Notes_Formatting_SD.md) + +## Scripts + +1. build script for making images. From [here](http://www.raspberrypi.org/phpBB3/viewtopic.php?p=129097#p129097). + (build) + +2. mkpartitions script contains basic commands to partition the sd card (nothing clever - just the basics). diff --git a/scrapbook/HowTo_Install_GRUB_into_a_disk_image.pdf b/scrapbook/HowTo_Install_GRUB_into_a_disk_image.pdf Binary files differnew file mode 100644 index 0000000..b064d3b --- /dev/null +++ b/scrapbook/HowTo_Install_GRUB_into_a_disk_image.pdf diff --git a/scrapbook/HowTo_Mount_Image.md b/scrapbook/HowTo_Mount_Image.md new file mode 100644 index 0000000..291af78 --- /dev/null +++ b/scrapbook/HowTo_Mount_Image.md @@ -0,0 +1,49 @@ +# Mounting Raspberry Pi Images + +The official image files are at [here] [1]. To mount these on a +filesystem you can use these tricks. + +(first, extract the .img from the downloaded .zip) + +## Gather required information + +The image is a disk image (i.e. it contains a partition table and partitions). +We need to know the partition offsets within the image so that we can mount the filesystems. + + $ parted archlinuxarm-01-03-2012.img + WARNING: You are not superuser. Watch out for permissions. + GNU Parted 3.1 + Using .../archlinuxarm-01-03-2012.img + Welcome to GNU Parted! Type 'help' to view a list of commands. + (parted) unit + Unit? [compact]? B + (parted) print + Model: (file) + Disk .../archlinuxarm-01-03-2012.img: 1977614336B + Sector size (logical/physical): 512B/512B + Partition Table: msdos + Disk Flags: + + Number Start End Size Type File system Flags + 1 512B 100000255B 99999744B primary fat16 lba + 2 100000256B 1977614335B 1877614080B primary ext3 + + (parted) q + +## Mount the first partition + + sudo mount -o loop,offset=512 archlinuxarm-01-03-2012.img /mnt + +## Mount the second partition + + sudo mount -o loop,offset=100000256 archlinuxarm-01-03-2012.img /mnt + +## Acknowledgement + +This is derived from a note written by [Andre Miller] [2] that has some further +information and discussion. + + [1]: http://www.raspberrypi.org/downloads + + [2]: http://www.andremiller.net/content/mounting-hard-disk-image-including-partitions-using-linux + diff --git a/scrapbook/HowTo_Pacman_Keyring_Entropy.md b/scrapbook/HowTo_Pacman_Keyring_Entropy.md new file mode 100644 index 0000000..f9b3af5 --- /dev/null +++ b/scrapbook/HowTo_Pacman_Keyring_Entropy.md @@ -0,0 +1,15 @@ +# Pacman Keyring Entropy + +Setting up the Pacman keyring requires "entropy" (randomness) in order to compute its keys. + +This is one way to quickly provide this entropy on a new system that has not been running +long enough to do this on its own. (Such a system could otherwise take hours to complete +"pacman-key --init") + + $ pacman -S haveged + $ haveged -w 1024 + $ pacman-key --init + $ pkill haveged + $ pacman -Rs haveged + + diff --git a/scrapbook/Notes_Formatting_SD.md b/scrapbook/Notes_Formatting_SD.md new file mode 100644 index 0000000..322c1d9 --- /dev/null +++ b/scrapbook/Notes_Formatting_SD.md @@ -0,0 +1,16 @@ +# Notes : Formatting SD Card + +# Found on the internet + +http://pastebin.com/u9Qpm5n0 +http://elinux.org/RPi_Tasks +http://en.wikipedia.org/wiki/Master_boot_record +http://libguestfs.org/virt-make-fs.1.html + +http://www.raspberrypi.org/phpBB3/viewtopic.php?p=118519 + +(mkcard.sh:) +http://www.raspberrypi.org/phpBB3/viewtopic.php?f=24&t=1079&p=8433&hilit=mbr#p8433 + + + diff --git a/scrapbook/build b/scrapbook/build new file mode 100755 index 0000000..c7dac7e --- /dev/null +++ b/scrapbook/build @@ -0,0 +1,53 @@ +#!/bin/bash +# +# Arch Linux ARM Image Builder +# +# Licensed under the GPLv2. +# +# This script builds an Arch Linux ARM distribution/image. +# First, it downloads and installs packages to the workingdir, +# then configures some basics, sets the root password to "root", +# and then creates a rootts.tar.gz and/or a UBI image, ready to flash. +# +# Usage: ./distro-builder workingdir +# +# NOTE: This script is interactive. +# Agree to installing packages and answer "y" to cleaning the Pacman database. +# +# ==== Variables to set ==== +INSTALLEDPKGS="base kernel26 kernel26-headers file ntfs-3g openssh openssl" +RELEASEVER=2011.06 +MAKETARGZ=1 +# ==== The Process ==== +mkdir -p $1 +echo -e "\033[1mInstalling packages...\033[0m" +mkdir -p $1/var/lib/pacman +pacman -Syyf --noconfirm --noprogressbar -r $1 $INSTALLEDPKGS + +echo -e "\033[1mSetting the password to 'root' and cleaning up:\033[0m" +echo -e "root\nroot\n" | chroot $1/ /usr/bin/passwd root +rm $1/dev/{console,null,zero} +chroot $1/ mknod -m 600 /dev/console c 5 1 +chroot $1/ mknod -m 666 /dev/null c 1 3 +chroot $1/ mknod -m 666 /dev/zero c 1 5 +rm $1/etc/locale.gen +echo "en_US.UTF-8 UTF-8" >> $1/etc/locale.gen +echo "en_US ISO-8859-1" >> $1/etc/locale.gen +echo "de_DE ISO-8859-1" >> $1/etc/locale.gen +echo "de_DE@euro ISO-8859-15" >> $1/etc/locale.gen +chroot $1/ /usr/sbin/locale-gen +chroot $1/ yes | /usr/bin/pacman -Scc +echo $RELEASEVER > $1/etc/alarm-version + +# Here is the rootfs.tar.gz part if you set MAKETARGZ to 1 +if [ $MAKETARGZ = 1 ]; then + echo -e "\033[1mCreating a rootfs.tar.gz...\033[0m" + cd $1 + tar czf ../PlugApps-Linux-$RELEASEVER-rootfs.tar.gz ./* + cd ../ +else + echo -e "\033[1mNot creating a rootfs.tar.gz...\033[0m" +fi + +echo -e "\033[1mCleaning up...\033[0m" +rm -rf $1 diff --git a/scrapbook/mkpartitions b/scrapbook/mkpartitions new file mode 100755 index 0000000..cd7df9d --- /dev/null +++ b/scrapbook/mkpartitions @@ -0,0 +1,7 @@ +#!/bin/bash +parted -s /dev/mmcblk0 mklabel msdos +parted -s /dev/mmcblk0 unit cyl mkpart primary fat32 -- 0 16 +parted -s /dev/mmcblk0 set 1 boot on +parted -s /dev/mmcblk0 unit cyl mkpart primary ext2 -- 16 -2 +mkfs.vfat /dev/mmcblk0p1 +mkfs.ext4 /dev/mmcblk0p2 |