about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/sys/fs/windows.rs15
-rw-r--r--library/std/src/sys/io/io_slice/uefi.rs74
-rw-r--r--library/std/src/sys/io/mod.rs3
-rw-r--r--library/std/src/sys/pal/uefi/tests.rs119
-rw-r--r--library/std/src/sys/process/windows.rs8
5 files changed, 207 insertions, 12 deletions
diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs
index 9b674a25165..09feddd0be9 100644
--- a/library/std/src/sys/fs/windows.rs
+++ b/library/std/src/sys/fs/windows.rs
@@ -80,7 +80,7 @@ pub struct OpenOptions {
     attributes: u32,
     share_mode: u32,
     security_qos_flags: u32,
-    security_attributes: *mut c::SECURITY_ATTRIBUTES,
+    inherit_handle: bool,
 }
 
 #[derive(Clone, PartialEq, Eq, Debug)]
@@ -203,7 +203,7 @@ impl OpenOptions {
             share_mode: c::FILE_SHARE_READ | c::FILE_SHARE_WRITE | c::FILE_SHARE_DELETE,
             attributes: 0,
             security_qos_flags: 0,
-            security_attributes: ptr::null_mut(),
+            inherit_handle: false,
         }
     }
 
@@ -243,8 +243,8 @@ impl OpenOptions {
         // receive is `SECURITY_ANONYMOUS = 0x0`, which we can't check for later on.
         self.security_qos_flags = flags | c::SECURITY_SQOS_PRESENT;
     }
-    pub fn security_attributes(&mut self, attrs: *mut c::SECURITY_ATTRIBUTES) {
-        self.security_attributes = attrs;
+    pub fn inherit_handle(&mut self, inherit: bool) {
+        self.inherit_handle = inherit;
     }
 
     fn get_access_mode(&self) -> io::Result<u32> {
@@ -307,12 +307,17 @@ impl File {
 
     fn open_native(path: &WCStr, opts: &OpenOptions) -> io::Result<File> {
         let creation = opts.get_creation_mode()?;
+        let sa = c::SECURITY_ATTRIBUTES {
+            nLength: size_of::<c::SECURITY_ATTRIBUTES>() as u32,
+            lpSecurityDescriptor: ptr::null_mut(),
+            bInheritHandle: opts.inherit_handle as c::BOOL,
+        };
         let handle = unsafe {
             c::CreateFileW(
                 path.as_ptr(),
                 opts.get_access_mode()?,
                 opts.share_mode,
-                opts.security_attributes,
+                if opts.inherit_handle { &sa } else { ptr::null() },
                 creation,
                 opts.get_flags_and_attributes(),
                 ptr::null_mut(),
diff --git a/library/std/src/sys/io/io_slice/uefi.rs b/library/std/src/sys/io/io_slice/uefi.rs
new file mode 100644
index 00000000000..909cfbea0b7
--- /dev/null
+++ b/library/std/src/sys/io/io_slice/uefi.rs
@@ -0,0 +1,74 @@
+//! A buffer type used with `Write::write_vectored` for UEFI Networking APIs. Vectored writing to
+//! File is not supported as of UEFI Spec 2.11.
+
+use crate::marker::PhantomData;
+use crate::slice;
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub struct IoSlice<'a> {
+    len: u32,
+    data: *const u8,
+    _p: PhantomData<&'a [u8]>,
+}
+
+impl<'a> IoSlice<'a> {
+    #[inline]
+    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
+        let len = buf.len().try_into().unwrap();
+        Self { len, data: buf.as_ptr(), _p: PhantomData }
+    }
+
+    #[inline]
+    pub fn advance(&mut self, n: usize) {
+        self.len = u32::try_from(n)
+            .ok()
+            .and_then(|n| self.len.checked_sub(n))
+            .expect("advancing IoSlice beyond its length");
+        unsafe { self.data = self.data.add(n) };
+    }
+
+    #[inline]
+    pub const fn as_slice(&self) -> &'a [u8] {
+        unsafe { slice::from_raw_parts(self.data, self.len as usize) }
+    }
+}
+
+#[repr(C)]
+pub struct IoSliceMut<'a> {
+    len: u32,
+    data: *mut u8,
+    _p: PhantomData<&'a mut [u8]>,
+}
+
+impl<'a> IoSliceMut<'a> {
+    #[inline]
+    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+        let len = buf.len().try_into().unwrap();
+        Self { len, data: buf.as_mut_ptr(), _p: PhantomData }
+    }
+
+    #[inline]
+    pub fn advance(&mut self, n: usize) {
+        self.len = u32::try_from(n)
+            .ok()
+            .and_then(|n| self.len.checked_sub(n))
+            .expect("advancing IoSlice beyond its length");
+        unsafe { self.data = self.data.add(n) };
+    }
+
+    #[inline]
+    pub fn as_slice(&self) -> &[u8] {
+        unsafe { slice::from_raw_parts(self.data, self.len as usize) }
+    }
+
+    #[inline]
+    pub const fn into_slice(self) -> &'a mut [u8] {
+        unsafe { slice::from_raw_parts_mut(self.data, self.len as usize) }
+    }
+
+    #[inline]
+    pub fn as_mut_slice(&mut self) -> &mut [u8] {
+        unsafe { slice::from_raw_parts_mut(self.data, self.len as usize) }
+    }
+}
diff --git a/library/std/src/sys/io/mod.rs b/library/std/src/sys/io/mod.rs
index 4d0365d42fd..ae75f4d97b4 100644
--- a/library/std/src/sys/io/mod.rs
+++ b/library/std/src/sys/io/mod.rs
@@ -11,6 +11,9 @@ mod io_slice {
         } else if #[cfg(target_os = "wasi")] {
             mod wasi;
             pub use wasi::*;
