// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "smbios.h"

#include <lib/fzl/owned-vmo-mapper.h>
#include <lib/smbios/smbios.h>
#include <lib/zx/resource.h>
#include <lib/zx/vmar.h>
#include <lib/zx/vmo.h>
#include <limits.h>

#include <ddk/driver.h>
#include <fbl/algorithm.h>

namespace {

// Map the structure with the given physical address and length.  Neither needs
// to be page-aligned.
zx_status_t MapStructure(const zx::resource& resource, zx_paddr_t paddr, size_t length,
                         fzl::OwnedVmoMapper* mapping, uintptr_t* offsetted_start) {
  zx_paddr_t base_paddr = fbl::round_down<zx_paddr_t>(paddr, static_cast<zx_paddr_t>(PAGE_SIZE));
  zx::vmo vmo;
  size_t page_offset = paddr - base_paddr;
  size_t mapping_size = fbl::round_up<size_t>(length + page_offset, static_cast<size_t>(PAGE_SIZE));
  zx_status_t status = zx::vmo::create_physical(resource, base_paddr, mapping_size, &vmo);
  if (status != ZX_OK) {
    return status;
  }

  fzl::OwnedVmoMapper new_mapping;
  status = new_mapping.Map(std::move(vmo), mapping_size, ZX_VM_PERM_READ);
  if (status != ZX_OK) {
    return status;
  }
  *mapping = std::move(new_mapping);
  *offsetted_start = reinterpret_cast<uintptr_t>(mapping->start()) + page_offset;
  return ZX_OK;
}

// Structure for handling the lifetime of the SMBIOS mappings
class SmbiosState {
 public:
  SmbiosState() = default;
  ~SmbiosState() = default;

  // Must only be invoked once on an instance.  On success, |entry_point()|
  // and |struct_table_mapping()| are usable.  |entry_point()| will be
  // guaranteed to be a valid SMBIOS entry point structure.
  zx_status_t LoadFromFirmware();

  // These values are only valid as long as the instance is around.
  const smbios::EntryPoint2_1* entry_point() const { return entry_point_; }
  uintptr_t struct_table_start() const { return struct_table_start_; }

 private:
  fzl::OwnedVmoMapper entry_point_mapping_;
  fzl::OwnedVmoMapper struct_table_mapping_;

  const smbios::EntryPoint2_1* entry_point_ = nullptr;
  uintptr_t struct_table_start_ = 0;
};

zx_status_t SmbiosState::LoadFromFirmware() {
  // Please do not use get_root_resource() in new code. See fxbug.dev/31358.
  zx::unowned_resource root_resource(get_root_resource());

  zx_paddr_t acpi_rsdp, smbios_ep;
  zx_status_t status = zx_pc_firmware_tables(root_resource->get(), &acpi_rsdp, &smbios_ep);
  if (status != ZX_OK) {
    return status;
  }

  if (smbios_ep == 0) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  // Map the entry point and see how much data we have
  fzl::OwnedVmoMapper ep_mapping;
  uintptr_t ep_start;
  status = MapStructure(*root_resource, smbios_ep, PAGE_SIZE, &ep_mapping, &ep_start);
  if (status != ZX_OK) {
    return status;
  }

  auto ep = reinterpret_cast<const smbios::EntryPoint2_1*>(ep_start);
  if (!ep->IsValid()) {
    return ZX_ERR_IO_DATA_INTEGRITY;
  }

  // Map the struct table
  fzl::OwnedVmoMapper struct_table_mapping;
  uintptr_t struct_table_start;
  status = MapStructure(*root_resource, ep->struct_table_phys, ep->struct_table_length,
                        &struct_table_mapping, &struct_table_start);
  if (status != ZX_OK) {
    return status;
  }

  entry_point_mapping_ = std::move(ep_mapping);
  struct_table_mapping_ = std::move(struct_table_mapping);
  entry_point_ = ep;
  struct_table_start_ = struct_table_start;
  return ZX_OK;
}

}  // namespace

bool smbios_product_name_is_valid(const char* product_name) {
  if (product_name == nullptr || !strcmp(product_name, "<null>") || strlen(product_name) == 0) {
    return false;
  }
  // Check if the product name is all spaces (seen on some devices)
  const size_t product_name_len = strlen(product_name);
  bool nonspace_found = false;
  for (size_t i = 0; i < product_name_len; ++i) {
    if (product_name[i] != ' ') {
      nonspace_found = true;
      break;
    }
  }

  if (!nonspace_found) {
    return false;
  }

  return true;
}

zx_status_t SmbiosInfo::Load() {
  SmbiosState smbios;
  zx_status_t status = smbios.LoadFromFirmware();
  if (status != ZX_OK) {
    return status;
  }

  auto callback = [this](smbios::SpecVersion version, const smbios::Header* h,
                         const smbios::StringTable& st) -> zx_status_t {
    const char* name;
    switch (h->type) {
      case smbios::StructType::BiosInfo: {
        if (!version.IncludesVersion(2, 0)) {
          break;
        }
        auto entry = reinterpret_cast<const smbios::BiosInformationStruct2_0*>(h);
        zx_status_t status = st.GetString(entry->vendor_str_idx, &name);
        if (status == ZX_OK) {
          vendor_ = name;
        }
        break;
      }
      case smbios::StructType::SystemInfo: {
        if (!version.IncludesVersion(2, 0)) {
          break;
        }
        auto entry = reinterpret_cast<const smbios::SystemInformationStruct2_0*>(h);
        zx_status_t status = st.GetString(entry->product_name_str_idx, &name);
        if (status == ZX_OK && smbios_product_name_is_valid(name)) {
          board_name_ = name;
        }
        break;
      }
      case smbios::StructType::Baseboard: {
        auto entry = reinterpret_cast<const smbios::BaseboardInformationStruct*>(h);
        zx_status_t status = st.GetString(entry->product_name_str_idx, &name);
        if (status == ZX_OK && smbios_product_name_is_valid(name)) {
          board_name_ = name;
        }
        break;
      }
      default:
        break;
    }
    return ZX_OK;
  };
  return smbios.entry_point()->WalkStructs(smbios.struct_table_start(), callback);
}
