blob: c26e8080b3326d475ab45dab14b78160e663e431 [file] [log] [blame]
// Copyright 2023 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_PHYSLOAD_H_
#define ZIRCON_KERNEL_PHYS_PHYSLOAD_H_
// This is the API for a phys module loaded by physload. A module is built for
// this using a kernel_elf_binary() GN target (see kernel_elf_binary.gni) that
// has //zircon/kernel/phys:physload.module in its deps list. That target goes
// into the deps list of a kernel_package() target, and should be paired with a
// kernel_cmdline() target with `args = [ "kernel.phys.next=..." ]` matching
// the name of the binary's path in the kernel package, both in deps of some
// zbi() target to produce a bootable image. (The cmdline is not needed for
// physboot itself, since it's the default for the boot option.)
//
// The physload ELF loader does simple-fixup relocation only, not symbolic
// dynamic linking. The loaded module shares some code with physload, but only
// via function pointers such as the one inside the FILE object. They share
// much more than that in data structures, but with separately-linked code to
// access them. To ensure they always have matching code for each other's data
// structures, the `:physload.module` dependency sets a PT_INTERP string in the
// ELF module that is matched at runtime against physload's build ID: each
// module is built to go with a single physload binary that can load it.
//
// The module's ELF entry point must match the PhysLoadHandoffFunction type
// signature. Linking it with `ldflags = [ "-Wl,-e,PhysLoadHandoff" ]` is the
// recommended way, so that this header file provides a declaration against
// which the definition can be checked at compile time. The entry point
// function must not return. It gets all the essential phys environment
// pointers for the state that physload has already set up. The ElfImage for
// the module just entered can be found at `symbolize->modules().back()`.
#include <stdio.h>
#include <phys/handoff.h>
#include <phys/kernel-package.h>
#include <phys/uart.h>
class AddressSpace;
struct ArchPhysInfo;
struct BootOptions;
class ElfImage;
class Log;
class MainSymbolize;
namespace memalloc {
class Pool;
} // namespace memalloc
using PhysLoadHandoffFunction =
void(ElfImage& self, // The module just handed off to.
Log* log, // Set gLog to this.
ArchPhysInfo* arch_phys, // Set gArchPhysInfo to this.
UartDriver& uart, // From GetUartDriver().
MainSymbolize* symbolize, // Set gSymbolize to this.
const BootOptions* boot_options, // Set gBootOptions to this.
memalloc::Pool& allocation_pool, // Pass to Pool::InitWithPool.
AddressSpace* aspace, // Set gAddressSpace to this.
PhysBootTimes boot_times, // TODO(mcgrathr): more time points
KernelStorage kernel_storage);
// The loaded module is linked with -W,-e,... to make this the entry symbol.
extern "C" [[noreturn]] PhysLoadHandoffFunction PhysLoadHandoff;
// PhysLoadHandoff calls PhysLoadModuleMain after initializing all the global
// variables that hold the rest of the state handed off.
extern "C" [[noreturn]] void PhysLoadModuleMain(UartDriver& uart, PhysBootTimes boot_times,
KernelStorage kernel_storage);
// This should be run early in the handoff function to reinitialize
// arch-specific state that's not included in the handoff data.
// PhysLoadHandoff calls it before PhysLoadModuleMain.
void ArchOnPhysLoadHandoff();
#endif // ZIRCON_KERNEL_PHYS_PHYSLOAD_H_