// 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

#include <inttypes.h>
#include <lib/arch/zbi-boot.h>
#include <lib/boot-options/boot-options.h>
#include <lib/boot-options/word-view.h>
#include <lib/zbitl/error_stdio.h>
#include <lib/zbitl/view.h>
#include <stdio.h>
#include <zircon/assert.h>

#include <ktl/array.h>
#include <ktl/optional.h>
#include <phys/allocation.h>
#include <phys/boot-zbi.h>
#include <phys/main.h>
#include <phys/symbolize.h>
#include <phys/zbitl-allocation.h>
#include <pretty/cpp/sizes.h>

const char Symbolize::kProgramName_[] = "physboot";

namespace {

// The boot_alloc code uses arbitrary pages after the official bss space.
// So make sure to allocate some extra slop for the kernel.
constexpr uint64_t kKernelBootAllocReserve = 1024 * 1024 * 4;

// A guess about the upper bound on reserve_memory_size so we can do a single
// allocation before decoding the header and probably not need to relocate.
constexpr uint64_t kKernelBssEstimate = 1024 * 1024 * 2;

struct LoadedZircon {
  Allocation buffer;
  BootZbi boot;
  arch::EarlyTicks decompress_ts;
};

LoadedZircon LoadZircon(BootZbi::InputZbi& zbi, BootZbi::InputZbi::iterator kernel_item,
                        uint64_t reserve_memory_estimate) {
  fbl::AllocChecker ac;
  const auto kernel_length = zbitl::UncompressedLength(*(*kernel_item).header);
  auto buffer_sizes = BootZbi::SuggestedAllocation(kernel_length);

  // That covers the uncompressed size of the image alone.  Preallocate enough
  // space after it that the bss and boot_alloc reserve are likely to fit.
  buffer_sizes.size += reserve_memory_estimate + kKernelBootAllocReserve;

  auto buffer = Allocation::New(ac, buffer_sizes.size, buffer_sizes.alignment);
  if (!ac.check()) {
    printf(
        "physboot: Cannot allocate %#zx bytes aligned to %#zx for decompressed kernel payload!\n",
        buffer_sizes.size, buffer_sizes.alignment);
    abort();
  }

  if (auto result = zbi.CopyStorageItem(buffer.data(), kernel_item, ZbitlScratchAllocator);
      result.is_error()) {
    printf("physboot: Cannot load STORAGE_KERNEL item (uncompressed size %#x): ", kernel_length);
    zbitl::PrintViewCopyError(result.error_value());
    abort();
  }

  auto decompress_ts = arch::EarlyTicks::Get();

  BootZbi::InputZbi kernel_zbi(zbitl::AsBytes(buffer.data()));

  {
    printf("physboot: STORAGE_KERNEL decompressed %s -> %s\n",
           FormattedSize((*kernel_item).header->length).str(),
           FormattedSize(kernel_zbi.size_bytes()).str());
  }

  BootZbi boot;
  if (auto result = boot.Init(kernel_zbi); result.is_error()) {
    printf("physboot: Cannot read STORAGE_KERNEL item ZBI: ");
    zbitl::PrintViewCopyError(result.error_value());
    abort();
  }

  return {std::move(buffer), std::move(boot), decompress_ts};
}

[[noreturn]] void BootZircon(BootZbi::InputZbi& zbi, BootZbi::InputZbi::iterator kernel_item,
                             arch::EarlyTicks entry_ts) {
  auto zircon = LoadZircon(zbi, kernel_item, kKernelBssEstimate);
  if (!zircon.boot.KernelCanLoadInPlace() ||
      zircon.buffer.size_bytes() < zircon.boot.KernelMemorySize() + kKernelBootAllocReserve) {
    printf("physboot: Kernel ZBI at %#" PRIx64 " cannot be loaded in place!\n",
           zircon.boot.KernelLoadAddress());
    uint64_t bss_size = zircon.boot.KernelHeader()->reserve_memory_size;
    printf("physboot: BSS size %#" PRIx64 " > estimate %#" PRIx64 "\n", bss_size,
           kKernelBssEstimate);
    ZX_ASSERT(bss_size > kKernelBssEstimate);
    zircon = {};  // Free old resources.
    printf("physboot: Repeating decompression with larger buffer...\n");
    zircon = LoadZircon(zbi, kernel_item, bss_size);
  }
  auto& [buffer, boot, decompress_ts] = zircon;

  ZX_ASSERT(boot.KernelCanLoadInPlace());
  ZX_ASSERT_MSG(buffer.size_bytes() >= boot.KernelMemorySize() + kKernelBootAllocReserve,
                "Kernel allocation %#zx too small for load size %#x +"
                " bss %#" PRIx64 " + boot_alloc reserve %#" PRIx64 "\n",
                buffer.size_bytes(), boot.KernelLoadSize(),
                boot.KernelHeader()->reserve_memory_size, kKernelBootAllocReserve);

  // TODO(mcgrathr): propagate timestamps

  // The kernel is now in place, but it will just use the original data ZBI.
  boot.DataZbi().storage() = {
      const_cast<std::byte*>(zbi.storage().data()),
      zbi.storage().size(),
  };

  printf("physboot: Kernel @ [0x%016" PRIxPTR ", 0x%016" PRIxPTR ")  %s\n",
         boot.KernelLoadAddress(), boot.KernelLoadAddress() + boot.KernelLoadSize(),
         FormattedSize(boot.KernelLoadSize()).str());
  printf("physboot:  Entry @  0x%016" PRIxPTR "\n", boot.KernelEntryAddress());
  printf("physboot:    BSS @ [0x%016" PRIxPTR ", 0x%016" PRIxPTR ")  %s\n",
         boot.KernelLoadAddress() + boot.KernelLoadSize(),
         boot.KernelLoadAddress() + boot.KernelMemorySize(),
         FormattedSize(boot.KernelHeader()->reserve_memory_size).str());
  printf("physboot: ZBI    @ [0x%016" PRIxPTR ", 0x%016" PRIxPTR ")  %s\n", boot.DataLoadAddress(),
         boot.DataLoadAddress() + boot.DataLoadSize(), FormattedSize(boot.DataLoadSize()).str());

  boot.Boot();
}

// TODO(fxbug.dev/53593): BootOptions already parsed and redacted, so put it
// back.
void UnredactEntropyMixin(zbitl::ByteView payload) {
  constexpr ktl::string_view kPrefix = "kernel.entropy-mixin=";
  if (gBootOptions->entropy_mixin.len > 0) {
    ktl::string_view cmdline{
        reinterpret_cast<const char*>(payload.data()),
        payload.size(),
    };
    for (auto word : WordView(cmdline)) {
      if (word.starts_with(kPrefix)) {
        word.remove_prefix(kPrefix.size());
        memcpy(const_cast<char*>(word.data()), gBootOptions->entropy_mixin.hex.data(),
               std::min(gBootOptions->entropy_mixin.len, word.size()));
        gBootOptions->entropy_mixin = {};
        break;
      }
    }
  }
}

[[noreturn]] void BadZbi(BootZbi::InputZbi zbi, size_t count,
                         ktl::optional<BootZbi::InputZbi::Error> error) {
  printf("physboot: Invalid ZBI of %zu bytes, %zu items: ", zbi.size_bytes(), count);

  if (error) {
    zbitl::PrintViewError(*error);
    printf("\n");
  } else {
    printf("No STORAGE_KERNEL item found!\n");
  }

  for (auto [header, payload] : zbi) {
    auto name = zbitl::TypeName(header->type);
    if (name.empty()) {
      name = "unknown!";
    }
    printf(
        "\
physboot: Item @ %#08x size %#08x type %#08x (%.*s) extra %#08x flags %#08x\n",
        static_cast<uint32_t>(payload.data() - zbi.storage().data()), header->length, header->type,
        static_cast<int>(name.size()), name.data(), header->extra, header->flags);
  }
  zbi.ignore_error();
  abort();
}

}  // namespace

