aboutsummaryrefslogblamecommitdiff
path: root/scripts/disk_image
blob: 1efc3afe3a1d63bd8761a7b381c5741f8e509cd8 (plain) (tree)
1
2
3
4
5
           
 
                                                         
         
 



















                                   











                                                                     
































                                                                                            
































































































































































































































































































                                                                                                                                                                                                                                             






                                         
                  







                                                              
                                    
            















                                                                                            



                                                          
 





                                                                     
 
                                       
                















                                                                          
              
 
                                                 
                









                                                                            
              








                               


                        



                              



                                                 

                                                          


                                          
        

                                                                                        

      
                                          


                     




                                                  
                                                    










                                                                                                        

















                                    
                       









                                                              
 



                                                 



                                                          
                                          
        
                                                                                        

      
        




                               


                   
                                                                                                                   



                                                                                           




                                                                                   
                                                                                
                                                                         
                                                                                                     










                                                                
 
                                   

                  















                                    







                                           











                         


               
















                                                             
 







                                                             
 
                                         
                                     
 



                  


                            













                                  
                       
                                                           
                                                                                 
                                                                                  
 



                                                                                        








                                                                                              







                                                                                      












                                                                                                 



                                                                                   
 


                            
                                                                                           

                                 
                                                                                                


                                         
                                                                                                        

                   








                                                







                                                                                         
    
                                
  
 




                                
                                          



                                
 





                                                                  

                                                  
                              



                            







                                                                                          












                                                                   
  
           



                               

                                          
  
           

    







                                                  




                                                        

                                                               

                                                        
                                                         
 



                                                             








                                                                     







                                                             








                                                                        



                                                          
 


                            
                                                                  

                                 
                                                                       


                                         
                                                                               

                   

    





                                                                                  
 


                      
                                 
                           







                                
                                            




                       
                  
#!/bin/bash

PROG_REQ=( kpartx mkfs.ext4 losetup sgdisk readlink awk )
SLACK=128

function cleanup_disk_image()
{
    kpartx -d /dev/mapper/diskimage
    dmsetup remove diskimage
    losetup -d $_loop_dev

    remove_tmp_files

    if [ "$DESTDIR_DEL" = true ]
    then
        rm -rf "$DESTDIR"
    fi
}

function cleanup_disk_image_error()
{
    cleanup_disk_image
    rm $IMG
}

