~smoser/cirros/trunk.mkcabundle-in-bash

« back to all changes in this revision

Viewing changes to bin/part2disk

  • Committer: Scott Moser
  • Date: 2016-07-21 14:56:04 UTC
  • mfrom: (369.1.29 cirros)
  • Revision ID: smoser@ubuntu.com-20160721145604-3n7dga1vnvaqakq1
Add support for UEFI booting on AArch64 and x86-64 architectures.

Grub2-efi binaries are pulled from Ubuntu and used to build EFI grub
images.

Disk images are switched to GPT scheme. Part1 is rootfs (from part.img
as it was), part15 is EFI System Partition with EFI grub in place
(on aarch64 and x86-64 only).

Also enabled ARM disk images to be part of release.

Boot tested:

- aarch64/uefi - grub
- aarch64/uefi - direct kernel
- arm - direct kernel
- i686/bios
- x86-64/bios
- x86-64/uefi

All those images booted fine. Not tested PPC ones yet.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
#    Copyright (C) 2010 Canonical Ltd.
5
5
#
6
6
#    Authors: Scott Moser <smoser@canonical.com>
 
7
#             Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
7
8
#
8
9
#    This program is free software: you can redistribute it and/or modify
9
10
#    it under the terms of the GNU General Public License as published by
17
18
#    You should have received a copy of the GNU General Public License
18
19
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20
 
 
21
source "${0%/*}/common-functions.sh"
 
22
 
20
23
DEF_SECTOR_SIZE=512
21
 
DEBUG=0
22
24
base_d=$(dirname $(readlink -f "${0}"))
23
25
PATH="${PATH}:${base_d}"
24
 
error() { echo "$@" 1>&2; }
25
 
debug() {
26
 
    [ "${DEBUG}" -ge "${1:-0}" ] && shift || return 0;
27
 
    error "$@";
28
 
}
29
 
fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
 
26
 
30
27
getsize() {
31
28
    local fname="$1" kname="" size=""
32
29
    if [ -b "${fname}" ]; then
48
45
 
49
46
Usage() {
50
47
    cat <<EOF
51
 
Usage: ${0##*/} [options] partition-image disk-image
 
48
Usage: ${0##*/} [options] partition-image grub-efi-tarball architecture disk-image
52
49
 
53
 
    create disk image 'disk-image' with 'partition-image' in a partition
54
 
    inside it.
 
50
    Create disk image 'disk-image' with 'partition-image' in a partition
 
51
    inside it. Add grub if requested.
55
52
 
56
53
    options:
57
54
      -G | --grub       install grub to disk image mbr
58
55
         | --grub1      install grub1 to disk image mbr
 
56
         | --grub-efi   install EFI grub to disk image
59
57
      -s | --size  S    create the disk image of size 'S'.
60
58
                        default is large enough to fit partition-image
61
59
      -v | --verbose    increase verbosity
62
60
EOF
63
61
}
64
 
bad_Usage() { Usage 1>&2; fail "$@"; }
65
62
human2bytes() {
66
63
    # converts size suitable for input to resize2fs to bytes
67
64
    # s:512 byte sectors, K:kilobytes, M:megabytes, G:gigabytes
78
75
    _RET=$((${count}*${unit}))
79
76
}
80
77
 
 
78
cleanup() {
 
79
    umount "$TMP/efi"
 
80
    umount "$TMP/rootfs"
 
81
    kpartx -d "$dimg"
 
82
}
 
83
 
 
84
trap cleanup EXIT
 
85
 
81
86
short_opts="b:c:Ghs:v"
82
 
long_opts="grub1,grub,help,size:,verbose"
 
87
long_opts="grub-efi,grub1,grub,help,size:,verbose"
83
88
getopt_out=$(getopt --name "${0##*/}" \
84
89
    --options "${short_opts}" --long "${long_opts}" -- "$@") &&
85
90
    eval set -- "${getopt_out}" ||
90
95
grub_ptnum=1
91
96
grub=0
92
97
grub1=0
 
98
grub_efi=0
93
99
while [ $# -ne 0 ]; do
94
100
    cur=${1}; next=${2};
95
101
    case "$cur" in
96
102
        -G|--grub) grub=1;;
97
103
        -G|--grub1) grub1=1;;
 
104
        --grub-efi) grub_efi=1;;
98
105
        -h|--help) Usage; exit 0;;
