@@ -5,6 +5,7 @@ use crate::PrivilegeLevel;
55use bit_field:: BitField ;
66use bitflags:: bitflags;
77use core:: { cmp, fmt, mem} ;
8+ use crate :: structures:: tss:: InvalidIoMap ;
89
910/// Specifies which element to load into a segment from
1011/// descriptor tables (i.e., is a index to LDT or GDT table
@@ -307,7 +308,30 @@ impl Descriptor {
307308 #[ inline]
308309 pub fn tss_segment ( tss : & ' static TaskStateSegment ) -> Descriptor {
309310 // SAFETY: if iomap_size is zero, there are no requirements to uphold.
310- unsafe { Self :: tss_segment_with_iomap ( tss, 0 ) }
311+ unsafe { Self :: tss_segment_raw ( tss, 0 ) }
312+ }
313+
314+ /// Creates a TSS system descriptor for the given TSS, setting up the IO permissions bitmap.
315+ pub fn tss_segment_with_iomap (
316+ tss : & ' static TaskStateSegment ,
317+ iomap : & ' static [ u8 ] ,
318+ ) -> Result < Descriptor , InvalidIoMap > {
319+ if iomap. len ( ) > 8193 {
320+ return Err ( InvalidIoMap :: TooLong { len : iomap. len ( ) } )
321+ }
322+
323+ let distance = iomap. as_ptr ( ) as usize - tss as * const _ as usize ;
324+ if distance > 0xdfff {
325+ return Err ( InvalidIoMap :: TooFarFromTss { distance } )
326+ }
327+
328+ let last_byte = * iomap. last ( ) . unwrap_or ( & 0xff ) ;
329+ if last_byte != 0xff {
330+ return Err ( InvalidIoMap :: InvalidTerminatingByte { byte : last_byte } )
331+ }
332+
333+ // SAFETY: all invariants checked above
334+ Ok ( unsafe { Self :: tss_segment_raw ( tss, iomap. len ( ) as u16 ) } )
311335 }
312336
313337 /// Creates a TSS system descriptor for the given TSS, setting up the IO permissions bitmap.
@@ -317,7 +341,7 @@ impl Descriptor {
317341 /// There must be a valid IO map at `(tss as *const u8).offset(tss.iomap_base)`
318342 /// of length `iomap_size`, with the terminating `0xFF` byte. Additionally, `iomap_base` must
319343 /// not exceed `0xDFFF`.
320- pub unsafe fn tss_segment_with_iomap (
344+ unsafe fn tss_segment_raw (
321345 tss : & ' static TaskStateSegment ,
322346 iomap_size : u16 ,
323347 ) -> Descriptor {
0 commit comments