function check_depends()
{
    for ((i=0; i<${#PROG_REQ[@]}; i++))
    do
        if ! command -v ${PROG_REQ[i]} > /dev/null
        then
            echo "Please install the needed program: ${PROG_REQ[i]}."
            exit 1
        fi
    done
}

function add_rootfs()
{
    local dev=${LOAD_CMD%:*}
    dev=${dev##* }
    local par=${LOAD_CMD#*:}
    local j=$1

    if [ -z "$dev" ] || [ -z "$par" ]
    then
        echo "Could not parse device and partition."
        exit 1
    fi

    par=$(( $par + $j ))

    if [[ $LOAD_CMD =~ mmc ]]
    then
        retval="/dev/mmcblk${dev}p${par}"
    elif [[ $LOAD_CMD =~ scsi ]]
    then
        # converts number to a scsi device character
        dev=$((dev + 97))
        dev=$(printf %x $dev)
        dev=$(printf "\x$dev")

        retval="/dev/sd${dev}${par}"
    else
        echo "Only mmc and scsi are supported for automatically setting the root partition."
        echo "Manually set DOM0_CMD with the root device in the config file to bypass this."
        exit 1
    fi
}

function get_interrupts()
{
    local xen_intr_txt="$1"
    local num_fields
    local intr_num
    local intr_str
    local val
    local i

    while IFS= read -r val
    do
        #Remove the prefix "interrupts = <"
        val=${val#*"interrupts = <"}

        #Remove the suffix ">;" from each line
        val=${val%>;*}

        num_fields=`echo $val | awk '{print NF}'`

        #We expect the following format
        #interrupts = <0x00 irq_no flags 0x00 irq_no flags 0x00 irq_no flags ..>;
        if test $((num_fields % 3)) -ne 0
        then
            return 1
        fi

        #Position of the first interrupt no
        i=2
        while test $i -lt $num_fields
        do
            intr_num=`echo $val | awk -v i="$i" '{print $i}'`

            #The next irq_no will be after 3 places
            i=$((i+3))

            intr_num=$((intr_num + 32))

            if test "$intr_str"
            then
                intr_str="$intr_str,"
            fi
            intr_str="$intr_str"$intr_num
        done

    done < "$xen_intr_txt"

    if test  "$intr_str"
    then
        echo "$intr_str"
    fi
}

function contains()
{
    local item="$1"
    local list="$2"
    local each

    for each in $list
    do
        if test "$each" = "$item"
        then
            echo "yes"
        fi
    done
}

function check_if_force_assign_iommu()
{
    local xen_path="$1"
    local dtb="$2"
    local node="$3"
    local path
    local subnode
    local subnode_cnt
    local props
    local xen_path_present
    local assign_present

    subnode_cnt=$(fdtget -l "$dtb" "$node" | wc -l)

    props=$(fdtget -p "$dtb" "$node")
    xen_path_present=$(contains "xen,path" "$props")
    assign_present=$(contains "xen,force-assign-without-iommu" "$props")

    if test "$xen_path_present" = "yes" && test "$assign_present" = "yes"
    then
        path=$(fdtget "$dtb" "$node" "xen,path")
        if test "$path" = "$xen_path"
        then
            echo "yes"
            return 0
        fi
    fi

    if test $subnode_cnt -gt 0
    then
        for subnode in `fdtget -l  "$dtb" "$node"`
        do
            subnode="$node/$subnode"
            check_if_force_assign_iommu "$xen_path" "$dtb" "$subnode"
        done
    fi
}

function get_iommu_prop()
{
    local xen_path_txt="$1"
    local domU_dtb="$2"
    local dtdev_str
    local devpath
    local force_assign

    #Iterate through all the lines in the file
    while IFS= read -r devpath
    do
        #Extract the path of the device from each line
        #
        #For eg, the line may be as follows
        #xen,path = "/axi/serial@ff010000";
        #
        #What we want is the following substring
        #"/axi/serial@ff010000"
        devpath=`echo $devpath | awk '{print $3}'`
        devpath=${devpath#*\"}
        devpath=${devpath%\";*}

        force_assign=$(check_if_force_assign_iommu "$devpath" "$domU_dtb" "/passthrough")

        if test -z "$force_assign"
        then
            if test "$dtdev_str"
            then
                dtdev_str="$dtdev_str, "
            fi
            dtdev_str=${dtdev_str}"\""${devpath}"\""
        fi

    done < "$xen_path_txt"

    if test "$dtdev_str"
    then
        echo "$dtdev_str"
    fi
}

function get_iomem()
{
    local xen_reg_txt="$1"
    local addr="$2"
    local size="$3"
    local val
    local i
    local num_fields
    local iomem_str
    local address_size_pair
    local mfn
    local gfn
    local size_
    local PAGE_SHIFT=12

    #Iterate through all the lines in the file
    #The file will look similar to the following:-
    #
    #xen,reg = <0x00 0xff010000 0x00 0x1000 0x00 0xff010000 0x00 0xff110000 0x00 0x1000 0x00 0xff110000 0x00 0xff120000 0x00 0x1000 0x00 0xff120000 0x00 0xff130000 0x00 0x1000 0x00 0xff130000 0x00 0xff140000 0x00 0x1000 0x00 0xff140000>;
    #xen,reg = <0x00 0xfd0c0000 0x00 0x2000 0x00 0xfd0c0000>;
    while IFS= read -r val
    do
        #Remove the prefix "xen,reg = <" from each line
        val=${val#*"xen,reg = <"}

        #Remove the suffix ">;" from each line
        val=${val%>;*}

        num_fields=`echo $val | awk '{print NF}'`

        i=0

        while test $i -lt $num_fields
        do

            i=$((i + addr))

            #Extract the iomem physical address
            mfn=`echo $val | awk -v i="$i" '{print $i}'`

            #Calculate the page address
            mfn=0x$(printf "%X" $(( $((mfn>>PAGE_SHIFT)) & 0xfffff)) )

            i=$((i + size))

            #Extract the size of the iomem address
            size_=`echo $val | awk -v i="$i" '{print $i}'`

            #Calculatde the number of pages
            size_=$(printf "%X" $(( $((size_>>PAGE_SHIFT)) & 0xfffff)) )

            i=$((i + addr))

            #Extract the iomem guest address
            gfn=`echo $val | awk -v i="$i" '{print $i}'`

            #Calculate the page address
            gfn=0x$(printf "%X" $(( $((gfn>>PAGE_SHIFT)) & 0xfffff)) )

            if test "$gfn" != "$mfn"
            then
                address_size_pair="\"$mfn,${size_}@${gfn}\""
            else
                address_size_pair="\"$mfn,$size_\""
            fi

            if test "$iomem_str"
            then
                iomem_str="$iomem_str, $address_size_pair"
            else
                iomem_str=$address_size_pair
            fi
        done

    done < "$xen_reg_txt"

    if test "$iomem_str"
    then
        echo "$iomem_str"
    fi
}

function update_domU_cfg()
{
    local domU_dtb="$1"
    local domU_cfg_file="$2"
    local addr=$(fdtget $domU_dtb /passthrough \#address-cells)
    local size=$(fdtget $domU_dtb /passthrough \#size-cells)
    local iomem_str
    local dtdev_str
    local intr_str
    local tmp_dts
    local tmp_search_results

    tmp_dts=`mktemp`
    tmp_files+=($tmp_dts)
    dtc -I dtb -O dts -o "$tmp_dts" "$domU_dtb"

    tmp_search_results=`mktemp`
    tmp_files+=($tmp_search_results)

    #Let's get all the lines containing xen,path in a file
    grep 'xen,reg' "$tmp_dts" > "$tmp_search_results"

    #From "xen,reg", one can determine the "iomem" attribute of the
    #cfg file.
    iomem_str="$(get_iomem $tmp_search_results $addr $size)"
    if test -z "$iomem_str"
    then
        echo "Error occurred while generating the iomem property"
        return 1
    else
        iomem_str="iomem = [ "$iomem_str" ]"
        echo "${iomem_str}" >> $domU_cfg_file
    fi

    #Let's get all the lines containing xen,path in a file
    grep 'xen,path' $tmp_dts > $tmp_search_results

    #From "xen,path", one can determine the "dtdev" attribute of the
    #cfg file. This attribute is optional.
    dtdev_str=$(get_iommu_prop $tmp_search_results $domU_dtb)
    if test "$dtdev_str"
    then
        dtdev_str="dtdev = [ "$dtdev_str" ]"
        echo "${dtdev_str}" >> $domU_cfg_file
    fi

    #Let's get all the lines containing interrupts in a file
    grep 'interrupts' $tmp_dts > $tmp_search_results

    #From "interrupts", one can determine the "irqs" attribute of the
    #cfg file.
    intr_str=$(get_interrupts $tmp_search_results)
    if test "$intr_str"
    then
        intr_str="irqs = [ "$intr_str" ]"
        echo "${intr_str}" >> $domU_cfg_file
    fi

    return 0
}

function generate_domU_configs()
{
    local i=0
    local j=$1
    # $j + 1 - 1 as it is starting from 0
    local n=$1
    local dest
    local dtb_name

    mount -t ext4 /dev/mapper/diskimage$j $DESTDIR/part/disk$j
    mkdir -p $DESTDIR/part/disk$j/etc/xen
    add_rootfs 0
    first_part=$retval

    while test $i -lt $NUM_DOMUS
    do
        if test "${DOMU_NOBOOT[$i]}"
        then
            if test -z "${DOMU_PASSTHROUGH_DTB[$i]}" && test "${DOMU_PASSTHROUGH_PATHS[$i]}"
            then
                output_dir=`mktemp -d`
                tmp_dirs+=($output_dir)

                # Check if the below function returns error
                # and unmount the partition
                compile_merge_partial_dts $output_dir "$PASSTHROUGH_DTS_REPO"
                if test $? -ne 0
                then
                    umount $DESTDIR/part/disk$j
                    cleanup_disk_image_error
                    exit 1
                fi
            fi

            dest="$DESTDIR/part/disk$j/etc/xen/domU$i.cfg"
            echo "name=\"domU$i\"" >> $dest
            echo "memory=${DOMU_MEM[$i]}" >> $dest
            echo "vcpus=${DOMU_VCPUS[$i]}" >> $dest

            echo "# mount $first_part /boot" >> $dest
            echo "kernel=\"/boot/${DOMU_KERNEL[$i]}\"" >> $dest
            if test "${DOMU_RAMDISK[$i]}"
            then
                echo "ramdisk=\"/boot/${DOMU_RAMDISK[$i]}\"" >> $dest
            fi

            if [ -z "${DOMU_CMD[$i]}" ]
            then
                DOMU_CMD[$i]="console=hvc0"
            fi
            if [[ ! ${DOMU_CMD[$i]} =~ root= ]]
            then
                if test -z "${DOMU_ROOTFS[$i]}"
                then
                    DOMU_CMD[$i]="${DOMU_CMD[$i]} root=/dev/ram0" >> $dest
                else
                    DOMU_CMD[$i]="${DOMU_CMD[$i]} root=/dev/xvda" >> $dest
                fi
            fi
            echo "extra=\"${DOMU_CMD[$i]}\"" >> $dest
            if test "${DOMU_ROOTFS[$i]}"
            then
                add_rootfs $n
                echo "disk=[\"$retval,,xvda\"]" >> $dest
            fi

            if test "${DOMU_PASSTHROUGH_DTB[$i]}"
            then
                cp ${DOMU_PASSTHROUGH_DTB[$i]} $DESTDIR/part/disk$j/etc/xen/
                dtb_name="$(basename ${DOMU_PASSTHROUGH_DTB[$i]})"
                echo "device_tree=\"/etc/xen/$dtb_name\"" >> $dest
                update_domU_cfg  ${DOMU_PASSTHROUGH_DTB[$i]} $dest
                if test $? -ne 0
                then
                    umount $DESTDIR/part/disk$j
                    cleanup_disk_image_error
                    exit 1
                fi
            fi
        fi

        n=$(( $n + 1 ))
        i=$(( $i + 1 ))
    done

    umount $DESTDIR/part/disk$j
}

function add_partition()
{
    local rootfs="$1"
    local aux_dir=$(mktemp -d)

    cd "$aux_dir"

    if [[ $rootfs = *.cpio ]]
    then
        cat "${UBOOT_OUT_ABS}/$rootfs" | cpio -id
    elif [[ $rootfs = *.cpio.gz ]]
    then
        cat "${UBOOT_OUT_ABS}/$rootfs" | gunzip | cpio -id
    elif [[ $rootfs = *.tar.gz ]]
    then
        tar -xf "${UBOOT_OUT_ABS}/$rootfs"
    else
        echo "Ignoring $rootfs: unsupported file format. Use cpio or cpio.gz or tar.gz."
        exit 1
    fi

    _part_size=$(du -sb| awk '{print $1}')
    cd -
    rm -rf "$aux_dir"

    _part_size=$(( $_part_size + $offset - 1))
    _part_size=$(( $_part_size & ~($offset - 1) ))
    # account for gzip compression
    _part_size=$(( $_part_size * 2 ))
    # add some slack
    _part_size=$(( $SLACK*1024*1024 + $_part_size ))
    _part_size=$(( $_part_size / 1024 / 1024 ))
    echo PART size: "$_part_size"MB
    
    prev=$(( $_npart - 1 ))
    _sector_start[$_npart]=$(( ${_sector_end[$prev]} + 1 ))
    _sector_end[$_npart]=$(( $_part_size * 1024 * 1024 / $_sector_size + ${_sector_start[$_npart]} - 1))

    _tot_size=$(( $_tot_size + $_part_size ))
    _npart=$(( $_npart + 1 ))
}

function align_size_power_of_two()
{
    local _cnt_bits=0
    local num=$1
    local _num=$num
    while [ $_num -ne 0 ]
    do
        _num=$((_num >> 1))
        _cnt_bits=$((_cnt_bits + 1))
    done
    _num=$((1<<(_cnt_bits - 1)))
    if [ $num -gt $_num ]
    then
        _num=$((1<<_cnt_bits))
    fi
    echo $_num
}

function write_rootfs()
{
    local j=$1
    local rootfs=$2

    # create mount point and mount diskn
    mkdir -p ${DESTDIR}/part/disk$j
    mount -t ext4 /dev/mapper/diskimage$j $DESTDIR/part/disk$j
    
    # Extract rootfs cpio archive into `.../part/vos_$j`
    cd ${DESTDIR}/part/disk$j

    if [[ $rootfs = *.cpio ]]
    then
        cat "${UBOOT_OUT_ABS}/$rootfs" | cpio -id
    elif [[ $rootfs = *.cpio.gz ]]
    then
        cat "${UBOOT_OUT_ABS}/$rootfs" | gunzip | cpio -id
    elif [[ $rootfs = *.tar.gz ]]
    then
        tar -xf "${UBOOT_OUT_ABS}/$rootfs"
    else
        echo "Ignoring $rootfs: unsupported file format. Use cpio or cpio.gz or tar.gz."
    fi

    cd -
    # umount
    sync
    umount $DESTDIR/part/disk$j
}

function print_help
{
    echo "usage:"
    echo "	$0 -c CONFIG_FILE -d UBOOT_DIRECTORY -t UBOOT_TYPE <-w WORK_DIRECTORY> <-s SLACK> <-a> -o IMG_FILE"
    echo "	$0 -h"
    echo "where:"
    echo "	-c CONFIG_FILE - configuration file"
    echo "	-d UBOOT_DIRECTORY - root directory for the paths specified in CONFIG_FILE"
    echo "	-t UBOOT_TYPE can be:"
    echo "		sd - alias for \"mmc load 0:1\" for uboot load commands"
    echo "		scsi - alias for \"scsi load 0:1\" for uboot load commands"
    echo "		tftp - alias for \"tftpb\" for uboot load cammnds"
    echo "		< > - used for uboot load commands"
    echo "	-w WORK_DIRECTORY - work directory used when building the image"
    echo "	-s SLACK - free MB to add to each partition, default 128"
    echo "	-a specifies that the size of IMG_FILE has to be aligned to the nearest power of two"
    echo "	-o IMG_FILE - the output img file "
    echo "Example:"
    echo "	$0 -c ../config -d ./build42 -w tmp -o disk.img"
}

# before anything else, check if we have root privilege
if ! [ $(id -u) = 0 ]
then
    echo "This script needs root privilege to run, exiting."
    exit 1
fi

while getopts ":w:d:c:t:s:o:ah" opt
do
    case ${opt} in
    t )
        case $OPTARG in
        scsi )
            LOAD_CMD="load scsi 0:1"
            ;;
        sd )
            LOAD_CMD="load mmc 0:1"
            ;;
        tftp )
            LOAD_CMD="tftpb"
            ;;
        * )
            LOAD_CMD="$OPTARG"
            ;;
        esac
        ;;
    s )
        SLACK=$OPTARG
        if ! test $SLACK -gt 0
        then
            echo "Invalid SLACK parameter."
            exit 1
        fi
        ;;
    w )
        DESTDIR=$OPTARG
        ;;
    d )
        UBOOT_OUT=$OPTARG
        ;;
    c )
        CFG_FILE=$OPTARG
        ;;
    o )
        IMG=$OPTARG
        ;;
    a )
        ALIGN=1
        ;;
    h )
        print_help
        exit 0
        ;;
    * )
        echo "Unknown option, see \"$0 -h\""
        exit 1
        ;;
    esac
