blob: 6937a8b2fd0ecb608deb3031d3ff1578dafeda67 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#ifndef ZIRCON_KERNEL_PHYS_BOOT_ZBI_H_
#define ZIRCON_KERNEL_PHYS_BOOT_ZBI_H_
#include <lib/fitx/result.h>
#include <lib/zbitl/image.h>
#include <lib/zbitl/view.h>
#include <zircon/boot/image.h>
#include <cstdint>
#include <ktl/span.h>
// This class manages loading a ZBI kernel and its data ZBI into memory and
// booting it. The caller first uses BootZbi::GetSizes() to determine the
// minimum physical memory required and does its own allocations; the caller
// can increase its allocation for the data ZBI if it needs to add items. Then
// a BootZbi object is primed with the Load() call, which fills in the memory
// just allocated with the kernel and data ZBI images from the incoming ZBI.
// The caller then has the opportunity to amend the data ZBI via the data()
// accessor, and finally it calls Boot() to transfer control to the ZBI kernel.
class BootZbi {
public:
using Bytes = ktl::span<std::byte>;
using InputZbi = zbitl::PermissiveView<zbitl::ByteView>;
using Zbi = zbitl::PermissiveImage<Bytes>;
using Error = InputZbi::CopyError<Bytes>;
struct Size {
size_t size, alignment;
};
struct Sizes {
Size kernel, data;
};
BootZbi() = default;
BootZbi(const BootZbi&) = default;
// Use GetSizes(), below, to compute required sizes and alignments to
// allocate. The BootZbi object does not take ownership of the buffers.
// Their data can be safely left uninitialized.
BootZbi(Bytes kernel, Bytes data) : kernel_(kernel), data_(data) {}
// Take the ZBI from the boot loader and compute the minimum sizes and
// alignments that must be allocated to hold the kernel and the data ZBI.
// The data.size can be increased before use if appending additional items.
// If the kernel.size is zero, then Load() can reuse the input ZBI memory.
static fitx::result<Error, Sizes> GetSizes(InputZbi zbi);
// Suggest allocation parameters for a whole bootable ZBI image whose
// incoming size is known but whose contents haven't been seen yet. A
// conforming allocation will be optimal for reuse by Load().
static Size SuggestedAllocation(uint32_t zbi_size_bytes);
// Split the ZBI from the boot loader into the kernel and data ZBIs using the
// space allocated for each. If data.size() > GetSizes(zbi)->data.size then
// data().Append and .Extend can be used to add items to the data ZBI later.
// If created with an empty kernel buffer, Boot() will reuse zbi.storage()
// directly instead of copying the kernel. Otherwise, zbi is no longer
// referenced after Load().
fitx::result<Error> Load(InputZbi zbi);
// This can be used after successful Load() to modify the data ZBI.
Zbi& data() { return data_; }
// Boot into the kernel loaded by Load(), which must have been called first.
// This cannot fail and never returns.
[[noreturn]] void Boot();
private:
Zbi kernel_, data_;
};
#endif // ZIRCON_KERNEL_PHYS_BOOT_ZBI_H_