99
106
        -s|--size) size_in=$2; shift;;
100
107
        -v|--verbose) DEBUG=$((${DEBUG}+1));;
103
110
    shift;
104
111
done
105
112
 
106
 
[ $# -eq 2 ] || bad_Usage "must supply partition image and output file"
 
113
[ $# -eq 4 ] || bad_Usage "must supply partition image, grub-efi tarball, architecture and output file"
107
114
 
108
115
pimg=${1}
109
 
dimg=${2}
 
116
grub_efi_in=${2}
 
117
arch=${3}
 
118
dimg=${4}
110
119
 
111
120
{ [ ${grub} -eq 0 ] || phelper=$(command -v part2disk-grubhelper); } ||
112
121
    fail "no part2disk-grubhelper in PATH"
118
127
    fail "failed to get size of $pimg"
119
128
pimg_s="$_RET"
120
129
 
121
 
# end_pad_sectors: room for secondary gpt
122
 
end_pad_sectors=33
123
 
end_pad=$(($end_pad_sectors*$ssize))
124
 
front_pad=$((1024*1024))
125
 
front_pad_sectors=$(($front_pad/$ssize))
126
 
padding=$(($front_pad+$end_pad))
127
 
pt_sector_pad=$(($ssize-(${pimg_s}%$ssize)))
128
 
if [ $pt_sector_pad -eq $ssize ]; then
129
 
    pt_sector_pad=0
130
 
fi
131
 
pt_size=$(($pimg_s+$pt_sector_pad))
132
 
pt_sectors=$(($pt_size/$ssize))
133
 
tot_size=$(($front_pad+$pt_size+$end_pad))
 
130
front_pad=$((12*1024*1024))
 
131
tot_size=$(($front_pad+$pimg_s))
134
132
tot_size_sectors=$(($tot_size/$ssize))
135
133
 
136
134
if [ -n "${size_in}" ]; then
137
135
    human2bytes "${size_in}" 1 || fail "failed to convert ${size_in} to bytes"
138
136
    size=${_RET}
139
137
else
140
 
    # no size specified, get enough to fit part_img, 1M header and 1M end.
141
 
    size=$((${pimg_s}+$padding+$pt_sector_pad))
 
138
    size=$tot_size_sectors
142
139
fi
143
140
 
144
141
if [ -e "$dimg" ]; then
153
150
    fail "size of $dimg ($dimg_s) not large enough to fit $size"
154
151
fi
155
152
 
156
 
debug 1 "input is ${pimg_s} bytes ($pt_sectors sectors of $ssize)."
157
 
debug 1 "target is ${tot_size} bytes ($tot_size_sectors sectors)."
158
 
debug 1 "padding $front_pad_sectors sectors at front," \
159
 
        "$end_pad_sectors sectors at end."
 
153
debug 1 "input is ${pimg_s} bytes."
 
154
debug 1 "target is ${tot_size} bytes."
160
155
 
161
 
debug 2 "zeroing first $front_pad_sectors sectors $dimg"
162
 
dd if=/dev/zero of="${dimg}" bs=$ssize "count=${front_pad_sectors}" \
 
156
debug 2 "create target image"
 
157
dd if=/dev/zero of="${dimg}" bs=$ssize count=$tot_size_sectors \
163
158
    2>/dev/null ||
164
159
    fail "failed to write to ${dimg}"
165
160
 
 
161
debug 2 "create partitions"
 
162
sgdisk -n 15:2048:+8M -t 15:ef00 -N 1 $dimg
 
163
loop_nr=`kpartx -av $dimg | head -n1 | cut -d" " -f3 | cut -d"p" -f2`
 
164
 
166
165
# copy partition image. this writes $pimg bytes even if that is
167
166
# not divivisble by $ssize
168
167
debug 2 "copying ${pimg} to partition in ${dimg}"
169
 
dd if="$pimg" of="$dimg" seek=${front_pad_sectors} bs=$ssize conv=notrunc \
 
168
dd if="$pimg" of=/dev/mapper/loop${loop_nr}p1 conv=notrunc \
170
169
    2>/dev/null ||
171
170
    fail "failed to write ${pimg} into ${dimg}"
172
171
 
173
 
# zero any unwritten portion of the final sector
174
 
leftover=$(($ssize-(${pimg_s}%$ssize)))
175
 
if [ $pt_sector_pad -ne 0 ]; then
176
 
    debug 2 "finishing final sector with $pt_sector_pad bytes of zeros"
177
 
    dd if=/dev/zero of="$dimg" bs=1 seek=$((${pimg_s}+${front_pad})) \
178
 
        conv=notrunc count=$pt_sector_pad 2>/dev/null ||
179
 
    fail "failed to finish final sector of $pimg"
180
 
fi
181
 
 
182
 
# we've now written front pad + round-sectors. now write end_pad
183
 
debug 2 "writing final $end_pad_sectors sectors"
184
 
dd if=/dev/zero "of=$dimg" bs=$ssize \
185
 
    seek=$((($size/$ssize)-${end_pad_sectors})) count=${end_pad_sectors} \
186
 
    conv=notrunc 2>/dev/null ||
187
 
    fail "failed to write final 1M to $pimg"
188
 
 
189
 
sfdisk_in="${front_pad_sectors},$pt_sectors,L,*"
190
 
debug 2 "writing partition table to ${dimg} ($sfdisk_in)"
191
 
sfdisk_out=$(echo "$sfdisk_in" | sfdisk --force --unit=S "${dimg}" 2>&1)
192
 
 
193
 
[ $? -eq 0 ] || {
194
 
    error "${sfdisk_out}";
195
 
    fail "failed to create partition table";
196
 
}
197
 
 
198
172
if [ ${grub} -ne 0 ]; then
199
173
    debug 2 "invoking part2disk-grubhelper ${dimg}"
200
174
    sudo "${phelper}" "${dimg}" ||
211
185
EOF
212
186
fi
213
187
 
 
188
if [ $grub_efi -ne 0 ]; then
 
189
    case $arch in
 
190
        x86_64)  efiarch=x64;;
 
191
        aarch64) efiarch=aa64;;
 