done
shift $((OPTIND -1))

if [ -z "$UBOOT_OUT" ] || [ -z "$CFG_FILE" ] || [ -z "$IMG" ]
then
    echo "Undefined arguments, see \"$0 -h\""
    exit 1
fi

# if the user hasn't specified a working directing, create it
if [ -z "$DESTDIR" ]
then
    DESTDIR="$(mktemp -d /tmp/imagebuilder.XXXXXX)"
    DESTDIR_DEL=true
else
    DESTDIR_DEL=false
fi

UBOOT_OUT_ABS="$(readlink -f $UBOOT_OUT)"
DESTDIR_ABS="$(readlink -f $DESTDIR)"

check_depends

source "$CFG_FILE"

SCRIPT_PATH=$(dirname "$0")
source "$SCRIPT_PATH/common"

i=0
while test $i -lt $NUM_DOMUS
do
    if test -z "${DOMU_MEM[$i]}"
    then
        DOMU_MEM[$i]=512
    fi
    if test -z "${DOMU_VCPUS[$i]}"
    then
        DOMU_VCPUS[$i]=1
    fi
    i=$(( $i + 1 ))
done

offset=$((2*1024*1024))
_part1_size=`stat -L --printf="%s" $UBOOT_OUT/$DOM0_KERNEL`
_part1_size=$(( $_part1_size + `stat -L --printf="%s" $UBOOT_OUT/$DEVICE_TREE` ))
_part1_size=$(( $_part1_size + `stat -L --printf="%s" $UBOOT_OUT/$UBOOT_SCRIPT` ))

