@@ -12,11 +12,11 @@ use gpt_disk_io::{
1212} ;
1313use uefi:: {
1414 boot:: { OpenProtocolParams , ScopedProtocol } ,
15- proto:: media:: { block:: BlockIO , disk :: DiskIo } ,
15+ proto:: media:: block:: BlockIO ,
1616 Handle ,
1717} ;
1818
19- fn open_disk ( handle : Handle ) -> Result < ( ScopedProtocol < DiskIo > , ScopedProtocol < BlockIO > ) > {
19+ fn open_disk ( handle : Handle ) -> Result < ScopedProtocol < BlockIO > > {
2020 let image_handle = uefi:: boot:: image_handle ( ) ;
2121 let bio = unsafe {
2222 uefi:: boot:: open_protocol :: < BlockIO > (
@@ -28,8 +28,7 @@ fn open_disk(handle: Handle) -> Result<(ScopedProtocol<DiskIo>, ScopedProtocol<B
2828 uefi:: boot:: OpenProtocolAttributes :: GetProtocol ,
2929 ) ?
3030 } ;
31- let proto = uefi:: boot:: open_protocol_exclusive :: < DiskIo > ( handle) ?;
32- Ok ( ( proto, bio) )
31+ Ok ( bio)
3332}
3433
3534#[ derive( Debug ) ]
@@ -41,7 +40,6 @@ pub struct DiskPartition {
4140}
4241
4342pub struct Disk {
44- disk : ScopedProtocol < DiskIo > ,
4543 block : ScopedProtocol < BlockIO > ,
4644 os : UefiOS ,
4745}
@@ -50,12 +48,11 @@ pub struct Disk {
5048// available; support having more than one disk.
5149impl Disk {
5250 pub fn new ( os : UefiOS ) -> Disk {
53- let ( _size, handle) = uefi:: boot:: find_handles :: < DiskIo > ( )
51+ let ( _size, handle) = uefi:: boot:: find_handles :: < BlockIO > ( )
5452 . unwrap ( )
5553 . into_iter ( )
5654 . filter_map ( |handle| {
57- let op = open_disk ( handle) ;
58- let Ok ( ( _, block) ) = op else {
55+ let Ok ( block) = open_disk ( handle) else {
5956 return None ;
6057 } ;
6158 let m = block. media ( ) ;
@@ -68,18 +65,17 @@ impl Disk {
6865 . max_by_key ( |( size, _) | * size)
6966 . expect ( "Disk not found" ) ;
7067
71- let ( disk , block) = open_disk ( handle) . unwrap ( ) ;
72- Disk { disk , block, os }
68+ let block = open_disk ( handle) . unwrap ( ) ;
69+ Disk { block, os }
7370 }
7471
7572 #[ cfg( feature = "coverage" ) ]
7673 pub fn open_with_size ( os : UefiOS , base_size : i64 ) -> Disk {
77- let ( _size, handle) = uefi:: boot:: find_handles :: < DiskIo > ( )
74+ let ( _size, handle) = uefi:: boot:: find_handles :: < BlockIO > ( )
7875 . unwrap ( )
7976 . into_iter ( )
8077 . filter_map ( |handle| {
81- let op = open_disk ( handle) ;
82- let Ok ( ( _, block) ) = op else {
78+ let Ok ( block) = open_disk ( handle) else {
8379 return None ;
8480 } ;
8581 let m = block. media ( ) ;
@@ -92,37 +88,84 @@ impl Disk {
9288 . min_by_key ( |( size, _) | * size)
9389 . expect ( "Disk not found" ) ;
9490
95- let ( disk , block) = open_disk ( handle) . unwrap ( ) ;
96- Disk { disk , block, os }
91+ let block = open_disk ( handle) . unwrap ( ) ;
92+ Disk { block, os }
9793 }
9894
9995 pub fn size ( & self ) -> u64 {
10096 self . block . media ( ) . block_size ( ) as u64 * ( self . block . media ( ) . last_block ( ) + 1 )
10197 }
10298
103- pub async fn flush ( & mut self ) {
104- self . block . flush_blocks ( ) . unwrap ( ) ;
99+ pub async fn flush ( & mut self ) -> Result < ( ) > {
100+ self . block . flush_blocks ( ) ?;
101+ Ok ( ( ) )
102+ }
103+
104+ pub fn read_sync ( & self , offset : u64 , buf : & mut [ u8 ] ) -> Result < ( ) > {
105+ let block_size = self . block . media ( ) . block_size ( ) as u64 ;
106+ let media_id = self . block . media ( ) . media_id ( ) ;
107+ let start_block = offset / block_size;
108+ let end_block = ( offset + buf. len ( ) as u64 ) . div_ceil ( block_size) ;
109+ let num_blocks = end_block - start_block;
110+ if buf. len ( ) as u64 != num_blocks * block_size
111+ || !( buf. as_ptr ( ) as usize ) . is_multiple_of ( 16 )
112+ {
113+ //log::warn!(
114+ // "Unaligned read: offset {}, block size {}, buf addr {:p}, buf len {}",
115+ // offset,
116+ // block_size,
117+ // buf.as_ptr(),
118+ // buf.len()
119+ //);
120+ let mut buf2 = vec ! [ 0u8 ; ( num_blocks * block_size) as usize + 15 ] ;
121+ let delta = buf2. as_ptr ( ) . align_offset ( 16 ) ;
122+ let buf2 = & mut buf2[ delta..delta + ( num_blocks * block_size) as usize ] ;
123+ self . block . read_blocks ( media_id, start_block, buf2) ?;
124+ let start_offset = ( offset % block_size) as usize ;
125+ buf. copy_from_slice ( & buf2[ start_offset..start_offset + buf. len ( ) ] ) ;
126+ } else {
127+ self . block . read_blocks ( media_id, start_block, buf) ?;
128+ }
129+ Ok ( ( ) )
105130 }
106131
107132 pub async fn read ( & self , offset : u64 , buf : & mut [ u8 ] ) -> Result < ( ) > {
108133 self . os . schedule ( ) . await ;
109- Ok ( self
110- . disk
111- . read_disk ( self . block . media ( ) . media_id ( ) , offset, buf) ?)
134+ self . read_sync ( offset, buf)
112135 }
113136
114- #[ cfg( feature = "coverage" ) ]
115- pub fn write_ ( & mut self , offset : u64 , buf : & [ u8 ] ) -> Result < ( ) > {
116- Ok ( self
117- . disk
118- . write_disk ( self . block . media ( ) . media_id ( ) , offset, buf) ?)
137+ pub fn write_sync ( & mut self , offset : u64 , buf : & [ u8 ] ) -> Result < ( ) > {
138+ let block_size = self . block . media ( ) . block_size ( ) as u64 ;
139+ let media_id = self . block . media ( ) . media_id ( ) ;
140+ let start_block = offset / block_size;
141+ let end_block = ( offset + buf. len ( ) as u64 ) . div_ceil ( block_size) ;
142+ let num_blocks = end_block - start_block;
143+ if buf. len ( ) as u64 != num_blocks * block_size
144+ || !( buf. as_ptr ( ) as usize ) . is_multiple_of ( 16 )
145+ {
146+ //log::warn!(
147+ // "Unaligned write: offset {}, block size {}, buf addr {:p}, buf len {}",
148+ // offset,
149+ // block_size,
150+ // buf.as_ptr(),
151+ // buf.len()
152+ //);
153+ let mut buf2 = vec ! [ 0u8 ; ( num_blocks * block_size) as usize + 15 ] ;
154+ let delta = buf2. as_ptr ( ) . align_offset ( 16 ) ;
155+ let buf2 = & mut buf2[ delta..delta + ( num_blocks * block_size) as usize ] ;
156+ self . block . read_blocks ( media_id, start_block, buf2) ?;
157+ let start_offset = ( offset % block_size) as usize ;
158+ buf2[ start_offset..start_offset + buf. len ( ) ] . copy_from_slice ( buf) ;
159+ self . block . write_blocks ( media_id, start_block, buf2) ?;
160+ } else {
161+ self . block . write_blocks ( media_id, start_block, buf) ?;
162+ }
163+ Ok ( ( ) )
119164 }
120165
121166 pub async fn write ( & mut self , offset : u64 , buf : & [ u8 ] ) -> Result < ( ) > {
122167 self . os . schedule ( ) . await ;
123- Ok ( self
124- . disk
125- . write_disk ( self . block . media ( ) . media_id ( ) , offset, buf) ?)
168+ self . write_sync ( offset, buf)
126169 }
127170
128171 pub fn partitions ( & mut self ) -> Result < Vec < DiskPartition > > {
@@ -175,17 +218,13 @@ impl gpt_disk_io::BlockIo for &mut Disk {
175218 Ok ( self . block . media ( ) . last_block ( ) + 1 )
176219 }
177220 fn read_blocks ( & mut self , start_lba : Lba , dst : & mut [ u8 ] ) -> Result < ( ) > {
178- self . disk . read_disk (
179- self . block . media ( ) . media_id ( ) ,
180- self . block . media ( ) . block_size ( ) as u64 * start_lba. 0 ,
181- dst,
182- ) ?;
183- Ok ( ( ) )
221+ self . read_sync ( self . block . media ( ) . block_size ( ) as u64 * start_lba. 0 , dst)
184222 }
185223 fn write_blocks ( & mut self , _start_lba : Lba , _src : & [ u8 ] ) -> Result < ( ) > {
186224 unreachable ! ( ) ;
187225 }
188226 fn flush ( & mut self ) -> Result < ( ) > {
189- Ok ( self . block . flush_blocks ( ) ?)
227+ // This is a no-op because write_blocks isn't implemented.
228+ Ok ( ( ) )
190229 }
191230}
0 commit comments