blob: 7566dd89c2b8204a6b23be242dacac0f552f7d8b [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/devicetree/testing/loaded-dtb.h"
#include <lib/fit/defer.h>
#include <filesystem>
#include <string_view>
#ifndef __Fuchsia__
#include <libgen.h>
#include <unistd.h>
#endif // !__Fuchsia__
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
namespace devicetree::testing {
namespace {
// TODO: make the non-fuchsia part of this a general utility that can be shared
// across host-side tests.
std::filesystem::path GetResourcePath() {
std::filesystem::path path;
#if defined(__Fuchsia__)
path.append("/pkg");
#elif defined(__APPLE__)
uint32_t length = PATH_MAX;
char self_path[PATH_MAX];
char self_path_symlink[PATH_MAX];
_NSGetExecutablePath(self_path_symlink, &length);
const char* bin_dir = dirname(realpath(self_path_symlink, self_path));
path.append(bin_dir);
#elif defined(__linux__)
char self_path[PATH_MAX];
const char* bin_dir = dirname(realpath("/proc/self/exe", self_path));
path.append(bin_dir);
#else
#error unknown platform.
#endif
return path;
}
} // namespace
fit::result<std::string, LoadedDtb> LoadDtb(std::string_view dtb_file) {
std::filesystem::path resource_path = GetResourcePath().append(LIB_DEVICETREE_DATA).string();
resource_path.append(dtb_file);
FILE* file = fopen(resource_path.c_str(), "r");
if (!file) {
std::string err =
"Failed to open: " + std::string(resource_path.c_str()) + ": " + strerror(errno);
return fit::error(err);
}
auto close_file = fit::defer([file]() { fclose(file); });
if (fseek(file, 0, SEEK_END) != 0) {
std::string err = "Failed to seek to end of file : " + std::string(resource_path.c_str()) +
": " + strerror(errno);
return fit::error(err);
}
auto size = static_cast<size_t>(ftell(file));
LoadedDtb ldtb;
ldtb.dtb.resize(size);
rewind(file);
if (auto actual = fread(reinterpret_cast<char*>(ldtb.dtb.data()), 1, size, file);
actual != size) {
std::string err = "Failed to read file : " + std::string(resource_path.c_str()) + ". Read " +
std::to_string(actual) + " bytes of " + std::to_string(size);
return fit::error(err);
}
return fit::success(ldtb);
}
} // namespace devicetree::testing