if test "${DOM0_RAMDISK}"
then
    _part1_size=$(( $_part1_size + `stat -L --printf="%s" $UBOOT_OUT/${DOM0_RAMDISK}` ))
fi
if test "$NUM_DT_OVERLAY" && test "$NUM_DT_OVERLAY" -gt 0
then
    i=0
    while test $i -lt "$NUM_DT_OVERLAY"
    do
        _part1_size=$(( $_part1_size + `stat -L --printf="%s" $UBOOT_OUT/${DT_OVERLAY[$i]}` ))
        i=$(( $i + 1 ))
    done
fi
if test "${UBOOT_SOURCE}"
then
    _part1_size=$(( $_part1_size + `stat -L --printf="%s" $UBOOT_OUT/$UBOOT_SOURCE` ))
fi
if test "${XEN}"
then
    _part1_size=$(( $_part1_size + `stat -L --printf="%s" $UBOOT_OUT/$XEN` ))
fi
if test "$NUM_BOOT_AUX_FILE"  && test "$NUM_BOOT_AUX_FILE" -gt 0
then
    i=0
    while test $i -lt "$NUM_BOOT_AUX_FILE"
    do
        if [ ! -f "$UBOOT_OUT/${BOOT_AUX_FILE[$i]}" ]
        then
            echo "Can not find ${BOOT_AUX_FILE[$i]}, exiting"
        fi
        _part1_size=$(( $_part1_size + `stat -L --printf="%s" $UBOOT_OUT/${BOOT_AUX_FILE[$i]}` ))
        i=$(( $i + 1 ))
    done
