diff --git a/Cargo.toml b/Cargo.toml index 3a4f2f39..fe955b40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ log = "0.4.22" bitflags = "2.6.0" enumn = "0.1.14" embedded-io = { version = "0.6.1", optional = true } -zerocopy = { version = "0.7.35", features = ["derive"] } +zerocopy = { version = "0.8.7", features = ["derive"] } [features] default = ["alloc", "embedded-io"] @@ -27,4 +27,4 @@ alloc = ["zerocopy/alloc"] embedded-io = ["dep:embedded-io"] [dev-dependencies] -zerocopy = { version = "0.7.35", features = ["alloc"] } +zerocopy = { version = "0.8.7", features = ["alloc"] } diff --git a/src/device/blk.rs b/src/device/blk.rs index bda6edc2..53f4bb53 100644 --- a/src/device/blk.rs +++ b/src/device/blk.rs @@ -7,7 +7,7 @@ use crate::volatile::{volread, Volatile}; use crate::{Error, Result}; use bitflags::bitflags; use log::info; -use zerocopy::{AsBytes, FromBytes, FromZeroes}; +use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout}; const QUEUE: u16 = 0; const QUEUE_SIZE: u16 = 16; @@ -111,7 +111,7 @@ impl VirtIOBlk { let mut resp = BlkResp::default(); self.queue.add_notify_wait_pop( &[request.as_bytes()], - &mut [resp.as_bytes_mut()], + &mut [resp.as_mut_bytes()], &mut self.transport, )?; resp.status.into() @@ -122,7 +122,7 @@ impl VirtIOBlk { let mut resp = BlkResp::default(); self.queue.add_notify_wait_pop( &[request.as_bytes()], - &mut [data, resp.as_bytes_mut()], + &mut [data, resp.as_mut_bytes()], &mut self.transport, )?; resp.status.into() @@ -133,7 +133,7 @@ impl VirtIOBlk { let mut resp = BlkResp::default(); self.queue.add_notify_wait_pop( &[request.as_bytes(), data], - &mut [resp.as_bytes_mut()], + &mut [resp.as_mut_bytes()], &mut self.transport, )?; resp.status.into() @@ -261,7 +261,7 @@ impl VirtIOBlk { }; let token = self .queue - .add(&[req.as_bytes()], &mut [buf, resp.as_bytes_mut()])?; + .add(&[req.as_bytes()], &mut [buf, resp.as_mut_bytes()])?; if self.queue.should_notify() { self.transport.notify(QUEUE); } @@ -282,7 +282,7 @@ impl VirtIOBlk { resp: &mut BlkResp, ) -> Result<()> { self.queue - .pop_used(token, &[req.as_bytes()], &mut [buf, resp.as_bytes_mut()])?; + .pop_used(token, &[req.as_bytes()], &mut [buf, resp.as_mut_bytes()])?; resp.status.into() } @@ -343,7 +343,7 @@ impl VirtIOBlk { }; let token = self .queue - .add(&[req.as_bytes(), buf], &mut [resp.as_bytes_mut()])?; + .add(&[req.as_bytes(), buf], &mut [resp.as_mut_bytes()])?; if self.queue.should_notify() { self.transport.notify(QUEUE); } @@ -364,7 +364,7 @@ impl VirtIOBlk { resp: &mut BlkResp, ) -> Result<()> { self.queue - .pop_used(token, &[req.as_bytes(), buf], &mut [resp.as_bytes_mut()])?; + .pop_used(token, &[req.as_bytes(), buf], &mut [resp.as_mut_bytes()])?; resp.status.into() } @@ -410,7 +410,7 @@ struct BlkConfig { /// A VirtIO block device request. #[repr(C)] -#[derive(AsBytes, Debug)] +#[derive(Debug, Immutable, IntoBytes, KnownLayout)] pub struct BlkReq { type_: ReqType, reserved: u32, @@ -429,7 +429,7 @@ impl Default for BlkReq { /// Response of a VirtIOBlk request. #[repr(C)] -#[derive(AsBytes, Debug, FromBytes, FromZeroes)] +#[derive(Debug, FromBytes, Immutable, IntoBytes, KnownLayout)] pub struct BlkResp { status: RespStatus, } @@ -442,7 +442,7 @@ impl BlkResp { } #[repr(u32)] -#[derive(AsBytes, Debug)] +#[derive(Debug, Immutable, IntoBytes, KnownLayout)] enum ReqType { In = 0, Out = 1, @@ -456,7 +456,7 @@ enum ReqType { /// Status of a VirtIOBlk request. #[repr(transparent)] -#[derive(AsBytes, Copy, Clone, Debug, Eq, FromBytes, FromZeroes, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)] pub struct RespStatus(u8); impl RespStatus { diff --git a/src/device/gpu.rs b/src/device/gpu.rs index 0cef8b4e..6c1cd7db 100644 --- a/src/device/gpu.rs +++ b/src/device/gpu.rs @@ -8,7 +8,7 @@ use crate::{pages, Error, Result, PAGE_SIZE}; use alloc::boxed::Box; use bitflags::bitflags; use log::info; -use zerocopy::{AsBytes, FromBytes, FromZeroes}; +use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; const QUEUE_SIZE: u16 = 2; const SUPPORTED_FEATURES: Features = Features::RING_EVENT_IDX.union(Features::RING_INDIRECT_DESC); @@ -66,8 +66,8 @@ impl VirtIOGpu { negotiated_features.contains(Features::RING_EVENT_IDX), )?; - let queue_buf_send = FromZeroes::new_box_slice_zeroed(PAGE_SIZE); - let queue_buf_recv = FromZeroes::new_box_slice_zeroed(PAGE_SIZE); + let queue_buf_send = FromZeros::new_box_zeroed_with_elems(PAGE_SIZE).unwrap(); + let queue_buf_recv = FromZeros::new_box_zeroed_with_elems(PAGE_SIZE).unwrap(); transport.finish_init(); @@ -173,18 +173,18 @@ impl VirtIOGpu { } /// Send a request to the device and block for a response. - fn request(&mut self, req: Req) -> Result { + fn request(&mut self, req: Req) -> Result { req.write_to_prefix(&mut self.queue_buf_send).unwrap(); self.control_queue.add_notify_wait_pop( &[&self.queue_buf_send], &mut [&mut self.queue_buf_recv], &mut self.transport, )?; - Ok(Rsp::read_from_prefix(&self.queue_buf_recv).unwrap()) + Ok(Rsp::read_from_prefix(&self.queue_buf_recv).unwrap().0) } /// Send a mouse cursor operation request to the device and block for a response. - fn cursor_request(&mut self, req: Req) -> Result { + fn cursor_request(&mut self, req: Req) -> Result { req.write_to_prefix(&mut self.queue_buf_send).unwrap(); self.cursor_queue.add_notify_wait_pop( &[&self.queue_buf_send], @@ -338,7 +338,7 @@ bitflags! { } #[repr(transparent)] -#[derive(AsBytes, Clone, Copy, Debug, Eq, PartialEq, FromBytes, FromZeroes)] +#[derive(Clone, Copy, Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)] struct Command(u32); impl Command { @@ -371,7 +371,7 @@ impl Command { const GPU_FLAG_FENCE: u32 = 1 << 0; #[repr(C)] -#[derive(AsBytes, Debug, Clone, Copy, FromBytes, FromZeroes)] +#[derive(Debug, Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout)] struct CtrlHeader { hdr_type: Command, flags: u32, @@ -402,7 +402,7 @@ impl CtrlHeader { } #[repr(C)] -#[derive(AsBytes, Debug, Copy, Clone, Default, FromBytes, FromZeroes)] +#[derive(Debug, Copy, Clone, Default, FromBytes, Immutable, IntoBytes, KnownLayout)] struct Rect { x: u32, y: u32, @@ -411,7 +411,7 @@ struct Rect { } #[repr(C)] -#[derive(Debug, FromBytes, FromZeroes)] +#[derive(Debug, FromBytes, Immutable, KnownLayout)] struct RespDisplayInfo { header: CtrlHeader, rect: Rect, @@ -420,7 +420,7 @@ struct RespDisplayInfo { } #[repr(C)] -#[derive(AsBytes, Debug)] +#[derive(Debug, Immutable, IntoBytes, KnownLayout)] struct ResourceCreate2D { header: CtrlHeader, resource_id: u32, @@ -430,13 +430,13 @@ struct ResourceCreate2D { } #[repr(u32)] -#[derive(AsBytes, Debug)] +#[derive(Debug, Immutable, IntoBytes, KnownLayout)] enum Format { B8G8R8A8UNORM = 1, } #[repr(C)] -#[derive(AsBytes, Debug)] +#[derive(Debug, Immutable, IntoBytes, KnownLayout)] struct ResourceAttachBacking { header: CtrlHeader, resource_id: u32, @@ -447,7 +447,7 @@ struct ResourceAttachBacking { } #[repr(C)] -#[derive(AsBytes, Debug)] +#[derive(Debug, Immutable, IntoBytes, KnownLayout)] struct SetScanout { header: CtrlHeader, rect: Rect, @@ -456,7 +456,7 @@ struct SetScanout { } #[repr(C)] -#[derive(AsBytes, Debug)] +#[derive(Debug, Immutable, IntoBytes, KnownLayout)] struct TransferToHost2D { header: CtrlHeader, rect: Rect, @@ -466,7 +466,7 @@ struct TransferToHost2D { } #[repr(C)] -#[derive(AsBytes, Debug)] +#[derive(Debug, Immutable, IntoBytes, KnownLayout)] struct ResourceFlush { header: CtrlHeader, rect: Rect, @@ -475,7 +475,7 @@ struct ResourceFlush { } #[repr(C)] -#[derive(AsBytes, Debug, Clone, Copy)] +#[derive(Copy, Clone, Debug, Immutable, IntoBytes, KnownLayout)] struct CursorPos { scanout_id: u32, x: u32, @@ -484,7 +484,7 @@ struct CursorPos { } #[repr(C)] -#[derive(AsBytes, Debug, Clone, Copy)] +#[derive(Copy, Clone, Debug, Immutable, IntoBytes, KnownLayout)] struct UpdateCursor { header: CtrlHeader, pos: CursorPos, diff --git a/src/device/input.rs b/src/device/input.rs index ed690764..4891c9f4 100644 --- a/src/device/input.rs +++ b/src/device/input.rs @@ -10,7 +10,7 @@ use alloc::{boxed::Box, string::String}; use core::cmp::min; use core::mem::size_of; use core::ptr::{addr_of, NonNull}; -use zerocopy::{AsBytes, FromBytes, FromZeroes}; +use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; /// Virtual human interface devices such as keyboards, mice and tablets. /// @@ -48,7 +48,7 @@ impl VirtIOInput { )?; for (i, event) in event_buf.as_mut().iter_mut().enumerate() { // Safe because the buffer lasts as long as the queue. - let token = unsafe { event_queue.add(&[], &mut [event.as_bytes_mut()])? }; + let token = unsafe { event_queue.add(&[], &mut [event.as_mut_bytes()])? }; assert_eq!(token, i as u16); } if event_queue.should_notify() { @@ -79,13 +79,13 @@ impl VirtIOInput { // is still valid. unsafe { self.event_queue - .pop_used(token, &[], &mut [event.as_bytes_mut()]) + .pop_used(token, &[], &mut [event.as_mut_bytes()]) .ok()?; } let event_saved = *event; // requeue // Safe because buffer lasts as long as the queue. - if let Ok(new_token) = unsafe { self.event_queue.add(&[], &mut [event.as_bytes_mut()]) } + if let Ok(new_token) = unsafe { self.event_queue.add(&[], &mut [event.as_mut_bytes()]) } { // This only works because nothing happen between `pop_used` and `add` that affects // the list of free descriptors in the queue, so `add` reuses the descriptor which @@ -137,7 +137,7 @@ impl VirtIOInput { if size > CONFIG_DATA_MAX_LENGTH { return Err(Error::IoError); } - let mut buf = u8::new_box_slice_zeroed(size); + let mut buf = <[u8]>::new_box_zeroed_with_elems(size).unwrap(); for i in 0..size { buf[i] = addr_of!((*self.config.as_ptr()).data[i]).vread(); } @@ -172,7 +172,7 @@ impl VirtIOInput { /// Queries and returns the ID information of the device. pub fn ids(&mut self) -> Result { let mut ids = DevIDs::default(); - let size = self.query_config_select(InputConfigSelect::IdDevids, 0, ids.as_bytes_mut()); + let size = self.query_config_select(InputConfigSelect::IdDevids, 0, ids.as_mut_bytes()); if usize::from(size) == size_of::() { Ok(ids) } else { @@ -195,7 +195,7 @@ impl VirtIOInput { /// Queries and returns information about the given axis of the device. pub fn abs_info(&mut self, axis: u8) -> Result { let mut info = AbsInfo::default(); - let size = self.query_config_select(InputConfigSelect::AbsInfo, axis, info.as_bytes_mut()); + let size = self.query_config_select(InputConfigSelect::AbsInfo, axis, info.as_mut_bytes()); if usize::from(size) == size_of::() { Ok(info) } else { @@ -263,7 +263,7 @@ struct Config { /// Information about an axis of an input device, typically a joystick. #[repr(C)] -#[derive(AsBytes, Clone, Debug, Default, Eq, PartialEq, FromBytes, FromZeroes)] +#[derive(Clone, Debug, Default, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)] pub struct AbsInfo { /// The minimum value for the axis. pub min: u32, @@ -279,7 +279,7 @@ pub struct AbsInfo { /// The identifiers of a VirtIO input device. #[repr(C)] -#[derive(AsBytes, Clone, Debug, Default, Eq, PartialEq, FromBytes, FromZeroes)] +#[derive(Clone, Debug, Default, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)] pub struct DevIDs { /// The bustype identifier. pub bustype: u16, @@ -294,7 +294,7 @@ pub struct DevIDs { /// Both queues use the same `virtio_input_event` struct. `type`, `code` and `value` /// are filled according to the Linux input layer (evdev) interface. #[repr(C)] -#[derive(AsBytes, Clone, Copy, Debug, Default, FromBytes, FromZeroes)] +#[derive(Clone, Copy, Debug, Default, FromBytes, Immutable, IntoBytes, KnownLayout)] pub struct InputEvent { /// Event type. pub event_type: u16, diff --git a/src/device/net/dev_raw.rs b/src/device/net/dev_raw.rs index 70b3a171..1f4b4c81 100644 --- a/src/device/net/dev_raw.rs +++ b/src/device/net/dev_raw.rs @@ -6,7 +6,7 @@ use crate::transport::Transport; use crate::volatile::volread; use crate::{Error, Result}; use log::{debug, info, warn}; -use zerocopy::AsBytes; +use zerocopy::IntoBytes; /// Raw driver for a VirtIO network device. /// diff --git a/src/device/net/mod.rs b/src/device/net/mod.rs index 3b97a182..d40a2d4f 100644 --- a/src/device/net/mod.rs +++ b/src/device/net/mod.rs @@ -12,7 +12,7 @@ pub use self::{dev::VirtIONet, net_buf::RxBuffer, net_buf::TxBuffer}; use crate::volatile::ReadOnly; use bitflags::bitflags; -use zerocopy::{AsBytes, FromBytes, FromZeroes}; +use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout}; const MAX_BUFFER_LEN: usize = 65535; const MIN_BUFFER_LEN: usize = 1526; @@ -113,7 +113,7 @@ type EthernetAddress = [u8; 6]; /// and buffers for incoming packets are placed in the receiveq1. . .receiveqN. /// In each case, the packet itself is preceded by a header. #[repr(C)] -#[derive(AsBytes, Debug, Default, FromBytes, FromZeroes)] +#[derive(Debug, Default, FromBytes, Immutable, IntoBytes, KnownLayout)] pub struct VirtioNetHdr { flags: Flags, gso_type: GsoType, @@ -125,7 +125,9 @@ pub struct VirtioNetHdr { // payload starts from here } -#[derive(AsBytes, Copy, Clone, Debug, Default, Eq, FromBytes, FromZeroes, PartialEq)] +#[derive( + IntoBytes, Copy, Clone, Debug, Default, Eq, FromBytes, Immutable, KnownLayout, PartialEq, +)] #[repr(transparent)] struct Flags(u8); @@ -138,7 +140,9 @@ bitflags! { } #[repr(transparent)] -#[derive(AsBytes, Debug, Copy, Clone, Default, Eq, FromBytes, FromZeroes, PartialEq)] +#[derive( + IntoBytes, Debug, Copy, Clone, Default, Eq, FromBytes, Immutable, KnownLayout, PartialEq, +)] struct GsoType(u8); impl GsoType { diff --git a/src/device/net/net_buf.rs b/src/device/net/net_buf.rs index 8b4947bf..dd2d748a 100644 --- a/src/device/net/net_buf.rs +++ b/src/device/net/net_buf.rs @@ -1,7 +1,7 @@ use super::{VirtioNetHdr, NET_HDR_SIZE}; use alloc::{vec, vec::Vec}; use core::{convert::TryInto, mem::size_of}; -use zerocopy::AsBytes; +use zerocopy::IntoBytes; /// A buffer used for transmitting. pub struct TxBuffer(pub(crate) Vec); @@ -63,7 +63,7 @@ impl RxBuffer { /// Returns all data in the buffer with the mutable reference, /// including both the header and the packet. pub fn as_bytes_mut(&mut self) -> &mut [u8] { - self.buf.as_bytes_mut() + self.buf.as_mut_bytes() } /// Returns the reference of the header. @@ -78,6 +78,6 @@ impl RxBuffer { /// Returns the network packet as a mutable slice. pub fn packet_mut(&mut self) -> &mut [u8] { - &mut self.buf.as_bytes_mut()[NET_HDR_SIZE..NET_HDR_SIZE + self.packet_len] + &mut self.buf.as_mut_bytes()[NET_HDR_SIZE..NET_HDR_SIZE + self.packet_len] } } diff --git a/src/device/socket/connectionmanager.rs b/src/device/socket/connectionmanager.rs index 0c9e4e81..96c7cd24 100644 --- a/src/device/socket/connectionmanager.rs +++ b/src/device/socket/connectionmanager.rs @@ -8,7 +8,7 @@ use core::cmp::min; use core::convert::TryInto; use core::hint::spin_loop; use log::debug; -use zerocopy::FromZeroes; +use zerocopy::FromZeros; const DEFAULT_PER_CONNECTION_BUFFER_CAPACITY: u32 = 1024; @@ -343,7 +343,7 @@ struct RingBuffer { impl RingBuffer { pub fn new(capacity: usize) -> Self { Self { - buffer: FromZeroes::new_box_slice_zeroed(capacity), + buffer: FromZeros::new_box_zeroed_with_elems(capacity).unwrap(), used: 0, start: 0, } @@ -431,7 +431,7 @@ mod tests { use alloc::{sync::Arc, vec}; use core::{mem::size_of, ptr::NonNull}; use std::{sync::Mutex, thread}; - use zerocopy::{AsBytes, FromBytes}; + use zerocopy::{FromBytes, IntoBytes}; #[test] fn send_recv() { @@ -474,7 +474,7 @@ mod tests { // Wait for connection request. State::wait_until_queue_notified(&state, TX_QUEUE_IDX); assert_eq!( - VirtioVsockHdr::read_from( + VirtioVsockHdr::read_from_bytes( state .lock() .unwrap() @@ -525,7 +525,9 @@ mod tests { size_of::() + hello_from_guest.len() ); assert_eq!( - VirtioVsockHdr::read_from_prefix(request.as_slice()).unwrap(), + VirtioVsockHdr::read_from_prefix(request.as_slice()) + .unwrap() + .0, VirtioVsockHdr { op: VirtioVsockOp::Rw.into(), src_cid: guest_cid.into(), @@ -560,7 +562,8 @@ mod tests { buf_alloc: 50.into(), fwd_cnt: (hello_from_guest.len() as u32).into(), } - .write_to_prefix(response.as_mut_slice()); + .write_to_prefix(response.as_mut_slice()) + .unwrap(); response[size_of::()..].copy_from_slice(hello_from_host.as_bytes()); state .lock() @@ -570,7 +573,7 @@ mod tests { // Expect a shutdown. State::wait_until_queue_notified(&state, TX_QUEUE_IDX); assert_eq!( - VirtioVsockHdr::read_from( + VirtioVsockHdr::read_from_bytes( state .lock() .unwrap() @@ -708,7 +711,7 @@ mod tests { println!("Host waiting for rejection"); State::wait_until_queue_notified(&state, TX_QUEUE_IDX); assert_eq!( - VirtioVsockHdr::read_from( + VirtioVsockHdr::read_from_bytes( state .lock() .unwrap() @@ -753,7 +756,7 @@ mod tests { println!("Host waiting for response"); State::wait_until_queue_notified(&state, TX_QUEUE_IDX); assert_eq!( - VirtioVsockHdr::read_from( + VirtioVsockHdr::read_from_bytes( state .lock() .unwrap() diff --git a/src/device/socket/protocol.rs b/src/device/socket/protocol.rs index 4eac3245..af5b85df 100644 --- a/src/device/socket/protocol.rs +++ b/src/device/socket/protocol.rs @@ -9,7 +9,7 @@ use core::{ }; use zerocopy::{ byteorder::{LittleEndian, U16, U32, U64}, - AsBytes, FromBytes, FromZeroes, + FromBytes, Immutable, IntoBytes, KnownLayout, }; /// Well-known CID for the host. @@ -46,7 +46,7 @@ pub struct VirtioVsockConfig { /// The message header for data packets sent on the tx/rx queues #[repr(C, packed)] -#[derive(AsBytes, Clone, Copy, Debug, Eq, FromBytes, FromZeroes, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)] pub struct VirtioVsockHdr { pub src_cid: U64, pub dst_cid: U64, @@ -122,7 +122,7 @@ pub struct VsockAddr { } /// An event sent to the event queue -#[derive(Copy, Clone, Debug, Default, AsBytes, FromBytes, FromZeroes)] +#[derive(Copy, Clone, Debug, Default, IntoBytes, FromBytes, Immutable, KnownLayout)] #[repr(C)] pub struct VirtioVsockEvent { // ID from the virtio_vsock_event_id struct in the virtio spec diff --git a/src/device/socket/vsock.rs b/src/device/socket/vsock.rs index 4a9e33be..a90ee13f 100644 --- a/src/device/socket/vsock.rs +++ b/src/device/socket/vsock.rs @@ -13,7 +13,7 @@ use crate::volatile::volread; use crate::Result; use core::mem::size_of; use log::debug; -use zerocopy::{AsBytes, FromBytes}; +use zerocopy::{FromBytes, IntoBytes}; pub(crate) const RX_QUEUE_IDX: u16 = 0; pub(crate) const TX_QUEUE_IDX: u16 = 1; @@ -441,7 +441,9 @@ impl VirtIOSocket Result<(VirtioVsockHdr, &[u8])> { // This could fail if the device returns a buffer used length shorter than the header size. - let header = VirtioVsockHdr::read_from_prefix(buffer).ok_or(SocketError::BufferTooShort)?; + let header = VirtioVsockHdr::read_from_prefix(buffer) + .map_err(|_| SocketError::BufferTooShort)? + .0; let body_length = header.len() as usize; // This could fail if the device returns an unreasonably long body length. diff --git a/src/device/sound.rs b/src/device/sound.rs index 571a55a5..b055d280 100644 --- a/src/device/sound.rs +++ b/src/device/sound.rs @@ -21,7 +21,7 @@ use core::{ }; use enumn::N; use log::{error, info, warn}; -use zerocopy::{AsBytes, FromBytes, FromZeroes}; +use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; /// Audio driver based on virtio v1.2. /// @@ -110,8 +110,8 @@ impl VirtIOSound { jacks, streams, chmaps ); - let queue_buf_send = FromZeroes::new_box_slice_zeroed(PAGE_SIZE); - let queue_buf_recv = FromZeroes::new_box_slice_zeroed(PAGE_SIZE); + let queue_buf_send = FromZeros::new_box_zeroed_with_elems(PAGE_SIZE).unwrap(); + let queue_buf_recv = FromZeros::new_box_zeroed_with_elems(PAGE_SIZE).unwrap(); // set pcm params to default let mut pcm_parameters = vec![]; @@ -168,13 +168,15 @@ impl VirtIOSound { self.transport.ack_interrupt() } - fn request(&mut self, req: Req) -> Result { + fn request(&mut self, req: Req) -> Result { self.control_queue.add_notify_wait_pop( &[req.as_bytes()], - &mut [self.queue_buf_recv.as_bytes_mut()], + &mut [self.queue_buf_recv.as_mut_bytes()], &mut self.transport, )?; - Ok(VirtIOSndHdr::read_from_prefix(&self.queue_buf_recv).unwrap()) + Ok(VirtIOSndHdr::read_from_prefix(&self.queue_buf_recv) + .unwrap() + .0) } /// Set up the driver, initate pcm_infos and jacks_infos @@ -242,9 +244,10 @@ impl VirtIOSound { const JACK_INFO_SIZE: usize = size_of::(); let start_byte_idx = HDR_SIZE + i * JACK_INFO_SIZE; let end_byte_idx = HDR_SIZE + (i + 1) * JACK_INFO_SIZE; - let jack_info = - VirtIOSndJackInfo::read_from(&self.queue_buf_recv[start_byte_idx..end_byte_idx]) - .unwrap(); + let jack_info = VirtIOSndJackInfo::read_from_bytes( + &self.queue_buf_recv[start_byte_idx..end_byte_idx], + ) + .unwrap(); jack_infos.push(jack_info) } Ok(jack_infos) @@ -277,9 +280,10 @@ impl VirtIOSound { const PCM_INFO_SIZE: usize = size_of::(); let start_byte_idx = HDR_SIZE + i * PCM_INFO_SIZE; let end_byte_idx = HDR_SIZE + (i + 1) * PCM_INFO_SIZE; - let pcm_info = - VirtIOSndPcmInfo::read_from(&self.queue_buf_recv[start_byte_idx..end_byte_idx]) - .unwrap(); + let pcm_info = VirtIOSndPcmInfo::read_from_bytes( + &self.queue_buf_recv[start_byte_idx..end_byte_idx], + ) + .unwrap(); pcm_infos.push(pcm_info); } Ok(pcm_infos) @@ -310,7 +314,8 @@ impl VirtIOSound { let start_byte = OFFSET + i * size_of::(); let end_byte = OFFSET + (i + 1) * size_of::(); let chmap_info = - VirtIOSndChmapInfo::read_from(&self.queue_buf_recv[start_byte..end_byte]).unwrap(); + VirtIOSndChmapInfo::read_from_bytes(&self.queue_buf_recv[start_byte..end_byte]) + .unwrap(); chmap_infos.push(chmap_info); } Ok(chmap_infos) @@ -524,7 +529,7 @@ impl VirtIOSound { tokens[head] = unsafe { self.tx_queue.add( &[&stream_id_bytes, buffer], - &mut [statuses[head].as_bytes_mut()], + &mut [statuses[head].as_mut_bytes()], )? }; if self.tx_queue.should_notify() { @@ -544,7 +549,7 @@ impl VirtIOSound { self.tx_queue.pop_used( tokens[tail], &[&stream_id_bytes, buffers[tail].unwrap()], - &mut [statuses[tail].as_bytes_mut()], + &mut [statuses[tail].as_mut_bytes()], )?; } if statuses[tail].status != CommandCode::SOk.into() { @@ -583,8 +588,8 @@ impl VirtIOSound { let mut buf = vec![0; U32_SIZE + period_size]; buf[..U32_SIZE].copy_from_slice(&stream_id.to_le_bytes()); buf[U32_SIZE..U32_SIZE + period_size].copy_from_slice(frames); - let mut rsp = VirtIOSndPcmStatus::new_box_zeroed(); - let token = unsafe { self.tx_queue.add(&[&buf], &mut [rsp.as_bytes_mut()])? }; + let mut rsp = VirtIOSndPcmStatus::new_box_zeroed().unwrap(); + let token = unsafe { self.tx_queue.add(&[&buf], &mut [rsp.as_mut_bytes()])? }; if self.tx_queue.should_notify() { self.transport.notify(TX_QUEUE_IDX); } @@ -601,7 +606,7 @@ impl VirtIOSound { self.tx_queue.pop_used( token, &[&self.token_buf[&token]], - &mut [self.token_rsp.get_mut(&token).unwrap().as_bytes_mut()], + &mut [self.token_rsp.get_mut(&token).unwrap().as_mut_bytes()], )?; } @@ -703,7 +708,7 @@ impl VirtIOSound { // If the device has written notifications to the event_queue, // then the oldest notification should be at the front of the queue. self.event_queue.poll(&mut self.transport, |buffer| { - if let Some(event) = VirtIOSndEvent::read_from(buffer) { + if let Ok(event) = VirtIOSndEvent::read_from_bytes(buffer) { Ok(Some(Notification { notification_type: NotificationType::n(event.hdr.command_code) .ok_or(Error::IoError)?, @@ -1112,7 +1117,7 @@ impl From for VirtIOSndHdr { /// A common header #[repr(C)] -#[derive(AsBytes, Clone, Debug, Eq, FromBytes, FromZeroes, PartialEq)] +#[derive(Clone, Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)] struct VirtIOSndHdr { command_code: u32, } @@ -1126,7 +1131,7 @@ impl From for VirtIOSndHdr { } #[repr(C)] -#[derive(FromBytes, FromZeroes)] +#[derive(FromBytes, Immutable, KnownLayout)] /// An event notification struct VirtIOSndEvent { hdr: VirtIOSndHdr, @@ -1183,7 +1188,7 @@ const VIRTIO_SND_D_OUTPUT: u8 = 0; const VIRTIO_SND_D_INPUT: u8 = 1; #[repr(C)] -#[derive(AsBytes, Debug, FromBytes, FromZeroes)] +#[derive(Debug, FromBytes, Immutable, IntoBytes, KnownLayout)] struct VirtIOSndQueryInfo { /// specifies a particular item request type (VIRTIO_SND_R_*_INFO) hdr: VirtIOSndHdr, @@ -1202,7 +1207,7 @@ struct VirtIOSndQueryInfo { } #[repr(C)] -#[derive(AsBytes, Debug, FromBytes, FromZeroes)] +#[derive(Debug, FromBytes, Immutable, IntoBytes, KnownLayout)] struct VirtIOSndQueryInfoRsp { hdr: VirtIOSndHdr, info: VirtIOSndInfo, @@ -1210,13 +1215,13 @@ struct VirtIOSndQueryInfoRsp { /// Field `hda_fn_nid` indicates a function group node identifier. #[repr(C)] -#[derive(AsBytes, Clone, Debug, Eq, FromBytes, FromZeroes, PartialEq)] +#[derive(Clone, Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)] pub struct VirtIOSndInfo { hda_fn_nid: u32, } #[repr(C)] -#[derive(AsBytes, Clone, Debug, FromBytes, FromZeroes)] +#[derive(Clone, Debug, FromBytes, Immutable, IntoBytes, KnownLayout)] struct VirtIOSndJackHdr { hdr: VirtIOSndHdr, /// specifies a jack identifier from 0 to jacks - 1 @@ -1225,7 +1230,7 @@ struct VirtIOSndJackHdr { /// Jack infomation. #[repr(C)] -#[derive(AsBytes, Clone, Eq, FromBytes, FromZeroes, PartialEq)] +#[derive(Clone, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)] pub struct VirtIOSndJackInfo { hdr: VirtIOSndInfo, features: u32, @@ -1271,14 +1276,14 @@ impl Display for VirtIOSndJackInfo { } #[repr(C)] -#[derive(AsBytes, FromBytes, FromZeroes)] +#[derive(FromBytes, Immutable, IntoBytes, KnownLayout)] struct VirtIOSndJackInfoRsp { hdr: VirtIOSndHdr, body: VirtIOSndJackInfo, } #[repr(C)] -#[derive(AsBytes, FromBytes, FromZeroes)] +#[derive(FromBytes, Immutable, IntoBytes, KnownLayout)] struct VirtIOSndJackRemap { hdr: VirtIOSndJackHdr, association: u32, @@ -1286,7 +1291,7 @@ struct VirtIOSndJackRemap { } #[repr(C)] -#[derive(AsBytes, Debug, Eq, FromBytes, FromZeroes, PartialEq)] +#[derive(Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)] struct VirtIOSndPcmHdr { /// specifies request type (VIRTIO_SND_R_PCM_*) hdr: VirtIOSndHdr, @@ -1349,7 +1354,7 @@ impl From for u64 { /// PCM information. #[repr(C)] -#[derive(AsBytes, Clone, Eq, FromBytes, FromZeroes, PartialEq)] +#[derive(Clone, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)] pub struct VirtIOSndPcmInfo { hdr: VirtIOSndInfo, features: u32, /* 1 << VIRTIO_SND_PCM_F_XXX */ @@ -1409,7 +1414,7 @@ struct PcmParameters { } #[repr(C)] -#[derive(AsBytes, Debug, Eq, FromBytes, FromZeroes, PartialEq)] +#[derive(Debug, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq)] struct VirtIOSndPcmSetParams { hdr: VirtIOSndPcmHdr, /* .code = VIRTIO_SND_R_PCM_SET_PARAMS */ buffer_bytes: u32, @@ -1424,14 +1429,14 @@ struct VirtIOSndPcmSetParams { /// An I/O header #[repr(C)] -#[derive(AsBytes, FromBytes, FromZeroes)] +#[derive(FromBytes, Immutable, IntoBytes, KnownLayout)] struct VirtIOSndPcmXfer { stream_id: u32, } /// An I/O status #[repr(C)] -#[derive(AsBytes, Default, FromBytes, FromZeroes)] +#[derive(Default, FromBytes, Immutable, IntoBytes, KnownLayout)] struct VirtIOSndPcmStatus { status: u32, latency_bytes: u32, @@ -1520,7 +1525,7 @@ enum ChannelPosition { const VIRTIO_SND_CHMAP_MAX_SIZE: usize = 18; #[repr(C)] -#[derive(AsBytes, Clone, Debug, FromBytes, FromZeroes)] +#[derive(Clone, Debug, FromBytes, Immutable, IntoBytes, KnownLayout)] struct VirtIOSndChmapInfo { hdr: VirtIOSndInfo, direction: u8, diff --git a/src/device/sound/fake.rs b/src/device/sound/fake.rs index b4bfb8c7..15d81ad3 100644 --- a/src/device/sound/fake.rs +++ b/src/device/sound/fake.rs @@ -28,7 +28,7 @@ use std::{ }, thread::{self, JoinHandle}, }; -use zerocopy::{AsBytes, FromBytes}; +use zerocopy::{FromBytes, IntoBytes}; #[derive(Clone, Debug)] pub struct FakeSoundDevice { @@ -128,7 +128,9 @@ impl FakeSoundDevice { } fn handle_tx(&self, request: &[u8]) -> Vec { - let header = VirtIOSndPcmXfer::read_from_prefix(&request).expect("TX request too short"); + let header = VirtIOSndPcmXfer::read_from_prefix(&request) + .expect("TX request too short") + .0; self.played_bytes.lock().unwrap()[usize::try_from(header.stream_id).unwrap()] .extend(&request[size_of::()..]); @@ -142,8 +144,9 @@ impl FakeSoundDevice { fn handle_control_request(&self, request: &[u8]) -> Vec { { - let header = - VirtIOSndHdr::read_from_prefix(&request).expect("Control request too short"); + let header = VirtIOSndHdr::read_from_prefix(&request) + .expect("Control request too short") + .0; let mut response = Vec::new(); const R_JACK_INFO: u32 = CommandCode::RJackInfo as u32; const R_PCM_INFO: u32 = CommandCode::RPcmInfo as u32; @@ -155,7 +158,7 @@ impl FakeSoundDevice { const R_PCM_RELEASE: u32 = CommandCode::RPcmRelease as u32; match header.command_code { R_JACK_INFO => { - let request = VirtIOSndQueryInfo::read_from(&request) + let request = VirtIOSndQueryInfo::read_from_bytes(&request) .expect("R_JACK_INFO control request wrong length"); assert_eq!( request.size, @@ -174,7 +177,7 @@ impl FakeSoundDevice { } } R_PCM_INFO => { - let request = VirtIOSndQueryInfo::read_from(&request) + let request = VirtIOSndQueryInfo::read_from_bytes(&request) .expect("R_PCM_INFO control request wrong length"); assert_eq!( request.size, @@ -193,7 +196,7 @@ impl FakeSoundDevice { } } R_CHMAP_INFO => { - let request = VirtIOSndQueryInfo::read_from(&request) + let request = VirtIOSndQueryInfo::read_from_bytes(&request) .expect("R_CHMAP_INFO control request wrong length"); assert_eq!( request.size, @@ -212,7 +215,7 @@ impl FakeSoundDevice { } } R_PCM_SET_PARAMS => { - let request = VirtIOSndPcmSetParams::read_from(&request) + let request = VirtIOSndPcmSetParams::read_from_bytes(&request) .expect("R_PCM_SET_PARAMS request wrong length"); let stream_id = request.hdr.stream_id; self.params.lock().unwrap()[usize::try_from(stream_id).unwrap()] = @@ -226,7 +229,7 @@ impl FakeSoundDevice { } R_PCM_PREPARE | R_PCM_START | R_PCM_STOP | R_PCM_RELEASE => { let _request = - VirtIOSndPcmHdr::read_from(&request).expect("Request wrong length"); + VirtIOSndPcmHdr::read_from_bytes(&request).expect("Request wrong length"); response.extend_from_slice( VirtIOSndHdr { command_code: CommandCode::SOk.into(), diff --git a/src/hal/fake.rs b/src/hal/fake.rs index f3737e2a..94891da9 100644 --- a/src/hal/fake.rs +++ b/src/hal/fake.rs @@ -8,7 +8,7 @@ use core::{ alloc::Layout, ptr::{self, NonNull}, }; -use zerocopy::FromZeroes; +use zerocopy::FromZeros; #[derive(Debug)] pub struct FakeHal; @@ -46,7 +46,7 @@ unsafe impl Hal for FakeHal { assert_ne!(buffer.len(), 0); // To ensure that the driver is handling and unsharing buffers properly, allocate a new // buffer and copy to it if appropriate. - let mut shared_buffer = u8::new_box_slice_zeroed(buffer.len()); + let mut shared_buffer = <[u8]>::new_box_zeroed_with_elems(buffer.len()).unwrap(); if let BufferDirection::DriverToDevice | BufferDirection::Both = direction { unsafe { buffer diff --git a/src/queue.rs b/src/queue.rs index ed7c856f..cef85932 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -18,7 +18,7 @@ use core::mem::{size_of, take}; use core::ptr; use core::ptr::NonNull; use core::sync::atomic::{fence, AtomicU16, Ordering}; -use zerocopy::{AsBytes, FromBytes, FromZeroes}; +use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; /// The mechanism for bulk data transport on virtio devices. /// @@ -110,7 +110,7 @@ impl VirtQueue { let avail = layout.avail_vaddr().cast(); let used = layout.used_vaddr().cast(); - let mut desc_shadow: [Descriptor; SIZE] = FromZeroes::new_zeroed(); + let mut desc_shadow: [Descriptor; SIZE] = FromZeros::new_zeroed(); // Link descriptors together. for i in 0..(size - 1) { desc_shadow[i as usize].next = i + 1; @@ -251,7 +251,8 @@ impl VirtQueue { let head = self.free_head; // Allocate and fill in indirect descriptor list. - let mut indirect_list = Descriptor::new_box_slice_zeroed(inputs.len() + outputs.len()); + let mut indirect_list = + <[Descriptor]>::new_box_zeroed_with_elems(inputs.len() + outputs.len()).unwrap(); for (i, (buffer, direction)) in InputOutputIter::new(inputs, outputs).enumerate() { let desc = &mut indirect_list[i]; // Safe because our caller promises that the buffers live at least until `pop_used` @@ -436,7 +437,7 @@ impl VirtQueue { unsafe { H::unshare( paddr as usize, - indirect_list.as_bytes_mut().into(), + indirect_list.as_mut_bytes().into(), BufferDirection::DriverToDevice, ); } @@ -697,7 +698,7 @@ fn queue_part_sizes(queue_size: u16) -> (usize, usize, usize) { } #[repr(C, align(16))] -#[derive(AsBytes, Clone, Debug, FromBytes, FromZeroes)] +#[derive(Clone, Debug, FromBytes, Immutable, IntoBytes, KnownLayout)] pub(crate) struct Descriptor { addr: u64, len: u32, @@ -752,7 +753,9 @@ impl Descriptor { } /// Descriptor flags -#[derive(AsBytes, Copy, Clone, Debug, Default, Eq, FromBytes, FromZeroes, PartialEq)] +#[derive( + Copy, Clone, Debug, Default, Eq, FromBytes, Immutable, IntoBytes, KnownLayout, PartialEq, +)] #[repr(transparent)] struct DescFlags(u16); @@ -877,11 +880,13 @@ pub(crate) fn fake_read_write_queue( // Loop through all input descriptors in the indirect descriptor list, reading data from // them. - let indirect_descriptor_list: &[Descriptor] = zerocopy::Ref::new_slice( - slice::from_raw_parts(descriptor.addr as *const u8, descriptor.len as usize), - ) - .unwrap() - .into_slice(); + let indirect_descriptor_list: &[Descriptor] = zerocopy::Ref::into_ref( + zerocopy::Ref::<_, [Descriptor]>::from_bytes(slice::from_raw_parts( + descriptor.addr as *const u8, + descriptor.len as usize, + )) + .unwrap(), + ); let mut input = Vec::new(); let mut indirect_descriptor_index = 0; while indirect_descriptor_index < indirect_descriptor_list.len() { diff --git a/src/queue/owning.rs b/src/queue/owning.rs index 9a0e17d5..2c1b883b 100644 --- a/src/queue/owning.rs +++ b/src/queue/owning.rs @@ -3,7 +3,7 @@ use crate::{transport::Transport, Error, Hal, Result}; use alloc::boxed::Box; use core::convert::TryInto; use core::ptr::{null_mut, NonNull}; -use zerocopy::FromZeroes; +use zerocopy::FromZeros; /// A wrapper around [`Queue`] that owns all the buffers that are passed to the queue. #[derive(Debug)] @@ -21,7 +21,7 @@ impl OwningQueue) -> Result { let mut buffers = [null_mut(); SIZE]; for (i, queue_buffer) in buffers.iter_mut().enumerate() { - let mut buffer: Box<[u8; BUFFER_SIZE]> = FromZeroes::new_box_zeroed(); + let mut buffer: Box<[u8; BUFFER_SIZE]> = FromZeros::new_box_zeroed().unwrap(); // SAFETY: The buffer lives as long as the queue, as specified in the function safety // requirement, and we don't access it until it is popped. let token = unsafe { queue.add(&[], &mut [buffer.as_mut_slice()]) }?;