Browse Source

OVA image creation is now fully integrated into build process

There are no complex external dependencies for OVA creation
anymore. An OVF file is directly maintained, and raw disks
are converted to streamOptimized VMDK using VBoxManage.

Added single loop device support to the chroot environment.

Separated boot/iso/ova phases into independent helper scripts,
invoked from "mkimage".

Removed unnecessary LC_ALL=C assignments at build-time.

Removed git snapshot creation script.

Clarified dependencies in Syslinux/GRUB configuration file
comments.
Maxim Kammerer 11 năm trước cách đây
mục cha
commit
0adb4bacf7

+ 2 - 0
doc/changelog.txt

@@ -25,6 +25,8 @@
   * Removed Audacious due to plugin location bugs
   * Replaced XChat with HexChat
 
+  * OVA image creation is fully integrated into build process
+
 
 2012-09-01
   + 2012.3 release

+ 14 - 10
enter

@@ -112,17 +112,23 @@ sinfo "Mounting system directories"
 
 [ "${tty#/dev/pts/}" = "${tty}" ] || tty=
 [ -L ${LIVECD}/dev/fd ] || ln -sfT /proc/self/fd ${LIVECD}/dev/fd
+loop=`losetup -f`
 
-for mp in /proc /dev/null /dev/random /dev/urandom /dev/tty /dev/ptmx /dev/pts ${tty}; do
-    if [ ! -e ${LIVECD}${mp} ]; then
+for mp in /proc /dev/null /dev/random /dev/urandom /dev/tty /dev/ptmx /dev/pts ${loop} ${tty}; do
+    if [ ${mp#/dev/loop} = ${mp} ]; then
+        lmp=${LIVECD}${mp}
+    else
+        lmp=${LIVECD}/dev/loop
+    fi
+    if [ ! -e ${lmp} ]; then
         if   [ -d ${mp} ]; then
-            mkdir -m 755 ${LIVECD}${mp}
+            mkdir -m 755 ${lmp}
         elif [ -e ${mp} ]; then
-            touch ${LIVECD}${mp}
+            touch ${lmp}
         fi
     fi
-    mount -B ${mp} ${LIVECD}${mp}
-    mounted="${LIVECD}${mp} ${mounted}"
+    mount -B ${mp} ${lmp}
+    mounted="${lmp} ${mounted}"
 done
 mount -rB -o remount ${LIVECD}/proc
 
@@ -160,10 +166,8 @@ fi
 
 umount -l ${mounted}
 
-# Condition is false for empty ${tty} and for block-device ${tty} (i.e., unmount failed)
-if [ -f ${LIVECD}${tty} ]; then
-    rm ${LIVECD}${tty}
-fi
+# Condition is false for empty and for block-device ${tty} (i.e., unmount failed)
+[ ! -f ${LIVECD}${tty} ] || rm ${LIVECD}${tty}
 
 
 exit ${retval}

+ 0 - 28
mkdist

@@ -1,28 +0,0 @@
-#!/bin/sh -e
-
-sinfo() {
-    echo ${BASH:+-e} "\033[1;33;41m$@\033[0m"
-}
-
-
-# Must have root directory as an argument
-if [ -z "$1" ]; then
-    echo "$0 <livecd root>"
-    exit 1
-fi
-
-
-# Variables
-SRC=`dirname $0`
-DIST=$1/dist
-
-version=`cat ${SRC}/conf/version`
-distname=liberte-${version}
-
-
-sinfo "Creating source distribution ${distname}-src.tar.bz2"
-(cd ${SRC}; git -c tar.umask=022 archive --format=tar --prefix=${distname}/ master) \
-    | bzip2 > ${DIST}/${distname}-src.tar.bz2
-
-
-sinfo "Done."

+ 0 - 3
mkroot

@@ -1,8 +1,5 @@
 #!/bin/sh -e
 
-export LC_ALL=C
-
-
 sinfo() {
     echo ${BASH:+-e} "\033[1;33;41m$@\033[0m"
 }

+ 0 - 250
mkvmdist

@@ -1,250 +0,0 @@
-#!/bin/sh -e
-
-# Requirements: parted, e2fsprogs, librsvg[tools]
-#               open-ovf, ovftool, vmware-{vdiskmanager,mount}
-#
-# http://dmtf.org/standards/vman
-# http://gitorious.org/open-ovf
-# http://blogs.vmware.com/vapp/2009/11/virtual-hardware-in-ovf-part-1.html
-
-sinfo() {
-    echo ${BASH:+-e} "\033[1;33;41m$@\033[0m"
-}
-
-
-# Must have root directory as an argument
-if [ -z "$1" ]; then
-    echo "$0 <livecd root>"
-    exit 1
-fi
-
-
-# Origin paths
-src=`dirname $0`
-distroot=$1/dist
-cdroot=${distroot}/cdroot
-vmstage=${distroot}/vmstage
-
-# Versioning and naming
-version=`cat ${src}/conf/version`
-distname=liberte-${version}
-
-# Derived paths
-logosvg=${src}/src/home/anon/config/images/liberte-logo-nofont.svg
-efiboot=${cdroot}/boot/efiboot.img
-syslinux=${cdroot}/liberte/boot/syslinux/syslinux-x86.tbz
-
-ovfpath=${vmstage}/${distname}.ovf
-diskpath=${vmstage}/${distname}.vmdk
-logopath=${vmstage}/${distname}.png
-ovapath=${distroot}/${distname}.ova
-
-# Descriptions
-volume="Liberté Linux"
-pname="Liberte Linux"
-purl="http://dee.su/liberte"
-pdesc="${pname}: Mission-critical stealth communication."
-pclass=su.dee.liberte
-efilabel=LIBERTE_EFI
-
-# VM parameters
-ramsize=256
-disksize=512
-diskformat="http://www.vmware.com/interfaces/specifications/vmdk.html#sparse"
-nettype=NAT
-logowidth=128
-efiextrablocks=32
-
-# Internal names
-vhwname=hw0
-diskid=disk0
-netid=net0
-iconid=icon0
-
-# Common mkovf parameters
-param="-f ${ovfpath} --encoding=UTF-8"
-
-
-# Safety checks
-if [ ! -e ${cdroot} ]; then
-    echo "cdroot does not exist yet"
-    exit 1
-fi
-
-
-# Prepare a staging directory
-rm -rf ${vmstage}
-mkdir  ${vmstage}
-
-
-# See also disk controller resource below
-sinfo "Initializing virtual disk"
-rm -f ${diskpath}
-vmware-vdiskmanager -c -q -a ide -t 0 -s ${disksize}MB ${diskpath}
-
-
-sinfo "Mounting virtual disk image"
-mkdir ${vmstage}/vdisk
-vmware-mount -f ${diskpath} ${vmstage}/vdisk
-
-
-sinfo "Partitioning and installing MBR"
-efiblocks=`du -s -B 4K --apparent-size ${cdroot}/EFI | cut -f1`
-efisize=$(((efiblocks + 6 + efiextrablocks) * 4))
-
-parted -s ${vmstage}/vdisk/flat                                     \
-          mklabel msdos                                             \
-          mkpart  primary fat16 4KiB $(((4 + efisize) * 1024 - 1))B \
-          mkpart  primary ext2  $((4 + efisize))KiB 100%            \
-          set     2       boot on
-sfdisk -q --change-id ${vmstage}/vdisk/flat 1 ef
-
-loop=`losetup -f`
-losetup ${loop} ${vmstage}/vdisk/flat
-
-tar -xjf ${syslinux} -C ${vmstage} mbr_c.bin
-cat ${vmstage}/mbr_c.bin > ${loop}
-
-while ! losetup -d ${loop}; do sleep 1; done
-
-
-sinfo "Creating EFI filesystem"
-losetup -o $((4 * 1024)) -s $((efisize * 1024)) ${loop} ${vmstage}/vdisk/flat
-mkdosfs -n "${efilabel}" ${loop}
-
-mkdir ${vmstage}/vpart
-mount -t vfat ${loop} ${vmstage}/vpart
-
-rsync -aHS ${cdroot}/EFI ${vmstage}/vpart
-umount -d ${vmstage}/vpart
-
-
-sinfo "Creating main filesystem"
-losetup -o $(((4 + efisize) * 1024)) ${loop} ${vmstage}/vdisk/flat
-
-mke2fs -q -m0 -T largefile -L "${volume}" -O ^resize_inode,^dir_index,sparse_super \
-       -F ${loop}
-tune2fs -c 0 -i 0 ${loop}
-
-mount -t ext2 -o noatime ${loop} ${vmstage}/vpart
-
-
-sinfo "Copying live image"
-rsync -aHS ${cdroot}/liberte ${vmstage}/vpart
-
-
-sinfo "Installing boot manager"
-${cdroot}/liberte/setup.sh ${loop}
-
-umount -d ${vmstage}/vpart
-
-
-sinfo "Unmounting virtual disk image"
-vmware-mount -d ${vmstage}/vdisk
-
-
-sinfo "Verifying virtual partitions"
-vmware-mount ${diskpath} 1 ${vmstage}/vpart
-test -e ${vmstage}/vpart/EFI/BOOT/BOOTx64.EFI
-vmware-mount -d ${vmstage}/vpart
-
-vmware-mount ${diskpath} 2 ${vmstage}/vpart
-test -e ${vmstage}/vpart/liberte/boot/syslinux/ldlinux.sys
-vmware-mount -d ${vmstage}/vpart
-
-
-sinfo "Rasterizing logo"
-rsvg-convert -a -w ${logowidth} -f png -o ${logopath} ${logosvg}
-
-
-sinfo "Creating OVF envelope"
-mkovf --init   ${param}
-mkovf --lang   ${param} -l "en-GB"
-
-
-# Reference external files
-mkovf --efile  ${param} -i ${diskid} -n `basename ${diskpath}` -c identity
-mkovf --efile  ${param} -i ${iconid} -n `basename ${logopath}` -c identity
-
-
-# Create disks section (-r references --efile -i above)
-mkovf --disk   ${param} -i ${diskid} -r ${diskid} -u "MegaBytes" \
-               -c ${disksize} -m "Virtual Disks" -F "${diskformat}"
-
-# Create networks section
-mkovf --net    ${param} -i ${netid} -e ${nettype} -m "Virtual Networks" \
-               -d "NAT Network"
-
-
-# Define a virtual system
-mkovf --vs     ${param} -i "${distname}" -m "Virtual Appliance"
-
-# Add Guest OS (100 = Linux 2.6 (64-bit) in VirtualBox, required for x64 EFI)
-mkovf --os     ${param} -d "Linux 3.x" -m "Guest Operating System" --secID=100
-
-# Add virtual hardware section (vmx-08 for vmwgfx dri)
-mkovf --virthw ${param} -p "vmx-06 vmx-08" --instanceID=1 -n ${vhwname} \
-               -m "Virtual Hardware Requirements"
-
-# Allocate CPUs
-mkovf --resource ${param} --elementName="Processors" \
-                 -i 1 -k 3 -d "Number of Virtual CPUs" -k 3 -g 1
-
-# Allocate RAM
-mkovf --resource ${param} --elementName="Memory" -u "MegaBytes" \
-                 -i 2 -k 4 -d "Memory Size" -g ${ramsize}
-
-# Allocate NIC (-n references --net -e above)
-mkovf --resource ${param} --elementName="Network Adapter" -t True \
-                 -i 3 -k 10 -d "Ethernet Adapter" -b E1000 -n ${nettype}
-
-# Allocate disk controller
-# IDE:  -k  5               (TianoCore EFI fw does not support SCSI disks)
-# SCSI: -k  6 / -b lsilogic
-# SATA: -k 20 / -b AHCI     (Not supported in VMware)
-mkovf --resource ${param} --elementName="IDE" \
-                 -i 4 -k 5 -d "IDE Controller" -a 0
-
-# Allocate disk
-mkovf --resource ${param} --elementName="Hard Disk" \
-                 -i 5 -k 17 -d "Hard Disk" -j 4 -p 0 -r ovf://disk/${diskid}
-
-# Allocate USB controller (optional; EHCI (USB 2.0) is not on by default, however)
-mkovf --resource ${param} --elementName="USB" \
-                 -i 6 -k 23 -d "USB Controller" -b vmware.usb.ehci -y
-
-# Allocate sound adapters (optional, VMware and VirtualBox subtypes)
-mkovf --resource ${param} --elementName="Sound" \
-                 -i 7 -k 35 -d "Sound Card" -b ensoniq1371 -y
-
-mkovf --resource ${param} --elementName="Sound" \
-                 -i 8 -k 1  -d "Sound Card" -b vmware.soundcard.ensoniq1371 -y
-
-
-# Create informative sections
-mkovf --annotate ${param} -m "Annotation" -a "${pdesc}"
-
-mkovf --product  ${param} -m "Product Information" -p "${pname}" -v ${version} \
-                 -r "${purl}" -c ${pclass} -n ${pclass}.1
-
-mkovf --icon     ${param} -t image/png -w ${logowidth} -n ${iconid} -s ${pclass} \
-                 --instance=${pclass}.1
-
-
-# Post-process unicode names (mkovf uses --encoding only for XML header)
-# mkovf --resource -y is an on-switch without corresponding off-switch
-sinfo "Fixing OVF envelope"
-sed -i 's/Liberte/Liberté/g ;
-        s/\<Item ovf:required="true"/Item ovf:required="false"/g' \
-    ${ovfpath}
-
-
-sinfo "Validating OVF and creating OVA bundle"
-ovftool -o -q --schemaValidate --skipManifestCheck --skipManifestGeneration \
-        ${ovfpath} ${ovapath}
-chmod --reference=${ovfpath} ${ovapath}
-
-rm -r ${vmstage}
-
-
-sinfo "Done."

+ 2 - 1
src/etc/portage/make.conf

@@ -93,6 +93,7 @@ DONT_MOUNT_BOOT=1
 # Hauppauge-Firmware          = distribution for Hauppage component products
 # bluez-firmware              = distribution by BlueZ project
 # Broadcom                    = should probably be "as-is" (#446658)
+# PUEL                        = personal license (build-time virtualbox-bin)
 ACCEPT_LICENSE="-* @FREE as-is freedist unRAR lha @BINARY-REDISTRIBUTABLE Atmel
                    SIL-freeware amd-ucode Conexant-firmware Hauppauge-Firmware
-                   bluez-firmware Broadcom"
+                   bluez-firmware Broadcom PUEL"

+ 1 - 1
src/etc/portage/package.use/all

@@ -87,7 +87,7 @@ dev-libs/libxslt                -crypt
 media-libs/libwmf               -expat
 app-text/ghostscript-gpl        -djvu -idn
 app-misc/geoclue                -*
-app-emulation/qemu              -aio -alsa -bluetooth -smartcard -curl -ncurses -seccomp -vhost-net -vnc
+app-emulation/virtualbox-bin    headless -additions -chm
 
 # Extra functionality
 # (ppp[ipv6]: #440696)

+ 3 - 0
src/etc/portage/profile/package.provided

@@ -12,3 +12,6 @@ media-fonts/font-sony-misc-0
 
 # Mostly unneeded (ghostscript-gpl)
 media-fonts/urw-fonts-2.4.9
+
+# Unneeded (app-emulation/virtualbox-bin)
+app-emulation/virtualbox-modules-4.1.26

+ 2 - 2
src/etc/portage/sets/temporary

@@ -19,8 +19,8 @@ media-fonts/terminus-font
 sys-fs/squashfs-tools
 sys-fs/mtools
 
-# OVA image creation (qemu-img)
-app-emulation/qemu
+# OVA image creation (VBoxManage)
+app-emulation/virtualbox-bin
 
 # Portage tools
 app-portage/portage-utils

+ 6 - 0
src/root/config/grub-early.cfg

@@ -1,3 +1,9 @@
+## Variables:
+## VERSION:     distribution version                       (replaced in gen-efi)
+##
+## Files:
+## grub.mf:     chained grub+manifest SHA-256 checksums     (created in gen-efi, patched in mk-boot)
+##
 echo "Liberté Linux VERSION: Early boot using GRUB ${grub_cpu}-${grub_platform}"
 set manifest=(memdisk)/boot/grub/grub.mf
 set chaingrub=/liberte/boot/grub/grub.cfg

+ 3 - 1
src/root/config/grub.cfg

@@ -1,7 +1,9 @@
 ## Variables:
 ## VERSION:     distribution version                     (replaced in gen-efi)
 ## CONSOLEFONT: PFF2 gfxterm font                        (replaced in gen-efi)
-## FSHASH:      SquashFS image hexadecimal SHA-256 hash  (replaced in mkimage)
+## FSHASH:      SquashFS image hexadecimal SHA-256 hash  (replaced in mk-boot)
+##
+## grub.mf:     kernel+font SHA-256 checksums             (created in mk-boot)
 ##
 # Regular kernel parameters:
 #     (see syslinux.cfg)

+ 188 - 0
src/root/config/liberte.ovf

@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+    This XML can be recreated using open-ovf: http://gitorious.org/open-ovf
+    Permanent mkovf parameters: -f filename.ovf -encoding=UTF-8
+    Long parameters are marked with a single hyphen due to XML format requirements.
+    'Item ovf:required="true"' should be replaced with 'Item ovf:required="false"'
+
+    Files:
+      liberte-VERSION-disk.vmdk  streamOptimized VMDK disk image
+      liberte-VERSION-icon.png   128x128 logo icon
+    Replacement strings:
+      VERSION                    distribution version
+      11111111                   disk image size in bytes
+      22222222                   icon size in bytes
+
+    Validation:
+      xmllint -schema http://schemas.dmtf.org/ovf/envelope/1/dsp8023_1.0.0.xsd -noout liberte.ovf
+
+    See also:
+      http://dmtf.org/standards/vman (DSP0243 1.0.0)
+      http://blogs.vmware.com/vapp/2009/11/virtual-hardware-in-ovf-part-1.html
+
+    mkovf -init
+    mkovf -lang -l en-GB
+-->
+<Envelope xml:lang="en-GB" ovf:version="1.0.0"
+          xmlns="http://schemas.dmtf.org/ovf/envelope/1"
+          xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"
+          xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
+          xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData">
+
+    <!-- ovf:id is referenced via ovf:fileRef below -->
+    <References>
+        <!-- mkovf -efile -i disk0 -n liberte-VERSION-disk.vmdk -c identity -->
+        <File ovf:id="disk0" ovf:href="liberte-VERSION-disk.vmdk" ovf:size="11111111" ovf:compression="identity"/>
+        <!-- mkovf -efile -i icon0 -n liberte-VERSION-icon.png  -c identity -->
+        <File ovf:id="icon0" ovf:href="liberte-VERSION-icon.png"  ovf:size="22222222" ovf:compression="identity"/>
+    </References>
+
+    <!-- ovf:diskId is referenced via rasd:HostResource below -->
+    <DiskSection ovf:required="true">
+        <Info>Virtual Disks</Info>
+
+        <!-- mkovf -disk -i disk0 -r disk0 -u "MegaBytes" -c 512 -m "Virtual Disks" -F ...vmdk.html#sparse -->
+        <Disk ovf:diskId="disk0" ovf:fileRef="disk0" ovf:capacityAllocationUnits="MegaBytes" ovf:capacity="512"
+              ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized"/>
+    </DiskSection>
+
+    <NetworkSection>
+        <Info>Virtual Networks</Info>
+
+        <!-- mkovf -net -i net0 -e NAT -m "Virtual Networks" -d "NAT Network" -->
+        <!-- ovf:name is referenced via rasd:Connection below -->
+        <Network ovf:id="net0" ovf:name="NAT">
+            <Description>NAT Network</Description>
+        </Network>
+    </NetworkSection>
+
+    <!-- mkovf -vs -i liberte-VERSION -m "Virtual Appliance" -->
+    <!-- vssd/rasd entries below must be sorted (xs:sequence) -->
+    <VirtualSystem ovf:id="liberte-VERSION">
+        <Info>Virtual Appliance</Info>
+
+        <!-- mkovf -os -secID=100 -m "Guest Operating System" -d "Linux 3.x" -->
+        <!-- secId=100 = Linux 2.6 (64-bit) in VirtualBox, required for x64 EFI -->
+        <OperatingSystemSection ovf:id="100">
+            <Info>Guest Operating System</Info>
+            <Description>Linux 3.x</Description>
+        </OperatingSystemSection>
+
+        <VirtualHardwareSection>
+            <Info>Virtual Hardware Requirements</Info>
+
+            <!-- mkovf -virthw -instanceID=1 -n hw0 -p "vmx-06 vmx-08" -m "Virtual Hardware Requirements" -->
+            <!-- vmx-06: VMDK v6 disk image, vmx-08: vmwgfx DRI -->
+            <System>
+                <vssd:ElementName>hw0</vssd:ElementName>
+                <vssd:InstanceID>1</vssd:InstanceID>
+                <vssd:VirtualSystemType>vmx-06 vmx-08 virtualbox-2.2</vssd:VirtualSystemType>
+            </System>
+
+            <!-- mkovf -resource -elementName=Processors -i 1 -k 3 -d "Number of Virtual CPUs" -g 1 -->
+            <Item>
+                <rasd:Description>Number of Virtual CPUs</rasd:Description>
+                <rasd:ElementName>Processors</rasd:ElementName>
+                <rasd:InstanceID>1</rasd:InstanceID>
+                <rasd:ResourceType>3</rasd:ResourceType>
+                <rasd:VirtualQuantity>1</rasd:VirtualQuantity>
+            </Item>
+
+            <!-- mkovf -resource -elementName=Memory -u MegaBytes -i 2 -k 4 -d "Memory Size" -g 256 -->
+            <Item>
+                <rasd:AllocationUnits>MegaBytes</rasd:AllocationUnits>
+                <rasd:Description>Memory Size</rasd:Description>
+                <rasd:ElementName>Memory</rasd:ElementName>
+                <rasd:InstanceID>2</rasd:InstanceID>
+                <rasd:ResourceType>4</rasd:ResourceType>
+                <rasd:VirtualQuantity>256</rasd:VirtualQuantity>
+            </Item>
+
+            <!-- mkovf -resource -elementName="Network Adapter" -t True -i 3 -k 10 -d "Ethernet Adapter" -b E1000 -n NAT -->
+            <Item>
+                <rasd:AutomaticAllocation>true</rasd:AutomaticAllocation>
+                <rasd:Connection>NAT</rasd:Connection>
+                <rasd:Description>Ethernet Adapter</rasd:Description>
+                <rasd:ElementName>Network Adapter</rasd:ElementName>
+                <rasd:InstanceID>3</rasd:InstanceID>
+                <rasd:ResourceSubType>E1000</rasd:ResourceSubType>
+                <rasd:ResourceType>10</rasd:ResourceType>
+            </Item>
+
+            <!-- mkovf -resource -elementName=IDE -i 4 -k 5 -d "IDE Controller" -a 0 -->
+            <!--
+                IDE:  -k  5               (TianoCore EFI fw does not support SCSI disks)
+                SCSI: -k  6 / -b lsilogic
+                SATA: -k 20 / -b AHCI     (Not supported in VMware)
+            -->
+            <Item>
+                <rasd:Address>0</rasd:Address>
+                <rasd:Description>IDE Controller</rasd:Description>
+                <rasd:ElementName>IDE</rasd:ElementName>
+                <rasd:InstanceID>4</rasd:InstanceID>
+                <rasd:ResourceType>5</rasd:ResourceType>
+            </Item>
+
+            <!-- mkovf -resource -elementName="Hard Disk" -i 5 -k 17 -d Hard Disk -j 4 -p 0 -r ovf://disk/disk0 -->
+            <Item>
+                <rasd:AddressOnParent>0</rasd:AddressOnParent>
+                <rasd:Description>Hard Disk</rasd:Description>
+                <rasd:ElementName>Hard Disk</rasd:ElementName>
+                <rasd:HostResource>ovf://disk/disk0</rasd:HostResource>
+                <rasd:InstanceID>5</rasd:InstanceID>
+                <rasd:Parent>4</rasd:Parent>
+                <rasd:ResourceType>17</rasd:ResourceType>
+            </Item>
+
+            <!-- mkovf -resource -elementName=USB -i 6 -k 23 -d "USB Controller" -b vmware.usb.ehci -y (false) -->
+            <!-- optional; EHCI (USB 2.0) is not on by default, however -->
+            <Item ovf:required="false">
+                <rasd:Description>USB Controller</rasd:Description>
+                <rasd:ElementName>USB</rasd:ElementName>
+                <rasd:InstanceID>6</rasd:InstanceID>
+                <rasd:ResourceSubType>vmware.usb.ehci</rasd:ResourceSubType>
+                <rasd:ResourceType>23</rasd:ResourceType>
+            </Item>
+
+            <!-- mkovf -resource -elementName=Sound -i 7 -k 35 -d "Sound Card" -b ensoniq1371 -y (false) -->
+            <!-- optional; VirtualBox subtype -->
+            <Item ovf:required="false">
+                <rasd:Description>Sound Card</rasd:Description>
+                <rasd:ElementName>Sound</rasd:ElementName>
+                <rasd:InstanceID>7</rasd:InstanceID>
+                <rasd:ResourceSubType>ensoniq1371</rasd:ResourceSubType>
+                <rasd:ResourceType>35</rasd:ResourceType>
+            </Item>
+
+            <!-- mkovf -resource -elementName=Sound -i 8 -k 1 -d "Sound Card" -b vmware.soundcard.ensoniq1371 -y (false) -->
+            <!-- optional; VMware subtype -->
+            <Item ovf:required="false">
+                <rasd:Description>Sound Card</rasd:Description>
+                <rasd:ElementName>Sound</rasd:ElementName>
+                <rasd:InstanceID>8</rasd:InstanceID>
+                <rasd:ResourceSubType>vmware.soundcard.ensoniq1371</rasd:ResourceSubType>
+                <rasd:ResourceType>1</rasd:ResourceType>
+            </Item>
+        </VirtualHardwareSection>
+
+        <!-- mkovf -annotate -m Annotation -a "..." -->
+        <AnnotationSection>
+            <Info>Annotation</Info>
+
+            <Annotation>Liberté Linux: Mission-critical stealth communication.</Annotation>
+        </AnnotationSection>
+
+        <!-- mkovf -product -m "Product Information" -p "Liberté Linux" -v VERSION -r http://dee.su/liberte -c su.dee.liberte -n su.dee.liberte.1 -->
+        <ProductSection ovf:class="su.dee.liberte" ovf:instance="su.dee.liberte.1">
+            <Info>Product Information</Info>
+
+            <Product>Liberté Linux</Product>
+            <Version>VERSION</Version>
+            <ProductUrl>http://dee.su/liberte</ProductUrl>
+
+            <!-- mkovf -icon -t image/png -w 128 -n icon0 -s su.dee.liberte -instance=su.dee.liberte.1 -->
+            <Icon ovf:mimeType="image/png" ovf:width="128" ovf:fileRef="icon0"/>
+        </ProductSection>
+    </VirtualSystem>
+</Envelope>

+ 4 - 2
src/root/config/syslinux.cfg

@@ -1,7 +1,9 @@
 ## Variables
 ## VERSION:     distribution version                     (replaced in gen-syslinux)
 ## CONSOLEFONT: psf(u) console font                      (replaced in gen-syslinux)
-## FSHASH:      SquashFS image hexadecimal SHA-256 hash  (replaced in mkimage)
+## FSHASH:      SquashFS image hexadecimal SHA-256 hash  (replaced in mk-boot)
+##
+## Encoding:    CP437                                  (translated in gen-syslinux)
 ##
 # Liberté-specific kernel parameters (all are optional):
 #     cdroot_type={auto,vfat,ext4,iso9660,hfsplus,squashfs} - boot media filesystem type
@@ -28,7 +30,7 @@
 #     gentoo=nontp       - disable NTP time synchronization (use with tz=...)
 #
 #     bridges=...        - comma-separated list of Tor bridges: IP[:port(=443)]
-#     gentoo=obfs        - enable obfsproxy transport for bridges
+#     gentoo=obfs        - enable obfsproxy (obfs2) transport for bridges
 #
 # "gentoo=" prefix is optional, and can combine several comma-separated parameters
 #

+ 2 - 1
src/root/dist/qemulate.sh

@@ -1,4 +1,5 @@
-#!/bin/sh -e
+#!/bin/sh
+set -e
 
 # TODO: add "-device virtio-rng" once it is supported by QEMU
 

+ 1 - 1
src/root/helpers/chk-live-tree

@@ -69,7 +69,7 @@ find . \( -name '*~*' -o -name '*-' -o -name '*#*' -o -name '*.bak' \
         ! -name 'routerInfo-*.dat'
 
 sinfo "Logs:"
-find . -name '*.log*' -o -type f \( -path './var/run/*' -o -path './var/log/*' \)
+find . -name '*.log*' -o -type f \( -path './run/*' -o -path './var/log/*' \)
 
 
 sinfo "SUID / SGID / capabilities / xattrs / ACLs:"

+ 7 - 3
src/root/helpers/gen-efi

@@ -58,20 +58,24 @@ memdisk() {
     mods=`echo "${mods}" | sed "s:.*:${libdir}/${arch}/&.mod:"`
     cp -p ${mods} ${moddir}
 
-    sed "s@VERSION@${LVERSION}@" ${templearlycfg} \
+    cat ${templearlycfg}               \
+        | sed "/^##/d ;                \
+               s@VERSION@${LVERSION}@" \
         > ${memroot}/grub.cfg
 
     # Compress all files (*.mod, *.lst, grub.cfg)
     xz -C crc32 --lzma2=dict=1MiB `find ${memroot} -type f`
     rename .xz ""                 `find ${memroot} -type f`
 
-    # Add bogus manifest (to be patched in mkimage)
+    # Add bogus manifest (to be patched in mk-boot)
     echo "replace_hash__________________________________________________01  /liberte${grubcfg}"        > ${memroot}/grub.mf
     echo "replace_hash__________________________________________________02  /liberte${grubcfg%.*}.mf" >> ${memroot}/grub.mf
 
     tar -cf ${build}/memdisk.tar -C ${build} boot
 
     # NOTE: -C has no effect (Savannah: #36770)
+    # grub2-mkstandalone -C xz -O ${arch} -o ${out} --compress=xz --install-modules="${modules}"
+    #                    --themes=none --fonts=none --locales=none (Savannah: #36772)
     grub2-mkimage -C xz -O ${arch} -m ${build}/memdisk.tar \
                   -o ${out} memdisk tar xzio gcry_crc
     rm -r ${build}
@@ -92,7 +96,7 @@ cp -p /usr/share/grub/${consolefont} ${grubroot}
 
 # Substitute and copy template
 cat ${templcfg}                           \
-    | sed "/^##/d ;
+    | sed "/^##/d ;                       \
            s@VERSION@${LVERSION}@ ;       \
            s@CONSOLEFONT@${consolefont}@" \
     > ${grubcfg}

+ 2 - 2
src/root/helpers/gen-syslinux

@@ -40,8 +40,8 @@ gunzip ${sysroot}/${consolefont}.gz
 
 # Substitute and copy template
 cat ${templcfg}                           \
-    | sed "/^##/d ;
-           s@VERSION@${LVERSION}@ ;
+    | sed "/^##/d ;                       \
+           s@VERSION@${LVERSION}@ ;       \
            s@CONSOLEFONT@${consolefont}@" \
     | iconv -f UTF-8 -t ${encoding}       \
     > ${syscfg}

+ 54 - 0
src/root/helpers/mk-boot

@@ -0,0 +1,54 @@
+#!/bin/sh -e
+
+# Variables
+cdroot=/mnt/boot/cdroot
+live=/mnt/live
+
+ziimage=${cdroot}/liberte/boot/kernel-x86.zi
+sqimage=${cdroot}/liberte/boot/root-x86.sfs
+
+efisbpfx=/usr/local/addons/secureboot/Liberte-SecureBoot
+
+sysver=`syslinux -v 2>&1 | cut -d' ' -f2`
+
+
+echo "Initializing /liberte"
+
+rsync -aHS ${HOME}/dist/                        ${cdroot}/liberte
+rsync -aHS ${live}/boot     --exclude /boot/EFI ${cdroot}/liberte
+rsync -aHS ${live}/boot/EFI                     ${cdroot}
+
+sed -i "s/SYSVER/${sysver}/"                    ${cdroot}/liberte/setup.sh
+
+find ${cdroot}/liberte \( -name '*.txt' -o -name '*.bat' -o -name '*.cfg' \) \
+    -exec sed -i 's/$/\r/' {} \;
+
+
+echo "Adapting Syslinux and GRUB configuration"
+
+fshash=`sha256sum ${sqimage}`
+sed -i "s/FSHASH/${fshash%% *}/"                  \
+    ${cdroot}/liberte/boot/syslinux/syslinux.cfg  \
+    ${cdroot}/liberte/boot/grub/grub.cfg          \
+    ${cdroot}/liberte/qemulate.sh
+
+sha256sum ${cdroot}/liberte/boot/grub/* ${ziimage}  \
+    | sed "/\<grub\.\(cfg\|mf\)\>/d; s:${cdroot}::" \
+    > ${cdroot}/liberte/boot/grub/grub.mf
+
+grub1hash=`sha256sum ${cdroot}/liberte/boot/grub/grub.cfg`
+grub2hash=`sha256sum ${cdroot}/liberte/boot/grub/grub.mf`
+sed -i "s/replace_hash_\{50\}01/${grub1hash%% *}/ ; \
+        s/replace_hash_\{50\}02/${grub2hash%% *}/"  \
+    ${cdroot}/EFI/BOOT/*.EFI
+
+
+echo "Signing EFI GRUB images"
+
+cp -p ${efisbpfx}-CA.der ${cdroot}/EFI/
+for efiimg in ${cdroot}/EFI/BOOT/*.EFI; do
+    sbsign   --cert ${efisbpfx}-Cert-1.crt --key ${efisbpfx}-Cert-1.key \
+             --output ${efiimg}.signed ${efiimg}
+    sbverify --cert ${efisbpfx}-CA.crt ${efiimg}.signed
+    mv ${efiimg}.signed ${efiimg}
+done

+ 47 - 0
src/root/helpers/mk-iso

@@ -0,0 +1,47 @@
+#!/bin/sh -e
+
+# Variables
+cdroot=/mnt/boot/cdroot
+imagepfx=/mnt/boot/liberte-${LVERSION}
+
+efilabel=LIBERTE_EFI
+efiboot=${cdroot}/boot/efiboot.img
+
+
+rm -rf ${cdroot}/boot
+mkdir  ${cdroot}/boot ${cdroot}/boot/syslinux
+
+
+# Add two extra 4K blocks (may need adjustment)
+echo "Creating EFI boot image for El-Torito"
+
+efiblocks=`du -s -B 4K --apparent-size ${cdroot}/EFI | cut -f1`
+truncate -s $(((efiblocks + 2) * 4))K ${efiboot}
+
+mkdosfs -n "${efilabel}" -I -f 1 -r 16 -R 1 ${efiboot} 1>/dev/null
+MTOOLS_SKIP_CHECK=1 mcopy -i ${efiboot} -smQ ${cdroot}/EFI ::
+
+
+# Hide root directories on Windows, and reset volume information
+# Allow '-' in filenames, since ISOLINUX doesn't support RockRidge/Joliet
+# (translation equivalent to mount's map=normal is still performed)
+echo "Creating ISO image ${imagepfx##*/}.iso"
+
+cp -p ${cdroot}/liberte/boot/syslinux/syslinux.cfg \
+      ${cdroot}/boot/syslinux/syslinux.cfg
+
+set -- -quiet -iso-level 2 -relaxed-filenames -R -no-pad \
+       -sysid '' -V '' -A '' errctl="ABORT|ALL *"        \
+       -no-emul-boot -boot-load-size 4 -boot-info-table  \
+       -c boot/eltorito.cat                              \
+       -b liberte/boot/syslinux/isolinux.bin             \
+       -eltorito-alt-boot -no-emul-boot                  \
+       -eltorito-platform efi -b boot/efiboot.img        \
+       -hidden boot -hidden liberte -m EFI
+mkisofs "$@" -o ${imagepfx}.iso ${cdroot}
+isovfy -i ${imagepfx}.iso 1>/dev/null
+
+
+echo "Creating ISO image ${imagepfx##*/}-bootstrap.iso"
+mkisofs "$@" -m "*.sfs" -o ${imagepfx}-bootstrap.iso ${cdroot}
+isovfy -i ${imagepfx}-bootstrap.iso 1>/dev/null

+ 141 - 0
src/root/helpers/mk-ova

@@ -0,0 +1,141 @@
+#!/bin/sh -e
+
+# Variables
+noroot="sudo -n -u nobody"
+
+cdroot=/mnt/boot/cdroot
+vmstage=/mnt/boot/vmstage
+imagepfx=/mnt/boot/liberte-${LVERSION}
+
+logosvg=/home/anon/config/images/liberte-logo-nofont.svg
+
+ovftemplate=${HOME}/config/liberte.ovf
+ovfpfx=${vmstage}/liberte-${LVERSION}
+ovfschema=http://schemas.dmtf.org/ovf/envelope/1/dsp8023_1.0.0.xsd
+
+ovfpath=${ovfpfx}.ovf
+mfpath=${ovfpfx}.mf
+diskpath=${ovfpfx}-disk.vmdk  # matches ovf:href[ovf:id="disk0"] in OVF
+logopath=${ovfpfx}-icon.png   # matches ovf:href[ovf:id="icon0"] in OVF
+
+disksize=512                  # matches ovf:capacity in OVF (MiB)
+logowidth=128                 # matches ovf:width    in OVF
+
+volume="Liberté Linux"
+efilabel=LIBERTE_EFI
+efiextrablocks=32             # extra settings space on EFI partition (KiB)
+
+sysmbr=/usr/share/syslinux/mbr_c.bin
+sysdir=/liberte/boot/syslinux
+
+
+# Prepare a staging directory
+rm -rf ${vmstage}
+mkdir  ${vmstage}
+
+
+# Initialize raw virtual disk
+truncate -s ${disksize}M ${diskpath}.flat
+
+
+echo "Partitioning raw disk image and writing EFI partition"
+efiblocks=`du -s -B 4K --apparent-size ${cdroot}/EFI | cut -f1`
+efisize=$(((efiblocks + 6 + efiextrablocks) * 4))
+
+sfdisk -qL --no-reread -u B ${diskpath}.flat 1>/dev/null 2>&1 <<EOF
+4,${efisize},ef
+$((4 + efisize)),+,L,*
+EOF
+
+truncate -s ${efisize}K ${diskpath}.flat.efi
+mkdosfs -n "${efilabel}" -I ${diskpath}.flat.efi 1>/dev/null
+MTOOLS_SKIP_CHECK=1 mcopy -i ${diskpath}.flat.efi -smQ ${cdroot}/EFI ::
+
+dd bs=440 count=1 iflag=fullblock conv=notrunc if=${sysmbr} of=${diskpath}.flat 2>/dev/null
+dd if=${diskpath}.flat.efi of=${diskpath}.flat bs=4K seek=1 conv=notrunc        2>/dev/null
+
+
+echo "Installing EXTLINUX and writing main partition"
+mainsize=$((disksize * 1024 - 4 - efisize))
+
+truncate -s ${mainsize}K ${diskpath}.flat.main
+mke2fs -q -m0 -T largefile -L "${volume}" -O ^resize_inode,^dir_index,sparse_super \
+       -F ${diskpath}.flat.main
+tune2fs -c 0 -i 0 ${diskpath}.flat.main 1>/dev/null
+
+mkdir ${diskpath}.flat.main.mnt
+mount -t ext2 -o loop=/dev/loop,noatime ${diskpath}.flat.main ${diskpath}.flat.main.mnt
+rsync -aHS ${cdroot}/liberte ${diskpath}.flat.main.mnt
+
+extlinux -i ${diskpath}.flat.main.mnt${sysdir} 2>/dev/null
+umount -d ${diskpath}.flat.main.mnt
+
+dd if=${diskpath}.flat.main of=${diskpath}.flat bs=4K seek=$((1 + efisize/4)) conv=notrunc 2>/dev/null
+
+
+echo "Verifying raw VMDK disk structure"
+ptdesc=`sfdisk -d ${diskpath}.flat | sed -n '/0, Id= 0$/d; s/^.*, size= *//p' | tr '\n' :`
+ptexp="$((efisize * 2)), Id=ef:$((mainsize * 2)), Id=83, bootable:"
+disktotal=`du -b ${diskpath}.flat | cut -f1`
+
+if [ "${ptdesc}" != "${ptexp}" -o ${disktotal} != $((disksize * 1024 * 1024)) ]; then
+    echo "Raw VMDK disk structure verification failed"
+    exit 1
+fi
+
+rm ${diskpath}.flat.efi ${diskpath}.flat.main
+
+
+echo "Converting raw disk to streamOptimized VMDK format"
+mkdir ${diskpath}.sandbox
+chown nobody:nobody ${diskpath}.sandbox
+
+chmod 755 ${VBOX_APP_HOME}/VBoxManage
+${noroot} HOME=${diskpath}.sandbox ${VBOX_APP_HOME}/VBoxManage convertfromraw \
+          ${diskpath}.flat ${diskpath}.sandbox/${diskpath##*/} --format VMDK --variant Stream 2>/dev/null
+
+chmod -R go=u-w ${diskpath}.sandbox
+mv ${diskpath}.sandbox/${diskpath##*/} ${diskpath}
+chown -h root:root ${diskpath}
+
+rm ${diskpath}.flat
+
+
+# Rasterize logo
+rsvg-convert -a -w ${logowidth} -f png -o ${logopath} ${logosvg}
+
+
+echo "Creating OVF envelope and OVA bundle"
+diskbytes=`du -b ${diskpath} | cut -f1`
+logobytes=`du -b ${logopath} | cut -f1`
+
+sed "s/VERSION/${LVERSION}/g;  \
+     s/11111111/${diskbytes}/; \
+     s/22222222/${logobytes}/" \
+    ${ovftemplate} > ${ovfpath}
+
+
+# Validate OVF (slow + fetches schemas)
+# xmllint --schema ${ovfschema} --noout ${ovfpath}
+
+
+# Create manifest
+# (useful since USTAR has no file checksums)
+# NOTE: VirtualBox chokes on icon in .mf, so no ${logopath} below
+#       (contrary to DSP0243, especially v2.0)
+openssl sha1 ${ovfpath} ${diskpath} \
+    | sed "s:${vmstage}/::" > ${mfpath}
+
+
+# Create OVA bundle
+# (order: ovf + mf/cert + disk/logo (order=<References>))
+tar -c --format=ustar -f ${imagepfx}.ova \
+    -C ${vmstage}           \
+    ${ovfpath#${vmstage}/}  \
+    ${mfpath#${vmstage}/}   \
+    ${diskpath#${vmstage}/} \
+    ${logopath#${vmstage}/}
+
+
+# Remove staging directory
+rm -r ${vmstage}

+ 9 - 88
src/root/mkimage

@@ -1,8 +1,5 @@
 #!/bin/sh -e
 
-export LC_ALL=C
-
-
 sinfo() {
     echo ${BASH:+-e} "\033[1;33;41m$@\033[0m"
 }
@@ -17,16 +14,9 @@ rootfspfx=${HOME}/config/rootfs
 cdroot=/mnt/boot/cdroot
 imagepfx=/mnt/boot/liberte-${LVERSION}
 
-efilabel=LIBERTE_EFI
-efiboot=${cdroot}/boot/efiboot.img
-efisbpfx=/usr/local/addons/secureboot/Liberte-SecureBoot
-
-ziimage=${cdroot}/liberte/boot/kernel-x86.zi
 sqimage=${cdroot}/liberte/boot/root-x86.sfs
 sqsort=${live}/tmp/transient/pkg/squashfs.sort
 
-sysver=`syslinux -v 2>&1 | cut -d' ' -f2`
-
 
 mibsize() {
     local bytes=`stat -c %s "$1"`
@@ -70,28 +60,13 @@ if [ -e ${cdroot}/liberte/boot/packages.lst ]; then
 fi
 
 
-sinfo "Copying image add-ons"
-rm -rf ${cdroot}
-mkdir  ${cdroot}
-
-rsync -aHS --delete-excluded ${HOME}/dist/  ${cdroot}/liberte
-sed -i "s/SYSVER/${sysver}/" ${cdroot}/liberte/setup.sh
-
-
-sinfo "Copying image /boot"
-rsync -aHS --delete-excluded ${live}/boot ${cdroot}/liberte
-mv ${cdroot}/liberte/boot/EFI ${cdroot}
-
-
-sinfo "Converting text files to DOS line endings"
-find ${cdroot} \( -name '*.txt' -o -name '*.bat' -o -name '*.cfg' \) \
-    -exec sed -i 's/$/\r/' {} \;
-
-
 # Using default block size of 128KiB
 # (chmod due to GRKERNSEC_HIDESYM)
 sinfo "Creating SquashFS image"
 
+rm -rf ${cdroot}
+mkdir  ${cdroot} ${cdroot}/liberte ${cdroot}/liberte/boot
+
 # NOTE: POSIX ACLs are not supported by SquashFS
 #       Non-PaX user xattrs are not supported by tmpfs
 mksquashfs ${live} ${sqimage}                \
@@ -101,34 +76,8 @@ mksquashfs ${live} ${sqimage}                \
 chmod go= ${sqimage}
 
 
-sinfo "Adapting Syslinux and GRUB configuration"
-
-fshash=`sha256sum ${sqimage}`
-sed -i "s/FSHASH/${fshash%% *}/"                  \
-    ${cdroot}/liberte/boot/syslinux/syslinux.cfg  \
-    ${cdroot}/liberte/boot/grub/grub.cfg          \
-    ${cdroot}/liberte/qemulate.sh
-
-sha256sum ${cdroot}/liberte/boot/grub/* ${ziimage}  \
-    | sed "/\<grub\.\(cfg\|mf\)\>/d; s:${cdroot}::" \
-    > ${cdroot}/liberte/boot/grub/grub.mf
-
-grub1hash=`sha256sum ${cdroot}/liberte/boot/grub/grub.cfg`
-grub2hash=`sha256sum ${cdroot}/liberte/boot/grub/grub.mf`
-sed -i "s/replace_hash_\{50\}01/${grub1hash%% *}/ ; \
-        s/replace_hash_\{50\}02/${grub2hash%% *}/"  \
-    ${cdroot}/EFI/BOOT/*.EFI
-
-
-sinfo "Signing EFI GRUB images"
-
-cp -p ${efisbpfx}-CA.der ${cdroot}/EFI/
-for efiimg in ${cdroot}/EFI/BOOT/*.EFI; do
-    sbsign   --cert ${efisbpfx}-Cert-1.crt --key ${efisbpfx}-Cert-1.key \
-             --output ${efiimg}.signed ${efiimg}
-    sbverify --cert ${efisbpfx}-CA.crt ${efiimg}.signed
-    mv ${efiimg}.signed ${efiimg}
-done
+sinfo "Initializing boot environment"
+${helpdir}/mk-boot
 
 
 # UEFI Spec 2.3.1 Err. A, Sec. 12.3.3: "UEFI implementations may allow
@@ -139,46 +88,18 @@ rm -f ${imagepfx}.zip
 unzip -qt ${imagepfx}.zip
 
 
-# Add two extra 4K blocks (may need adjustment)
-sinfo "Creating EFI boot image for El-Torito"
-
-mkdir ${cdroot}/boot
-efiblocks=`du -s -B 4K --apparent-size ${cdroot}/EFI | cut -f1`
-truncate -s $(((efiblocks + 2) * 4))K ${efiboot}
-
-mkdosfs -n "${efilabel}" -I -f 1 -r 16 -R 1 ${efiboot}
-MTOOLS_SKIP_CHECK=1 mcopy -i ${efiboot} -smQ ${cdroot}/EFI ::
-
-
-# Hide root directories on Windows, and reset volume information
-# Allow '-' in filenames, since ISOLINUX doesn't support RockRidge/Joliet
-# (translation equivalent to mount's map=normal is still performed)
 sinfo "Creating ISO image ${imagepfx##*/}.iso"
-
-mkdir ${cdroot}/boot/syslinux
-cp -p ${cdroot}/liberte/boot/syslinux/syslinux.cfg \
-      ${cdroot}/boot/syslinux/syslinux.cfg
-
-set -- -quiet -iso-level 2 -relaxed-filenames -R -no-pad \
-       -sysid '' -V '' -A ''                             \
-       -no-emul-boot -boot-load-size 4 -boot-info-table  \
-       -c boot/eltorito.cat                              \
-       -b liberte/boot/syslinux/isolinux.bin             \
-       -eltorito-alt-boot -no-emul-boot                  \
-       -eltorito-platform efi -b boot/efiboot.img        \
-       -hidden boot -hidden liberte -m EFI
-mkisofs "$@" -o ${imagepfx}.iso ${cdroot}
-isovfy ${imagepfx}.iso
+${helpdir}/mk-iso
 
 
-sinfo "Creating ISO image ${imagepfx##*/}-bootstrap.iso"
-mkisofs "$@" -m ${sqimage##*/} -o ${imagepfx}-bootstrap.iso ${cdroot}
-isovfy ${imagepfx}-bootstrap.iso
+sinfo "Creating OVA bundle ${imagepfx##*/}.zip"
+${helpdir}/mk-ova
 
 
 echo "Disk usage: `du -s --apparent-size -B 1M ${cdroot} | cut -f1` MiB"
 echo "ZIP size:   `mibsize ${imagepfx}.zip` MiB"
 echo "ISO size:   `mibsize ${imagepfx}.iso` MiB"
+echo "OVA size:   `mibsize ${imagepfx}.ova` MiB"
 
 
 sinfo "Done."