fi
if test "${BITSTREAM}"
then
    _part1_size=$(( $_part1_size + `stat -L --printf="%s" $UBOOT_OUT/$BITSTREAM` ))
fi

i=0
while test $i -lt $NUM_DOMUS
do
    _part1_size=$(( $_part1_size + `stat -L --printf="%s" $UBOOT_OUT/${DOMU_KERNEL[$i]}` ))
    if test "${DOMU_RAMDISK[$i]}"
    then
        _part1_size=$(( $_part1_size + `stat -L --printf="%s" $UBOOT_OUT/${DOMU_RAMDISK[$i]}` ))
    fi
    if test "${DOMU_PASSTHROUGH_DTB[$i]}"
    then
        _part1_size=$(( $_part1_size + `stat -L --printf="%s" $UBOOT_OUT/${DOMU_PASSTHROUGH_DTB[$i]}` ))
    fi
    i=$(( $i + 1 ))
done

# add 16 MB slack
_part1_size=$(( $_part1_size + 16777216 ))
_part1_size=$(( $_part1_size + $offset - 1))
_part1_size=$(( $_part1_size & ~($offset - 1) ))
_part1_size=$(( $_part1_size / 1024 / 1024 ))
echo PART1 size: "$_part1_size"MB

_sector_size=512
# _sector_start[0] needs to be aligned to 2048
_sector_start[0]=2048
_sector_end[0]=$(( $_part1_size * 1024 * 1024 / $_sector_size + ${_sector_start[0]} - 1))
_tot_size=$(( $_part1_size ))
_npart=1

