blob: 44d8683dd913683fd1ba7dc88c853dd9b2b9cc67 [file]
// Copyright 2026 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
use crate::object::{Dispatcher, HandleValue, IoBufferDispatcher, VmAddressRegionDispatcher};
use crate::user_copy::UserOutPtr;
use crate::vm::vm_object::VmObject;
use fbl::RefPtr;
use syscalls_macro::syscall;
use zx_status::Status;
use zx_types::{zx_rights_t, zx_status_t, zx_vaddr_t, zx_vm_option_t};
unsafe extern "C" {
fn cpp_vmar_map_common(
options: zx_vm_option_t,
vmar: *mut VmAddressRegionDispatcher,
vmar_offset: u64,
vmar_rights: zx_rights_t,
vmo: *mut VmObject,
vmo_offset: u64,
vmo_rights: zx_rights_t,
len: u64,
mapped_addr: *mut zx_vaddr_t,
) -> zx_status_t;
}
#[syscall]
pub fn sys_vmar_map_iob(
handle: HandleValue,
options: zx_vm_option_t,
vmar_offset: usize,
ep: HandleValue,
region_index: u32,
region_offset: u64,
region_length: usize,
mapped_addr: UserOutPtr<zx_vaddr_t>,
) -> Result<(), Status> {
let (vmar, vmar_rights) = Dispatcher::get_and_rights::<VmAddressRegionDispatcher>(handle)?;
let (iob, iob_rights) = Dispatcher::get_and_rights::<IoBufferDispatcher>(ep)?;
if region_index as usize >= iob.region_count() {
return Err(Status::OUT_OF_RANGE);
}
let vmo = iob.create_mappable_vmo_for_region(region_index as usize)?;
let region_rights = iob.get_map_rights(iob_rights, region_index as usize);
// SAFETY: We transfer ownership of the `RefPtr` references into `cpp_vmar_map_common`
// via `RefPtr::into_raw`, which `ImportFromRawPtr` reclaims on the C++ side.
let status = unsafe {
cpp_vmar_map_common(
options,
RefPtr::into_raw(vmar).cast_mut(),
vmar_offset as u64,
vmar_rights,
RefPtr::into_raw(vmo).cast_mut(),
region_offset,
region_rights,
region_length as u64,
mapped_addr.as_ptr(),
)
};
Status::ok(status)?;
Ok(())
}