blob: cd727a9a8af7be396e854ae97310740862bf5a98 [file] [log] [blame]
// Copyright 2020 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 <lib/fdio/io.h>
#include <lib/zbitl/error_stdio.h>
#include <lib/zbitl/image.h>
#include <lib/zbitl/view.h>
#include <lib/zbitl/vmo.h>
#include <lib/zx/vmo.h>
#include <stdio.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <cstddef>
#include <string_view>
#include <fbl/unique_fd.h>
constexpr const char* kMexecZbi = "/boot/testdata/mexec-child.zbi";
// We reserve 4 pages because this should hopefully be enough buffer for the
// extra mexec data.
constexpr size_t kMexecPayloadSize = ZX_PAGE_SIZE * 4;
int main(int argc, char** argv) {
fbl::unique_fd fd{open(kMexecZbi, O_RDONLY)};
if (!fd) {
printf("failed to open %s: %s\n", kMexecZbi, strerror(errno));
return ZX_ERR_INTERNAL;
}
zx::vmo kernel_zbi, data_zbi;
{
zx::vmo vmo;
if (zx_status_t status = fdio_get_vmo_exact(fd.get(), vmo.reset_and_get_address());
status != ZX_OK) {
printf("failed get child ZBI's VMO: %s\n", zx_status_get_string(status));
return status;
}
zbitl::View view(std::move(vmo));
if (auto result = view.Copy(view.begin(), ++view.begin()); result.is_error()) {
zbitl::PrintViewCopyError(result.error_value());
view.ignore_error();
return ZX_ERR_INTERNAL;
} else {
kernel_zbi = std::move(result).value();
}
if (auto result = view.Copy(++view.begin(), view.end()); result.is_error()) {
zbitl::PrintViewCopyError(result.error_value());
view.ignore_error();
return ZX_ERR_INTERNAL;
} else {
data_zbi = std::move(result).value();
}
if (auto result = view.take_error(); result.is_error()) {
zbitl::PrintViewError(result.error_value());
return ZX_ERR_INTERNAL;
}
}
zx::resource root_resource{zx_take_startup_handle(PA_HND(PA_RESOURCE, 0))};
if (!root_resource.is_valid()) {
printf("unable to get a hold of the root resource\n");
return ZX_ERR_INTERNAL;
}
std::byte buff[kMexecPayloadSize];
if (zx_status_t status =
zx_system_mexec_payload_get(root_resource.get(), buff, kMexecPayloadSize);
status != ZX_OK) {
printf("failed to get mexec payload: %s\n", zx_status_get_string(status));
return ZX_ERR_INTERNAL;
}
zbitl::View mexec_payload_view(std::basic_string_view<std::byte>{buff, kMexecPayloadSize});
zbitl::Image data_image(std::move(data_zbi));
if (auto result = data_image.Extend(mexec_payload_view.begin(), mexec_payload_view.end());
result.is_error()) {
zbitl::PrintViewCopyError(result.error_value());
return ZX_ERR_INTERNAL;
}
if (auto result = mexec_payload_view.take_error(); result.is_error()) {
zbitl::PrintViewError(result.error_value());
return ZX_ERR_INTERNAL;
}
if (zx_status_t status =
zx_system_mexec(root_resource.get(), kernel_zbi.get(), data_image.storage().get());
status != ZX_OK) {
printf("failed to mexec: %s\n", zx_status_get_string(status));
return status;
}
return ZX_OK;
}