if test "$DOM0_ROOTFS"
then
    add_partition "$DOM0_ROOTFS"
fi

i=0
while test $i -lt $NUM_DOMUS
do
    if test "${DOMU_ROOTFS[$i]}"
    then
        add_partition "${DOMU_ROOTFS[$i]}"
    fi
    i=$(( $i + 1 ))
done
_tot_size=$(( $_tot_size + 16 ))

# NOTE: Increase the size of the image to the nearest power of two
if test "$ALIGN"
then
    _tot_size=$(align_size_power_of_two $_tot_size)
fi

# NOTE: Increase vos_a to 256 to accomodate rootfs
# 528 MiB (256 + 256 + 16)
truncate $IMG -s "$_tot_size"M

# create GPT partition table
sgdisk -og $IMG

i=0
j=1
while test $i -lt $_npart
do
    sgdisk -n $j:${_sector_start[$i]}:${_sector_end[$i]} -c $j:"Linux""$j" -t $j:8300 $IMG
    i=$(( $i + 1 ))
    j=$(( $j + 1 ))
done

# find the first available loop device
_loop_dev=$(losetup -f)

# attach loopback device to $IMG
losetup $_loop_dev $IMG

_disksize=$(blockdev --getsize $_loop_dev)

dmsetup create diskimage --table "0 $_disksize linear $_loop_dev 0"

