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