void ZbiMain(void* zbi_ptr, arch::EarlyTicks ticks) {
  Symbolize::GetInstance()->Context();

  InitMemory(zbi_ptr);

  auto zbi_header = static_cast<const zbi_header_t*>(zbi_ptr);
  BootZbi::InputZbi zbi(zbitl::StorageFromRawHeader(zbi_header));

  BootZbi::InputZbi::iterator kernel_item = zbi.end();
  size_t count = 0;
  for (auto it = zbi.begin(); it != zbi.end(); ++it) {
    ++count;
    auto [header, payload] = *it;
    switch (header->type) {
      case ZBI_TYPE_STORAGE_KERNEL:
        kernel_item = it;
        break;
      case ZBI_TYPE_CMDLINE:
        UnredactEntropyMixin(payload);
        break;
    }
  }

  if (auto result = zbi.take_error(); result.is_error()) {
    BadZbi(zbi, count, result.error_value());
  }

  if (kernel_item == zbi.end()) {
    BadZbi(zbi, count, ktl::nullopt);
  }

  // TODO(mcgrathr): Bloat the binary so the total kernel.zbi size doesn't
  // get too comfortably small while physboot functionality is still growing.
  static const ktl::array<char, 512 * 1024> kPad{1};
  __asm__ volatile("" ::"m"(kPad), "r"(kPad.data()));

  BootZircon(zbi, kernel_item, ticks);
}
