blob: 4da1f3e4f5b3d1a1df5319cbf49fbf52a29ec73f [file] [log] [blame]
#include <fidl/my.config.lib/cpp/fidl.h>
#include <lib/zx/vmo.h>
#include <zircon/assert.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <iostream>
#include <string>
#include <vector>
#include "cpp_elf_config_lib.h"
namespace cpp_elf_config_lib {
void Config::RecordInspect(inspect::Node* node) const {
node->RecordBool("my_flag", this->my_flag());
node->RecordInt("my_int16", this->my_int16());
node->RecordInt("my_int32", this->my_int32());
node->RecordInt("my_int64", this->my_int64());
node->RecordInt("my_int8", this->my_int8());
node->RecordString("my_string", this->my_string());
node->RecordUint("my_uint16", this->my_uint16());
node->RecordUint("my_uint32", this->my_uint32());
node->RecordUint("my_uint64", this->my_uint64());
node->RecordUint("my_uint8", this->my_uint8());
auto my_vector_of_flag_array_ = node->CreateUintArray(
"my_vector_of_flag", this->my_vector_of_flag().size());
for (size_t i = 0; i < this->my_vector_of_flag().size(); i++) {
my_vector_of_flag_array_.Set(i, this->my_vector_of_flag()[i]);
}
node->Record(std::move(my_vector_of_flag_array_));
auto my_vector_of_int16_array_ = node->CreateIntArray(
"my_vector_of_int16", this->my_vector_of_int16().size());
for (size_t i = 0; i < this->my_vector_of_int16().size(); i++) {
my_vector_of_int16_array_.Set(i, this->my_vector_of_int16()[i]);
}
node->Record(std::move(my_vector_of_int16_array_));
auto my_vector_of_int32_array_ = node->CreateIntArray(
"my_vector_of_int32", this->my_vector_of_int32().size());
for (size_t i = 0; i < this->my_vector_of_int32().size(); i++) {
my_vector_of_int32_array_.Set(i, this->my_vector_of_int32()[i]);
}
node->Record(std::move(my_vector_of_int32_array_));
auto my_vector_of_int64_array_ = node->CreateIntArray(
"my_vector_of_int64", this->my_vector_of_int64().size());
for (size_t i = 0; i < this->my_vector_of_int64().size(); i++) {
my_vector_of_int64_array_.Set(i, this->my_vector_of_int64()[i]);
}
node->Record(std::move(my_vector_of_int64_array_));
auto my_vector_of_int8_array_ = node->CreateIntArray(
"my_vector_of_int8", this->my_vector_of_int8().size());
for (size_t i = 0; i < this->my_vector_of_int8().size(); i++) {
my_vector_of_int8_array_.Set(i, this->my_vector_of_int8()[i]);
}
node->Record(std::move(my_vector_of_int8_array_));
auto my_vector_of_string_array_ = node->CreateStringArray(
"my_vector_of_string", this->my_vector_of_string().size());
for (size_t i = 0; i < this->my_vector_of_string().size(); i++) {
auto ref = std::string_view(this->my_vector_of_string()[i].data());
my_vector_of_string_array_.Set(i, ref);
}
node->Record(std::move(my_vector_of_string_array_));
auto my_vector_of_uint16_array_ = node->CreateUintArray(
"my_vector_of_uint16", this->my_vector_of_uint16().size());
for (size_t i = 0; i < this->my_vector_of_uint16().size(); i++) {
my_vector_of_uint16_array_.Set(i, this->my_vector_of_uint16()[i]);
}
node->Record(std::move(my_vector_of_uint16_array_));
auto my_vector_of_uint32_array_ = node->CreateUintArray(
"my_vector_of_uint32", this->my_vector_of_uint32().size());
for (size_t i = 0; i < this->my_vector_of_uint32().size(); i++) {
my_vector_of_uint32_array_.Set(i, this->my_vector_of_uint32()[i]);
}
node->Record(std::move(my_vector_of_uint32_array_));
auto my_vector_of_uint64_array_ = node->CreateUintArray(
"my_vector_of_uint64", this->my_vector_of_uint64().size());
for (size_t i = 0; i < this->my_vector_of_uint64().size(); i++) {
my_vector_of_uint64_array_.Set(i, this->my_vector_of_uint64()[i]);
}
node->Record(std::move(my_vector_of_uint64_array_));
auto my_vector_of_uint8_array_ = node->CreateUintArray(
"my_vector_of_uint8", this->my_vector_of_uint8().size());
for (size_t i = 0; i < this->my_vector_of_uint8().size(); i++) {
my_vector_of_uint8_array_.Set(i, this->my_vector_of_uint8()[i]);
}
node->Record(std::move(my_vector_of_uint8_array_));
}
std::string Config::ToString() const noexcept {
std::string str;
str.reserve(4096); // minimize reallocations
if (my_flag()) {
str += "my_flag; ";
}
str += "my_int16=";
str += std::to_string(my_int16());
str += "; ";
str += "my_int32=";
str += std::to_string(my_int32());
str += "; ";
str += "my_int64=";
str += std::to_string(my_int64());
str += "; ";
str += "my_int8=";
str += std::to_string(my_int8());
str += "; ";
str += "my_string=";
str += my_string();
str += "; ";
str += "my_uint16=";
str += std::to_string(my_uint16());
str += "; ";
str += "my_uint32=";
str += std::to_string(my_uint32());
str += "; ";
str += "my_uint64=";
str += std::to_string(my_uint64());
str += "; ";
str += "my_uint8=";
str += std::to_string(my_uint8());
str += "; ";
str += "my_vector_of_flag: [";
for (auto iter = my_vector_of_flag().begin();
iter != my_vector_of_flag().end(); iter++) {
if (iter != my_vector_of_flag().begin()) str += ", ";
str += std::to_string(*iter);
}
str += "]";
str += "my_vector_of_int16: [";
for (auto iter = my_vector_of_int16().begin();
iter != my_vector_of_int16().end(); iter++) {
if (iter != my_vector_of_int16().begin()) str += ", ";
str += std::to_string(*iter);
}
str += "]";
str += "my_vector_of_int32: [";
for (auto iter = my_vector_of_int32().begin();
iter != my_vector_of_int32().end(); iter++) {
if (iter != my_vector_of_int32().begin()) str += ", ";
str += std::to_string(*iter);
}
str += "]";
str += "my_vector_of_int64: [";
for (auto iter = my_vector_of_int64().begin();
iter != my_vector_of_int64().end(); iter++) {
if (iter != my_vector_of_int64().begin()) str += ", ";
str += std::to_string(*iter);
}
str += "]";
str += "my_vector_of_int8: [";
for (auto iter = my_vector_of_int8().begin();
iter != my_vector_of_int8().end(); iter++) {
if (iter != my_vector_of_int8().begin()) str += ", ";
str += std::to_string(*iter);
}
str += "]";
str += "my_vector_of_string: [";
for (auto iter = my_vector_of_string().begin();
iter != my_vector_of_string().end(); iter++) {
if (iter != my_vector_of_string().begin()) str += ", ";
str += *iter;
}
str += "]";
str += "my_vector_of_uint16: [";
for (auto iter = my_vector_of_uint16().begin();
iter != my_vector_of_uint16().end(); iter++) {
if (iter != my_vector_of_uint16().begin()) str += ", ";
str += std::to_string(*iter);
}
str += "]";
str += "my_vector_of_uint32: [";
for (auto iter = my_vector_of_uint32().begin();
iter != my_vector_of_uint32().end(); iter++) {
if (iter != my_vector_of_uint32().begin()) str += ", ";
str += std::to_string(*iter);
}
str += "]";
str += "my_vector_of_uint64: [";
for (auto iter = my_vector_of_uint64().begin();
iter != my_vector_of_uint64().end(); iter++) {
if (iter != my_vector_of_uint64().begin()) str += ", ";
str += std::to_string(*iter);
}
str += "]";
str += "my_vector_of_uint8: [";
for (auto iter = my_vector_of_uint8().begin();
iter != my_vector_of_uint8().end(); iter++) {
if (iter != my_vector_of_uint8().begin()) str += ", ";
str += std::to_string(*iter);
}
str += "]";
str.shrink_to_fit(); // give back excess allocations if above reservation was
// too much
return str;
}
template <class T>
std::vector<T> from_vector_view(fidl::VectorView<T> v) {
size_t count = v.count();
std::vector<T> data(count);
for (size_t i = 0; i < count; i++) {
data[i] = v[i];
}
return data;
}
std::vector<std::string> from_vector_string_view(
fidl::VectorView<fidl::StringView> v) {
size_t count = v.count();
std::vector<std::string> data(count);
for (size_t i = 0; i < count; i++) {
data[i] = std::string(v[i].get());
}
return data;
}
Config Config::TakeFromStartupHandle() noexcept {
// Get the VMO containing FIDL config
zx_handle_t config_vmo_handle =
zx_take_startup_handle(PA_VMO_COMPONENT_CONFIG);
ZX_ASSERT_MSG(
config_vmo_handle != ZX_HANDLE_INVALID,
"Config VMO handle must be provided and cannot already have been taken.");
zx::vmo config_vmo(config_vmo_handle);
return Config::CreateFromVmo(std::move(config_vmo));
}
Config Config::CreateFromVmo(zx::vmo config_vmo) noexcept {
// Get the size of the VMO
uint64_t content_size_prop = 0;
zx_status_t status = config_vmo.get_prop_content_size(&content_size_prop);
ZX_ASSERT_MSG(status == ZX_OK, "Could not get content size of config VMO");
size_t vmo_content_size = static_cast<size_t>(content_size_prop);
// Checksum length must be correct
uint16_t checksum_length = 0;
status = config_vmo.read(&checksum_length, 0, 2);
ZX_ASSERT_MSG(status == ZX_OK,
"Could not read checksum length from config VMO");
// Verify Checksum
std::vector<uint8_t> checksum(checksum_length);
status = config_vmo.read(checksum.data(), 2, checksum_length);
ZX_ASSERT_MSG(status == ZX_OK, "Could not read checksum from config VMO");
std::vector<uint8_t> expected_checksum{
0xcd, 0x57, 0xb2, 0xa2, 0x89, 0xbb, 0xb6, 0x11, 0xcf, 0x81, 0x50,
0xec, 0x06, 0xc5, 0x06, 0x4c, 0x7c, 0xae, 0x79, 0x0f, 0xaa, 0x73,
0x0b, 0x6f, 0xa1, 0x02, 0xc3, 0x53, 0x7b, 0x94, 0xee, 0x1a};
ZX_ASSERT_MSG(checksum == expected_checksum,
"Invalid checksum for config VMO");
// Read the FIDL struct into memory, skipping the checksum length and the
// checksum itself
size_t header = 2 + checksum_length;
size_t fidl_struct_size = vmo_content_size - header;
std::vector<uint8_t> fidl_struct(fidl_struct_size);
status = config_vmo.read(fidl_struct.data(), header, fidl_struct.size());
ZX_ASSERT_MSG(status == ZX_OK, "Could not read FIDL struct from config VMO");
// Decode the FIDL struct
fit::result result = fidl::Unpersist<my_config_lib::Config>(fidl_struct);
ZX_ASSERT_MSG(result.is_ok(), "Could not decode Config FIDL structure");
my_config_lib::Config fidl_config = std::move(result.value());
// Convert the configuration into a new struct
Config c{{
.my_flag = std::move(fidl_config.my_flag()),
.my_int16 = std::move(fidl_config.my_int16()),
.my_int32 = std::move(fidl_config.my_int32()),
.my_int64 = std::move(fidl_config.my_int64()),
.my_int8 = std::move(fidl_config.my_int8()),
.my_string = std::move(fidl_config.my_string()),
.my_uint16 = std::move(fidl_config.my_uint16()),
.my_uint32 = std::move(fidl_config.my_uint32()),
.my_uint64 = std::move(fidl_config.my_uint64()),
.my_uint8 = std::move(fidl_config.my_uint8()),
.my_vector_of_flag = std::move(fidl_config.my_vector_of_flag()),
.my_vector_of_int16 = std::move(fidl_config.my_vector_of_int16()),
.my_vector_of_int32 = std::move(fidl_config.my_vector_of_int32()),
.my_vector_of_int64 = std::move(fidl_config.my_vector_of_int64()),
.my_vector_of_int8 = std::move(fidl_config.my_vector_of_int8()),
.my_vector_of_string = std::move(fidl_config.my_vector_of_string()),
.my_vector_of_uint16 = std::move(fidl_config.my_vector_of_uint16()),
.my_vector_of_uint32 = std::move(fidl_config.my_vector_of_uint32()),
.my_vector_of_uint64 = std::move(fidl_config.my_vector_of_uint64()),
.my_vector_of_uint8 = std::move(fidl_config.my_vector_of_uint8()),
}};
return c;
}
zx::vmo Config::ToVmo() const noexcept {
// Create the FIDL object.
my_config_lib::Config fidl_config;
fidl_config.my_flag(this->my_flag());
fidl_config.my_int16(this->my_int16());
fidl_config.my_int32(this->my_int32());
fidl_config.my_int64(this->my_int64());
fidl_config.my_int8(this->my_int8());
fidl_config.my_string(this->my_string());
fidl_config.my_uint16(this->my_uint16());
fidl_config.my_uint32(this->my_uint32());
fidl_config.my_uint64(this->my_uint64());
fidl_config.my_uint8(this->my_uint8());
fidl_config.my_vector_of_flag(this->my_vector_of_flag());
fidl_config.my_vector_of_int16(this->my_vector_of_int16());
fidl_config.my_vector_of_int32(this->my_vector_of_int32());
fidl_config.my_vector_of_int64(this->my_vector_of_int64());
fidl_config.my_vector_of_int8(this->my_vector_of_int8());
fidl_config.my_vector_of_string(this->my_vector_of_string());
fidl_config.my_vector_of_uint16(this->my_vector_of_uint16());
fidl_config.my_vector_of_uint32(this->my_vector_of_uint32());
fidl_config.my_vector_of_uint64(this->my_vector_of_uint64());
fidl_config.my_vector_of_uint8(
this->my_vector_of_uint8()); // Persist the FIDL object.
fit::result persist_result = fidl::Persist(fidl_config);
ZX_ASSERT(persist_result.is_ok());
std::vector fidl_bytes = std::move(persist_result.value());
// Create the checksum.
std::vector<uint8_t> checksum{0xcd, 0x57, 0xb2, 0xa2, 0x89, 0xbb, 0xb6, 0x11,
0xcf, 0x81, 0x50, 0xec, 0x06, 0xc5, 0x06, 0x4c,
0x7c, 0xae, 0x79, 0x0f, 0xaa, 0x73, 0x0b, 0x6f,
0xa1, 0x02, 0xc3, 0x53, 0x7b, 0x94, 0xee, 0x1a};
// Calculate the VMO size.
uint64_t vmo_content_size = 2 + checksum.size() + fidl_bytes.size();
zx_status_t status;
zx::vmo config_vmo;
status = zx::vmo::create(vmo_content_size, 0, &config_vmo);
ZX_ASSERT_MSG(status == ZX_OK, "Failed to create vmo: %s",
zx_status_get_string(status));
// Write the checksum length
uint16_t checksum_length = static_cast<uint16_t>(checksum.size());
status = config_vmo.write(&checksum_length, 0, 2);
ZX_ASSERT_MSG(status == ZX_OK, "Failed to write checksum length: %s",
zx_status_get_string(status));
// Write the checksum.
status = config_vmo.write(checksum.data(), 2, checksum.size());
ZX_ASSERT_MSG(status == ZX_OK, "Failed to write checksum: %s",
zx_status_get_string(status));
// Write the FIDL data.
size_t header = 2 + checksum_length;
status = config_vmo.write(fidl_bytes.data(), header, fidl_bytes.size());
ZX_ASSERT_MSG(status == ZX_OK,
"Could not write FIDL struct to config VMO: %s",
zx_status_get_string(status));
// Finished!
return config_vmo;
}
} // namespace cpp_elf_config_lib