192
        i386)    efiarch=ia32;;
 
193
        arm)     efiarch=arm;;
 
194
        *) fail "arch $arch without EFI grub"
 
195
    esac
 
196
    TMP=$(mktemp -d)
 
197
    install -d $TMP/tar $TMP/efi $TMP/rootfs
 
198
 
 
199
    mkfs.vfat /dev/mapper/loop${loop_nr}p15
 
200
    mount /dev/mapper/loop${loop_nr}p15 $TMP/efi
 
201
    install -d $TMP/efi/EFI/BOOT $TMP/efi/EFI/ubuntu
 
202
    tar -xf $grub_efi_in -C $TMP/efi/EFI/BOOT
 
203
 
 
204
    mount /dev/mapper/loop${loop_nr}p1 $TMP/rootfs
 
205
    kernelfile=$(cd $TMP/rootfs/boot; ls vmlinu* | head -n1)
 
206
    initrdfile=$(cd $TMP/rootfs/boot; ls initrd.img-* | head -n1)
 
207
 
 
208
        
 
209
    cat >$TMP/efi/EFI/ubuntu/grub.cfg <<EOF
 
210
set default=0
 
211
set timeout=1
 
212
menuentry 'CirrOS' {
 
213
        set root='hd0,gpt1'
 
214
        if [ x$feature_platform_search_hint = xy ]; then
 
215
          search --no-floppy --label --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci1,gpt1  cirros-rootfs
 
216
        else
 
217
          search --no-floppy --label --set=root cirros-rootfs
 
218
        fi
 
219
 
 
220
    linux  /boot/${kernelfile} LABEL=cirros-rootfs ro
 
221
    initrd /boot/${initrdfile} 
 
222
}
 
223
EOF
 
224
 
 
225
    umount "$TMP/efi"
 
226
    umount "$TMP/rootfs"
 
227
fi
 
228
 
 
229
kpartx -d "$dimg"
214
230
error "wrote to ${dimg}"
215
 
 
216
 
# vi: tabstop=4 expandtab
 
231
# vi: ts=4 noexpandtab