# ensure that /dev/mapper/diskimage exists
while [ ! -b /dev/mapper/diskimage ]
do
    sleep 2
done

kpartx -a /dev/mapper/diskimage

# ensure that /dev/mapperdiskimage1 exists
while [ ! -b /dev/mapper/diskimage1 ]
do
    sleep 2
done

i=0
j=1
while test $i -lt $_npart
do
    mkfs.ext4 -L vos_$j -F /dev/mapper/diskimage$j
    i=$(( $i + 1 ))
    j=$(( $j + 1 ))
done

# create mount point and mount disk1
mkdir -p ${DESTDIR}/part/disk1
mount -t ext4 /dev/mapper/diskimage1 $DESTDIR/part/disk1

# only copy over files that were counted for the partition size
cd "$UBOOT_OUT"
cp --parents "$DOM0_KERNEL" "${DESTDIR_ABS}/part/disk1/"
cp --parents "$DEVICE_TREE" "${DESTDIR_ABS}/part/disk1/"
cp --parents "$UBOOT_SCRIPT" "${DESTDIR_ABS}/part/disk1/"

if test "${DOM0_RAMDISK}"
then
    cp --parents "$DOM0_RAMDISK" "${DESTDIR_ABS}/part/disk1/"
fi
if test "$NUM_DT_OVERLAY" && test "$NUM_DT_OVERLAY" -gt 0
then
    i=0
    while test $i -lt "$NUM_DT_OVERLAY"
    do
        cp --parents "${DT_OVERLAY[$i]}" "${DESTDIR_ABS}/part/disk1/"
        i=$(( $i + 1 ))
    done
fi
if test "${UBOOT_SOURCE}"
then
    cp --parents "$UBOOT_SOURCE" "${DESTDIR_ABS}/part/disk1/"
fi
if test "${XEN}"
then
    cp --parents "$XEN" "${DESTDIR_ABS}/part/disk1/"
fi
if test "$NUM_BOOT_AUX_FILE" && test "$NUM_BOOT_AUX_FILE" -gt 0
then
    i=0
    while test $i -lt "$NUM_BOOT_AUX_FILE"
    do
        cp --parents "${BOOT_AUX_FILE[$i]}" "${DESTDIR_ABS}/part/disk1/"
        i=$(( $i + 1 ))
    done
fi
if test "${BITSTREAM}"
then
    cp --parents "$BITSTREAM" "${DESTDIR_ABS}/part/disk1/"
fi

i=0
while test $i -lt $NUM_DOMUS
do
    cp --parents "${DOMU_KERNEL[$i]}" "${DESTDIR_ABS}/part/disk1/"
    if test "${DOMU_RAMDISK[$i]}"
    then
        cp --parents "${DOMU_RAMDISK[$i]}" "${DESTDIR_ABS}/part/disk1/"
    fi
    if test "${DOMU_PASSTHROUGH_DTB[$i]}"
    then
        cp --parents "${DOMU_PASSTHROUGH_DTB[$i]}" "${DESTDIR_ABS}/part/disk1/"
    fi
    i=$(( $i + 1 ))
done
cd -

# unmount
sync
# This fails for some reason. It could work now because we are not using qemu-user
# fstrim $DESTDIR/part/disk1
umount $DESTDIR/part/disk1

j=2
if test "$DOM0_ROOTFS"
then
    write_rootfs 2 "$DOM0_ROOTFS"
    generate_domU_configs 2
    j=$(( $j + 1 ))
fi

i=0
while test $i -lt $NUM_DOMUS
do
    if test "${DOMU_ROOTFS[$i]}"
    then
        write_rootfs $j "${DOMU_ROOTFS[$i]}"
        j=$(( $j + 1 ))
    fi
    i=$(( $i + 1 ))
done

cleanup_disk_image