// Copyright 2022 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 "phys/efi/file.h"

#include <zircon/assert.h>

#include <efi/protocol/file.h>
#include <efi/protocol/simple-file-system.h>
#include <fbl/alloc_checker.h>
#include <ktl/string_view.h>
#include <ktl/unique_ptr.h>
#include <phys/efi/main.h>
#include <phys/efi/protocol.h>
#include <phys/symbolize.h>

#include "src/lib/utf_conversion/utf_conversion.h"

#include <ktl/enforce.h>

template <>
constexpr const efi_guid& kEfiProtocolGuid<efi_simple_file_system_protocol> =
    SimpleFileSystemProtocol;

namespace {

ktl::unique_ptr<char16_t[]> ConvertUtf8ToUtf16CString(ktl::string_view utf8) {
  fbl::AllocChecker ac;
  ktl::unique_ptr<char16_t[]> utf16(new (&ac) char16_t[utf8.size() + 1]);
  if (!ac.check()) {
    return nullptr;
  }
  size_t len = utf8.size();

  zx_status_t status = utf8_to_utf16(reinterpret_cast<const uint8_t*>(utf8.data()), utf8.size(),
                                     reinterpret_cast<uint16_t*>(utf16.get()), &len);
  if (status != ZX_OK) {
    printf("%s: Error %d converting UTF8 file name \"%.*s\" to UTF16!\n", ProgramName(), status,
           static_cast<int>(utf8.size()), utf8.data());
    return nullptr;
  }
  ZX_ASSERT_MSG(len <= utf8.size(), "%zu UTF8 became %zu UTF16??", utf8.size(), len);
  utf16[len] = L'\0';
  return utf16;
}

}  // namespace

EfiFilePtr EfiRootDir() {
  if (!gEfiLoadedImage) {
    printf("%s: Cannot get EFI root filesystem without LOADED_IMAGE_PROTOCOL\n", ProgramName());
    return {};
  }
  auto fs = EfiOpenProtocol<efi_simple_file_system_protocol>(gEfiLoadedImage->DeviceHandle);
  if (fs.is_error()) {
    printf("%s: EFI error %#zx getting SIMPLE_FILE_SYSTEM_PROTOCOL\n", ProgramName(),
           fs.error_value());
  }

  efi_file_protocol* root = nullptr;
  efi_status status = fs->OpenVolume(fs.value().get(), &root);
  if (status != EFI_SUCCESS) {
    printf("%s: EFI error %#zx from OpenVolume", ProgramName(), status);
    return {};
  }

  return EfiFilePtr(root);
}

fitx::result<efi_status, uint64_t> EfiFileSize(efi_file_protocol* file) {
  union {
    efi_file_info info;
    char space[sizeof(efi_file_info) + sizeof(char16_t[255])];
  } buffer;
  size_t info_size = sizeof(buffer);
  efi_status status = file->GetInfo(file, &FileInfoGuid, &info_size, &buffer);
  if (status != EFI_SUCCESS) {
    return fitx::error{status};
  }
  ZX_ASSERT(info_size >= sizeof(buffer.info));
  return fitx::ok(buffer.info.FileSize);
}

fitx::result<efi_status, EfiFilePtr> EfiOpenFile(const char16_t* filename, efi_file_protocol* dir) {
  efi_file_protocol* file = nullptr;
  efi_status status = dir->Open(dir, &file, filename, EFI_FILE_MODE_READ, 0);
  if (status != EFI_SUCCESS) {
    return fitx::error{status};
  }
  return fitx::ok(EfiFilePtr(file));
}

fitx::result<efi_status, EfiFilePtr> EfiOpenFile(ktl::string_view filename,
                                                 efi_file_protocol* dir) {
  ktl::unique_ptr<char16_t[]> utf16 = ConvertUtf8ToUtf16CString(filename);
  if (!utf16) {
    return fitx::error{EFI_OUT_OF_RESOURCES};
  }
  return EfiOpenFile(utf16.get(), dir);
}
