blob: 3b722f9c77b4e68ce2c7a2e2cc33bb00cfe29a2a [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
#include <lib/boot-options/boot-options.h>
#include <lib/boot-shim/devicetree-boot-shim.h>
#include <lib/boot-shim/devicetree.h>
#include <lib/boot-shim/pool-mem-config.h>
#include <lib/boot-shim/uart.h>
#include <lib/zbi-format/board.h>
#include <lib/zbitl/view.h>
#include <stdint.h>
#include <stdlib.h>
#include <zircon/assert.h>
#include <zircon/compiler.h>
#include <fbl/alloc_checker.h>
#include <ktl/align.h>
#include <ktl/span.h>
#include <ktl/string_view.h>
#include <phys/address-space.h>
#include <phys/allocation.h>
#include <phys/arch/arch-phys-info.h>
#include <phys/boot-shim/devicetree.h>
#include <phys/boot-zbi.h>
#include <phys/main.h>
#include <phys/new.h>
#include <phys/stdio.h>
#include <phys/symbolize.h>
#include <phys/uart.h>
#include <ktl/enforce.h>
namespace {
using PlatformIdItem = boot_shim::SingleOptionalItem<zbi_platform_id_t, ZBI_TYPE_PLATFORM_ID>;
using BoardInfoItem = boot_shim::SingleOptionalItem<zbi_board_info_t, ZBI_TYPE_DRV_BOARD_INFO>;
constexpr const char* kShimName = "linux-riscv64-boot-shim";
// TODO(https://fxbug.dev/295031359): Once assembly generates this items, remove the hardcoded pair.
constexpr zbi_platform_id_t kQemuPlatformId = {
.vid = 1, // fuchsia.platform.BIND_PLATFORM_DEV_VID.QEMU
.pid = 1, // fuchsia.platform.BIND_PLATFORM_DEV_PID.QEMU
.board_name = "qemu-riscv64",
};
constexpr zbi_board_info_t kQemuBoardInfo = {
.revision = 0x1,
};
struct BootHartIdGetter {
static uint64_t Get() {
ZX_DEBUG_ASSERT(gArchPhysInfo);
return gArchPhysInfo->boot_hart_id;
}
};
} // namespace
void PhysMain(void* fdt, arch::EarlyTicks ticks) {
InitStdout();
ApplyRelocations();
// Set up gArchPhysInfo as early as possible, as the boot hart ID needs to
// be supplied to the CPU topology devicetree matcher.
ArchSetUp(nullptr);
AddressSpace aspace;
InitMemory(fdt, &aspace);
MainSymbolize symbolize(kShimName);
// Memory has been initialized, we can finish up parsing the rest of the items from the boot shim.
boot_shim::DevicetreeBootShim<boot_shim::UartItem<>, boot_shim::PoolMemConfigItem,
boot_shim::RiscvDevicetreePlicItem,
boot_shim::RiscvDevicetreeTimerItem,
boot_shim::RiscvDevicetreeCpuTopologyItem<BootHartIdGetter>,
boot_shim::DevicetreeDtbItem, PlatformIdItem, BoardInfoItem>
shim(kShimName, gDevicetreeBoot.fdt);
shim.set_allocator([](size_t size, size_t align, fbl::AllocChecker& ac) -> void* {
return new (ktl::align_val_t{align}, gPhysNew<memalloc::Type::kPhysScratch>, ac) uint8_t[size];
});
shim.set_cmdline(gDevicetreeBoot.cmdline);
shim.Get<boot_shim::UartItem<>>().Init(GetUartDriver().uart());
shim.Get<boot_shim::PoolMemConfigItem>().Init(Allocation::GetPool());
shim.Get<boot_shim::DevicetreeDtbItem>().set_payload(ktl::as_bytes(gDevicetreeBoot.fdt.fdt()));
shim.Get<PlatformIdItem>().set_payload(kQemuPlatformId);
shim.Get<BoardInfoItem>().set_payload(kQemuBoardInfo);
// Fill DevicetreeItems.
ZX_ASSERT(shim.Init());
// Finally we can boot into the kernel image.
BootZbi::InputZbi zbi_view(gDevicetreeBoot.ramdisk);
BootZbi boot;
if (shim.Check("Not a bootable ZBI", boot.Init(zbi_view)) &&
shim.Check("Failed to load ZBI", boot.Load(static_cast<uint32_t>(shim.size_bytes()))) &&
shim.Check("Failed to append boot loader items to data ZBI",
shim.AppendItems(boot.DataZbi()))) {
boot.Log();
boot.Boot();
}
abort();
}