|
1054
by Scott Moser
Add support for booting multiboot images from a floppy (LP: #611144) |
1 |
Description: add support for booting a multiboot image from a floppy |
2 |
This adds a tool 'mk-mb-loader' which takes a multiboot compliant image |
|
3 |
and puts it onto a floppy disk image and loads it. |
|
4 |
. |
|
5 |
It also contains modifications to gen_kvm_libvirt_xml that |
|
6 |
a.) make mk-mb-loader run |
|
7 |
b.) modify libvirt xml output to add a floppy disk and boot |
|
8 |
off it rather than booting via '<kernel>' |
|
9 |
. |
|
10 |
The hack to boot off of a floppy is required because when a multiboot |
|
11 |
image is loaded by 'kvm -kernel "mb.img"', it will not have access to |
|
12 |
scsi disks. That means that if a scsi disk is the root block device |
|
13 |
that the multiboot image will not see any disks. |
|
14 |
. |
|
15 |
The solution is to boot via floppy instead. The mk-mb-image creates |
|
16 |
a floppy disk that loads the user provided multiboot image. |
|
17 |
. |
|
18 |
In the future, this patch can be dropped if either of the following occur: |
|
19 |
a.) scsi root disk support is abandoned |
|
20 |
b.) seabios gains native support for scsi disks, such that |
|
21 |
'kvm -kernel <mb.img' has access to scsi disks as it has access to |
|
22 |
ide or virtio disks in seabios 0.6.0-0ubuntu1. |
|
23 |
. |
|
24 |
That would provide a much more clean solution of simply booting with |
|
25 |
'-kernel' whatever the user provided. |
|
26 |
Author: Scott Moser <scott.moser@canonical.com> |
|
27 |
Last-Update: 2010-07-28 |
|
28 |
Bug: https://bugs.launchpad.net/eucalyptus/+bug/611144 |
|
29 |
--- a/node/handlers.c
|
|
30 |
+++ b/node/handlers.c
|
|
31 |
@@ -380,6 +380,7 @@
|
|
32 |
char **xml) |
|
33 |
{
|
|
34 |
char buf [MAX_PATH]; |
|
35 |
+ char patharg [MAX_PATH];
|
|
36 |
||
37 |
snprintf(buf, MAX_PATH, "%s", gen_libvirt_cmd_path); |
|
38 |
if (strnlen(ramdiskId, CHAR_BUFFER_SIZE)) {
|
|
39 |
@@ -395,6 +396,9 @@
|
|
40 |
if (params->disk > 0) { /* TODO: get this info from scMakeImage */
|
|
41 |
strncat (buf, " --ephemeral", MAX_PATH); |
|
42 |
} |
|
43 |
+ snprintf(buf+strnlen(buf,MAX_PATH), MAX_PATH-strnlen(buf,MAX_PATH),
|
|
44 |
+ " --basepath='%s'", disk_path);
|
|
45 |
+
|
|
46 |
* xml = system_output (buf); |
|
47 |
if ( ( * xml ) == NULL ) {
|
|
48 |
logprintfl (EUCAFATAL, "%s: %s\n", gen_libvirt_cmd_path, strerror (errno)); |
|
49 |
--- a/tools/gen_kvm_libvirt_xml
|
|
50 |
+++ b/tools/gen_kvm_libvirt_xml
|
|
51 |
@@ -76,6 +76,8 @@
|
|
52 |
our $local_kvm=""; |
|
53 |
our $use_virtio_net = 0; |
|
54 |
our $use_virtio_root = 0; |
|
55 |
+our $base_path = "";
|
|
56 |
+our $multi_boot_floppy = 0;
|
|
57 |
||
58 |
if ( -x "/usr/bin/kvm" ) {
|
|
59 |
$local_kvm="/usr/bin/kvm"; |
|
|
1062
by Scott Moser
work around kvm virtio bug with -kernel by using boot floppy LP: #615529 |
60 |
@@ -90,24 +92,38 @@
|
|
1054
by Scott Moser
Add support for booting multiboot images from a floppy (LP: #611144) |
61 |
'ephemeral' => sub { }, # option ignored
|
62 |
'virtionet' => sub { $use_virtio_net = 1; },
|
|
63 |
'virtioroot' => sub { $use_virtio_root = 1; },
|
|
64 |
+ 'basepath=s' => \$base_path,
|
|
65 |
) or exit (1); |
|
66 |
||
|
1062
by Scott Moser
work around kvm virtio bug with -kernel by using boot floppy LP: #615529 |
67 |
+if ($base_path && &is_multiboot_img($base_path . "/kernel")) {
|
|
1054
by Scott Moser
Add support for booting multiboot images from a floppy (LP: #611144) |
68 |
+ $multi_boot_floppy = 1;
|
69 |
+}
|
|
70 |
+
|
|
71 |
print <<EOF; |
|
72 |
<domain type='kvm'> |
|
73 |
<name>NAME</name> |
|
74 |
<os> |
|
75 |
<type>hvm</type> |
|
76 |
- <kernel>BASEPATH/kernel</kernel>
|
|
77 |
EOF |
|
78 |
||
79 |
-if ( $use_ramdisk ) {
|
|
80 |
- print " <initrd>BASEPATH/ramdisk</initrd>\n";
|
|
81 |
-}
|
|
82 |
-
|
|
83 |
-if ( $use_virtio_root ) {
|
|
84 |
- print " <cmdline>root=/dev/vda1 console=ttyS0</cmdline>\n"
|
|
85 |
+if ( $multi_boot_floppy ) {
|
|
86 |
+ my $mb_load_cmd = "/usr/share/eucalyptus/mk-mb-loader " .
|
|
87 |
+ "'" . $base_path . "/kernel' '" . $base_path . "/loader' 2>&1";
|
|
88 |
+ my $mb_out = `$mb_load_cmd`;
|
|
89 |
+ if ( $? != 0 ) { print("failed to make loader\n${mb_out}\n"); exit(1); }
|
|
90 |
+ print " <boot dev='fd'/>\n";
|
|
91 |
+ print " <boot dev='hd'/>\n";
|
|
92 |
} else {
|
|
93 |
- print " <cmdline>root=/dev/sda1 console=ttyS0</cmdline>\n"
|
|
94 |
+ print " <kernel>BASEPATH/kernel</kernel>\n";
|
|
95 |
+ if ( $use_ramdisk ) {
|
|
96 |
+ print " <initrd>BASEPATH/ramdisk</initrd>\n";
|
|
97 |
+ }
|
|
98 |
+
|
|
99 |
+ if ( $use_virtio_root ) {
|
|
100 |
+ print " <cmdline>root=/dev/vda1 console=ttyS0</cmdline>\n"
|
|
101 |
+ } else {
|
|
102 |
+ print " <cmdline>root=/dev/sda1 console=ttyS0</cmdline>\n"
|
|
103 |
+ }
|
|
104 |
} |
|
105 |
||
106 |
print <<EOF; |
|
|
1062
by Scott Moser
work around kvm virtio bug with -kernel by using boot floppy LP: #615529 |
107 |
@@ -121,6 +137,15 @@
|
|
1054
by Scott Moser
Add support for booting multiboot images from a floppy (LP: #611144) |
108 |
<emulator>$local_kvm</emulator> |
109 |
EOF |
|
110 |
||
111 |
+if ( $multi_boot_floppy ) {
|
|
112 |
+ print <<EOF
|
|
113 |
+ <disk type='file' device='floppy'>
|
|
114 |
+ <source file='BASEPATH/loader'/>
|
|
115 |
+ <target dev='fda' bus='fdc'/>
|
|
116 |
+ </disk>
|
|
117 |
+EOF
|
|
118 |
+}
|
|
119 |
+
|
|
120 |
if ( $use_virtio_root ) {
|
|
121 |
print <<EOF; |
|
122 |
<disk type='file' device='disk'> |
|
|
1089
by Scott Moser
take the multiboot path only if kernel really is a multiboot |
123 |
@@ -163,3 +188,42 @@
|
|
1054
by Scott Moser
Add support for booting multiboot images from a floppy (LP: #611144) |
124 |
</devices> |
125 |
</domain> |
|
126 |
EOF |
|
127 |
+
|
|
|
1089
by Scott Moser
take the multiboot path only if kernel really is a multiboot |
128 |
+# This checks if a binary looks like a multiboot image
|
129 |
+# The check is similar to grub 0.97's mbchk and to kvm's multiboot
|
|
130 |
+# check in hw/multiboot.c:load_multiboot
|
|
|
1054
by Scott Moser
Add support for booting multiboot images from a floppy (LP: #611144) |
131 |
+sub is_multiboot_img
|
132 |
+{
|
|
|
1089
by Scott Moser
take the multiboot path only if kernel really is a multiboot |
133 |
+ my $kpath=$_[0];
|
134 |
+ my $buf;
|
|
135 |
+ my $found = 0;
|
|
136 |
+ my $header_magic = 0x1BADB002;
|
|
137 |
+ my $header_size = 32; # there are 8 uint32 values
|
|
138 |
+ my $search_bytes = 8192; # copied from kvm and grub's mbchk
|
|
139 |
+ my $magic = 0;
|
|
140 |
+ my $flags = 0;
|
|
141 |
+ my $checksum = 0;
|
|
142 |
+ my $count = 0;
|
|
143 |
+
|
|
144 |
+ if (! (-s $kpath)) { return(0); }
|
|
145 |
+ open INF, $kpath or return(0);
|
|
146 |
+ binmode INF;
|
|
147 |
+ if (!($count = read (INF, $buf, $search_bytes))) {
|
|
148 |
+ close INF;
|
|
149 |
+ return(0);
|
|
150 |
+ }
|
|
151 |
+ close INF;
|
|
152 |
+ for(my $i=0;$i < ($count - $header_size);$i=$i+4) {
|
|
153 |
+ if (unpack("V",substr($buf,$i,4)) == $header_magic ) {
|
|
154 |
+ $found=$i; last;
|
|
155 |
+ }
|
|
156 |
+ }
|
|
157 |
+
|
|
158 |
+ if ($found == 0) { return(0); }
|
|
|
1090
by Scott Moser
gen_kvm_libvirt_xml: fix incorrect length in substr argument |
159 |
+ ($magic,$flags,$checksum) = unpack("VVV",substr($buf,$found,4*3));
|
|
1089
by Scott Moser
take the multiboot path only if kernel really is a multiboot |
160 |
+ # magic + flags + checksum == (uint32) 0 == 2**32
|
|
1098
by Scott Moser
fix determination of 'is_multiboot'. |
161 |
+ if(($magic+$flags+$checksum) % 2**32 == 0 ) {
|
|
1089
by Scott Moser
take the multiboot path only if kernel really is a multiboot |
162 |
+ return(1);
|
163 |
+ }
|
|
164 |
+ return(0);
|
|
|
1054
by Scott Moser
Add support for booting multiboot images from a floppy (LP: #611144) |
165 |
+}
|
166 |
--- a/tools/Makefile
|
|
167 |
+++ b/tools/Makefile
|
|
168 |
@@ -47,6 +47,7 @@
|
|
169 |
@$(INSTALL) -m 755 connect_iscsitarget.pl $(DESTDIR)$(datarootdir)/eucalyptus |
|
170 |
@$(INSTALL) -m 755 disconnect_iscsitarget.pl $(DESTDIR)$(datarootdir)/eucalyptus |
|
171 |
@$(INSTALL) -m 755 get_iscsitarget.pl $(DESTDIR)$(datarootdir)/eucalyptus |
|
172 |
+ @$(INSTALL) -m 755 mk-mb-loader $(DESTDIR)$(datarootdir)/eucalyptus
|
|
173 |
||
174 |
uninstall: |
|
175 |
@$(RM) -f $(DESTDIR)$(etcdir)/init.d/eucalyptus-cloud |
|
176 |
@@ -68,4 +69,5 @@
|
|
177 |
@$(RM) -f $(DESTDIR)$(sbindir)/euca_conf |
|
178 |
@$(RM) -f $(DESTDIR)/etc/bash_completion.d/euca_conf |
|
179 |
@$(RM) -f $(DESTDIR)$(sbindir)/euca_sync_key |
|
180 |
+ @$(RM) -f $(DESTDIR)$(datarootdir)/eucalyptus/mk-mb-loader
|
|
181 |
||
182 |
--- /dev/null
|
|
183 |
+++ b/tools/mk-mb-loader
|
|
184 |
@@ -0,0 +1,113 @@
|
|
185 |
+#!/bin/sh
|
|
186 |
+# vi: ts=4 noexpandtab
|
|
187 |
+#
|
|
188 |
+# Copyright (C) 2010 Canonical Ltd.
|
|
189 |
+#
|
|
190 |
+# Authors: Scott Moser <smoser@canonical.com>
|
|
191 |
+#
|
|
192 |
+# This program is free software: you can redistribute it and/or modify
|
|
193 |
+# it under the terms of the GNU General Public License as published by
|
|
194 |
+# the Free Software Foundation, version 3 of the License.
|
|
195 |
+#
|
|
196 |
+# This program is distributed in the hope that it will be useful,
|
|
197 |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
198 |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
199 |
+# GNU General Public License for more details.
|
|
200 |
+#
|
|
201 |
+# You should have received a copy of the GNU General Public License
|
|
202 |
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
203 |
+
|
|
204 |
+TEMP_D=""
|
|
205 |
+
|
|
206 |
+error() { echo "$@" 1>&2; }
|
|
207 |
+fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
|
|
208 |
+Usage() {
|
|
209 |
+ cat <<EOF
|
|
210 |
+Usage: ${0##*/} loader.img output.img
|
|
211 |
+ Create a multiboot floppy image that will multiboot 'loader.img'
|
|
212 |
+ where loader.img is a multiboot complient loader
|
|
213 |
+
|
|
214 |
+ The output.img file can then be booted with
|
|
215 |
+ kvm -fda output.img -boot a -drive ...
|
|
216 |
+ and will load 'loader.img'
|
|
217 |
+EOF
|
|
218 |
+}
|
|
219 |
+bad_Usage() { Usage 1>&2; fail "$@"; }
|
|
220 |
+cleanup() {
|
|
221 |
+ [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
|
|
222 |
+}
|
|
223 |
+
|
|
224 |
+getsize() {
|
|
225 |
+ local f="$1" size=""
|
|
226 |
+ size=$(ls -l "${f}" 2>/dev/null | awk '{print $5}') &&
|
|
227 |
+ [ -n "${size}" ] && _RET=${size} && return 0
|
|
228 |
+}
|
|
229 |
+checksize() {
|
|
230 |
+ getsize "$1" || return 1
|
|
231 |
+ [ "${_RET}" "$2" "$3" ]
|
|
232 |
+}
|
|
233 |
+
|
|
234 |
+mk_grub_rescue() {
|
|
235 |
+ local input=${1} output=${2}
|
|
236 |
+ local bdir="${TEMP_D}/bdir"
|
|
237 |
+ local err="${TEMP_D}/err"
|
|
238 |
+ local modules="configfile"
|
|
239 |
+ local modules=""
|
|
240 |
+ mkdir "${bdir}" &&
|
|
241 |
+ mkdir -p "${bdir}/boot/grub" &&
|
|
242 |
+ cp "${input}" "${bdir}/boot/grub/loader.img" &&
|
|
243 |
+ cat > "${bdir}/boot/grub/grub.cfg" <<EOF
|
|
244 |
+multiboot /boot/grub/loader.img
|
|
245 |
+boot
|
|
246 |
+EOF
|
|
247 |
+ [ $? -eq 0 ] || return
|
|
248 |
+ grub-mkrescue --output="${output}" \
|
|
249 |
+ ${modules:+"--modules=${modules}"} "${bdir}" > "${err}" 2>&1 ||
|
|
250 |
+ { cat "${err}" 1>&2; return 1; }
|
|
251 |
+}
|
|
252 |
+
|
|
253 |
+short_opts="h"
|
|
254 |
+long_opts="help"
|
|
255 |
+getopt_out=$(getopt --name "${0##*/}" \
|
|
256 |
+ --options "${short_opts}" --long "${long_opts}" -- "$@") &&
|
|
257 |
+ eval set -- "${getopt_out}" ||
|
|
258 |
+ bad_Usage
|
|
259 |
+
|
|
260 |
+mode="grub-rescue-floppy"
|
|
261 |
+while [ $# -ne 0 ]; do
|
|
262 |
+ cur=${1}; next=${2};
|
|
263 |
+ case "$cur" in
|
|
264 |
+ -h|--help) Usage; exit 0;;
|
|
265 |
+ --) shift; break;;
|
|
266 |
+ esac
|
|
267 |
+ shift;
|
|
268 |
+done
|
|
269 |
+
|
|
270 |
+[ $# -eq 2 ] || bad_Usage "must multiboot loader input and output file"
|
|
271 |
+
|
|
272 |
+TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/.${0##*/}.XXXXXX") ||
|
|
273 |
+ fail "failed to make tempd"
|
|
274 |
+trap cleanup EXIT
|
|
275 |
+
|
|
276 |
+loader=${1}
|
|
277 |
+output=${2}
|
|
278 |
+
|
|
279 |
+case "${mode}" in
|
|
280 |
+ grub-rescue-floppy)
|
|
281 |
+ mk_grub_rescue "${loader}" "${output}" ||
|
|
282 |
+ fail "failed to make rescue floppy"
|
|
283 |
+ checksize "${output}" -lt $((2880*1024)) ||
|
|
284 |
+ fail "output of mk_rescue was to large for floppy"
|
|
285 |
+ size=${_RET}
|
|
286 |
+ truncate --size 2880K "${output}" ||
|
|
287 |
+ fail "failed to pad ${output} to 2880K"
|
|
288 |
+ echo "created ${mode} loader in ${output} (payload $size)"
|
|
289 |
+ ;;
|
|
290 |
+ grub-rescue-cdrom)
|
|
291 |
+ mk_grub_rescue "${loader}" "${output}" ||
|
|
292 |
+ fail "failed to make rescue cdrom"
|
|
293 |
+ echo "created ${mode} loader in ${output}"
|
|
294 |
+ ;;
|
|
295 |
+esac
|
|
296 |
+
|
|
297 |
+[ $? -eq 0 ] || fail "failed to create loader"
|