Andrey Smirnov 33332f4c74 chore: support bootloader emulation in firecracker provisioner
Firecracker launches tries to open VM disk image before every boot,
parses partition table, finds boot partition, tries to read it as FAT32
filesystem, extracts uncompressed kernel from `bzImage` (firecracker
doesn't support `bzImage` yet), extracts initramfs and passes it to
firecracker binary.

This flow allows for extended tests, e.g. testing installer, upgrade and
downgrade tests, etc.

Bootloader emulation is disabled by default for now, can be enabled via
`--with-bootloader-emulation` flag to `osctl cluster create`.

Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
2020-02-13 23:21:37 +03:00

75 lines
1.7 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Package vmlinuz provides utilities for reading bzImage kernel format.
package vmlinuz
import (
"bytes"
"compress/bzip2"
"compress/gzip"
"fmt"
"io"
"io/ioutil"
"github.com/smira/go-xz"
)
type decompressFunc func(io.Reader) (io.ReadCloser, error)
// Based on https://github.com/torvalds/linux/blob/master/scripts/extract-vmlinux.
var bzImageMagic = []struct {
magic []byte
reader decompressFunc
}{
{
magic: []byte("\037\213\010"),
reader: func(r io.Reader) (io.ReadCloser, error) {
return gzip.NewReader(r)
},
},
{
magic: []byte("\3757zXZ\000"),
reader: func(r io.Reader) (io.ReadCloser, error) {
return xz.NewReader(r)
},
},
{
magic: []byte("BZh"),
reader: func(r io.Reader) (io.ReadCloser, error) {
return ioutil.NopCloser(bzip2.NewReader(r)), nil
},
},
}
// Decompress the bzImage Linux kernel format and extract vmlinux kernel.
//
// Only following formats are supported: gzip, xz and bzip2.
func Decompress(r io.Reader) (io.ReadCloser, error) {
// read first 64Kb and look for signature
head := make([]byte, 65536)
if _, err := io.ReadFull(r, head); err != nil {
return nil, fmt.Errorf("error reading 64Kb vmlinuz head: %w", err)
}
start := -1
var decompress decompressFunc
for _, matcher := range bzImageMagic {
start = bytes.Index(head, matcher.magic)
if start != -1 {
decompress = matcher.reader
break
}
}
if start == -1 {
return nil, fmt.Errorf("error looking for vmlinuz magic")
}
return decompress(io.MultiReader(bytes.NewReader(head[start:]), r))
}