+        } else if #[cfg(target_os = "uefi")] {
+            mod uefi;
+            pub use uefi::*;
         } else {
             mod unsupported;
             pub use unsupported::*;
diff --git a/library/std/src/sys/pal/uefi/tests.rs b/library/std/src/sys/pal/uefi/tests.rs
index 38658cc4e9a..49e75a1a70d 100644
--- a/library/std/src/sys/pal/uefi/tests.rs
+++ b/library/std/src/sys/pal/uefi/tests.rs
@@ -1,5 +1,6 @@
 use super::alloc::*;
 use super::time::*;
+use crate::io::{IoSlice, IoSliceMut};
 use crate::time::Duration;
 
 #[test]
@@ -39,3 +40,121 @@ fn epoch() {
     };
     assert_eq!(system_time_internal::uefi_time_to_duration(t), Duration::new(0, 0));
 }
+
+// UEFI IoSlice and IoSliceMut Tests
+//
+// Strictly speaking, vectored read/write types for UDP4, UDP6, TCP4, TCP6 are defined
+// separately in the UEFI Spec. However, they have the same signature. These tests just ensure
+// that `IoSlice` and `IoSliceMut` are compatible with the vectored types for all the
+// networking protocols.
+
+unsafe fn to_slice<T>(val: &T) -> &[u8] {
+    let len = size_of_val(val);
+    unsafe { crate::slice::from_raw_parts(crate::ptr::from_ref(val).cast(), len) }
+}
+
+#[test]
+fn io_slice_single() {
+    let mut data = [0, 1, 2, 3, 4];
+
+    let tcp4_frag = r_efi::protocols::tcp4::FragmentData {
+        fragment_length: data.len().try_into().unwrap(),
+        fragment_buffer: data.as_mut_ptr().cast(),
+    };
+    let tcp6_frag = r_efi::protocols::tcp6::FragmentData {
+        fragment_length: data.len().try_into().unwrap(),
+        fragment_buffer: data.as_mut_ptr().cast(),
+    };
+    let udp4_frag = r_efi::protocols::udp4::FragmentData {
+        fragment_length: data.len().try_into().unwrap(),
+        fragment_buffer: data.as_mut_ptr().cast(),
+    };
+    let udp6_frag = r_efi::protocols::udp6::FragmentData {
+        fragment_length: data.len().try_into().unwrap(),
+        fragment_buffer: data.as_mut_ptr().cast(),
+    };
+    let io_slice = IoSlice::new(&data);
+
+    unsafe {
+        assert_eq!(to_slice(&io_slice), to_slice(&tcp4_frag));
+        assert_eq!(to_slice(&io_slice), to_slice(&tcp6_frag));
+        assert_eq!(to_slice(&io_slice), to_slice(&udp4_frag));
+        assert_eq!(to_slice(&io_slice), to_slice(&udp6_frag));
+    }
+}
+
+#[test]
+fn io_slice_mut_single() {
+    let mut data = [0, 1, 2, 3, 4];
+
+    let tcp4_frag = r_efi::protocols::tcp4::FragmentData {
+        fragment_length: data.len().try_into().unwrap(),
+        fragment_buffer: data.as_mut_ptr().cast(),
+    };
+    let tcp6_frag = r_efi::protocols::tcp6::FragmentData {
+        fragment_length: data.len().try_into().unwrap(),
+        fragment_buffer: data.as_mut_ptr().cast(),
+    };
+    let udp4_frag = r_efi::protocols::udp4::FragmentData {
+        fragment_length: data.len().try_into().unwrap(),
+        fragment_buffer: data.as_mut_ptr().cast(),
+    };
+    let udp6_frag = r_efi::protocols::udp6::FragmentData {
+        fragment_length: data.len().try_into().unwrap(),
+        fragment_buffer: data.as_mut_ptr().cast(),
+    };
+    let io_slice_mut = IoSliceMut::new(&mut data);
+
+    unsafe {
+        assert_eq!(to_slice(&io_slice_mut), to_slice(&tcp4_frag));
+        assert_eq!(to_slice(&io_slice_mut), to_slice(&tcp6_frag));
+        assert_eq!(to_slice(&io_slice_mut), to_slice(&udp4_frag));
+        assert_eq!(to_slice(&io_slice_mut), to_slice(&udp6_frag));
+    }
+}
+
+#[test]
+fn io_slice_multi() {
+    let mut data = [0, 1, 2, 3, 4];
+
+    let tcp4_frag = r_efi::protocols::tcp4::FragmentData {
+        fragment_length: data.len().try_into().unwrap(),
+        fragment_buffer: data.as_mut_ptr().cast(),
+    };
+    let rhs =
+        [tcp4_frag.clone(), tcp4_frag.clone(), tcp4_frag.clone(), tcp4_frag.clone(), tcp4_frag];
+    let lhs = [
+        IoSlice::new(&data),
+        IoSlice::new(&data),
+        IoSlice::new(&data),
+        IoSlice::new(&data),
+        IoSlice::new(&data),
+    ];
+
+    unsafe {
+        assert_eq!(to_slice(&lhs), to_slice(&rhs));
+    }
+}
+
+#[test]
+fn io_slice_basic() {
+    let data = [0, 1, 2, 3, 4];
+    let mut io_slice = IoSlice::new(&data);
+
+    assert_eq!(data, io_slice.as_slice());
+    io_slice.advance(2);
+    assert_eq!(&data[2..], io_slice.as_slice());
+}
+
+#[test]
+fn io_slice_mut_basic() {
+    let data = [0, 1, 2, 3, 4];
+    let mut data_clone = [0, 1, 2, 3, 4];
+    let mut io_slice_mut = IoSliceMut::new(&mut data_clone);
+
+    assert_eq!(data, io_slice_mut.as_slice());
+    assert_eq!(data, io_slice_mut.as_mut_slice());
+
+    io_slice_mut.advance(2);
+    assert_eq!(&data[2..], io_slice_mut.into_slice());
+}
diff --git a/library/std/src/sys/process/windows.rs b/library/std/src/sys/process/windows.rs
index 1ee3fbd285f..f9e15b82475 100644
--- a/library/std/src/sys/process/windows.rs
+++ b/library/std/src/sys/process/windows.rs
@@ -623,16 +623,10 @@ impl Stdio {
             // permissions as well as the ability to be inherited to child
             // processes (as this is about to be inherited).
             Stdio::Null => {
-                let size = size_of::<c::SECURITY_ATTRIBUTES>();
-                let mut sa = c::SECURITY_ATTRIBUTES {
-                    nLength: size as u32,
-                    lpSecurityDescriptor: ptr::null_mut(),
-                    bInheritHandle: 1,
-                };
                 let mut opts = OpenOptions::new();
                 opts.read(stdio_id == c::STD_INPUT_HANDLE);
                 opts.write(stdio_id != c::STD_INPUT_HANDLE);
-                opts.security_attributes(&mut sa);
+                opts.inherit_handle(true);
                 File::open(Path::new(r"\\.\NUL"), &opts).map(|file| file.into_inner())
             }
         }