blob: 4e84dabd8f99fde93710ba65baa3c946646afae1 [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_HANDOFF_PREP_H_
#define ZIRCON_KERNEL_PHYS_HANDOFF_PREP_H_
#include <lib/trivial-allocator/basic-leaky-allocator.h>
#include <lib/trivial-allocator/new.h>
#include <lib/trivial-allocator/single-heap-allocator.h>
#include <lib/zbitl/image.h>
#include <zircon/boot/image.h>
#include <fbl/alloc_checker.h>
#include <ktl/byte.h>
#include <ktl/initializer_list.h>
#include <ktl/move.h>
#include <ktl/span.h>
#include <phys/handoff-ptr.h>
#include <phys/handoff.h>
#include <phys/zbitl-allocation.h>
struct BootOptions;
class PhysBootTimes;
class HandoffPrep {
public:
// TODO(fxbug.dev/84107): The first argument is the space inside the data ZBI
// where the ZBI_TYPE_STORAGE_KERNEL was, the only safe space to reuse for
// now. Eventually this function will just allocate from the memalloc::Pool
// using a type designated for handoff data so the kernel can decide if it
// wants to reuse the space after consuming all the data.
void Init(ktl::span<ktl::byte> handoff_payload);
// This is the main structure. After Init has been called the pointer is
// valid but the data is in default-constructed state.
PhysHandoff* handoff() { return handoff_; }
// This returns new T(args...) using the temporary handoff allocator and
// fills in the handoff_ptr to point to it.
template <typename T, typename... Args>
T* New(PhysHandoffTemporaryPtr<const T>& handoff_ptr, fbl::AllocChecker& ac, Args&&... args) {
T* ptr = new (allocator(), ac) T(ktl::forward<Args>(args)...);
if (ptr) {
void* generic_ptr = static_cast<void*>(ptr);
handoff_ptr.ptr_ = reinterpret_cast<uintptr_t>(generic_ptr);
}
return ptr;
}
// Similar but for new T[n] using spans instead of pointers.
template <typename T>
ktl::span<T> New(PhysHandoffTemporarySpan<const T>& handoff_span, fbl::AllocChecker& ac,
size_t n) {
T* ptr = new (allocator(), ac) T[n];
if (ptr) {
void* generic_ptr = static_cast<void*>(ptr);
handoff_span.ptr_.ptr_ = reinterpret_cast<uintptr_t>(generic_ptr);
handoff_span.size_ = n;
return {ptr, n};
}
return {};
}
// Fills in handoff()->boot_options and returns the mutable reference to
// update its fields later so that `.serial` can be transferred last.
BootOptions& SetBootOptions(const BootOptions& boot_options);
// Summarizes the provided data ZBI's miscellaneous simple items for the
// kernel, filling in corresponding handoff()->item fields.
// Certain fields, may be cleaned after consumption for security considerations,
// such as 'ZBI_TYPE_SECURE_ENTROPY'.
void SummarizeMiscZbiItems(ktl::span<ktl::byte> zbi);
// Add physboot's own instrumentation data to the handoff. After this, the
// live instrumented physboot code is updating the handoff data directly up
// through the very last compiled basic block that jumps into the kernel.
void SetInstrumentation();
private:
using AllocateFunction = trivial_allocator::SingleHeapAllocator;
using Allocator = trivial_allocator::BasicLeakyAllocator<AllocateFunction>;
struct Debugdata {
ktl::string_view announce, sink_name, vmo_name;
size_t size_bytes = 0;
};
// TODO(fxbug.dev/84107): Later this will just return
// gPhysNew<memalloc::Type::kPhysHandoff>.
Allocator& allocator() { return allocator_; }
void SaveForMexec(const zbi_header_t& header, ktl::span<const ktl::byte> payload);
// The arch-specific protocol for a given item.
// Defined in //zircon/kernel/arch/$cpu/phys/arch-handoff-prep-zbi.cc.
void ArchSummarizeMiscZbiItem(const zbi_header_t& header, ktl::span<const ktl::byte> payload);
void SetSymbolizerLog(ktl::initializer_list<Debugdata> dumps);
Allocator allocator_;
PhysHandoff* handoff_ = nullptr;
zbitl::Image<Allocation> mexec_image_;
};
#endif // ZIRCON_KERNEL_PHYS_HANDOFF_PREP_H_