1
- //! An implementation of Pipes using UEFI variables
1
+ //! An implementation of Pipes for UEFI
2
2
3
3
use super :: common;
4
4
use crate :: io:: { self , IoSlice , IoSliceMut } ;
@@ -47,13 +47,36 @@ impl AnonPipe {
47
47
}
48
48
49
49
pub fn read ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
50
- let protocol = common:: open_protocol ( self . handle , uefi_pipe_protocol:: PROTOCOL_GUID ) ?;
51
- unsafe { uefi_pipe_protocol:: Protocol :: read ( protocol. as_ptr ( ) , buf) }
50
+ let protocol = common:: open_protocol :: < uefi_pipe_protocol:: Protocol > (
51
+ self . handle ,
52
+ uefi_pipe_protocol:: PROTOCOL_GUID ,
53
+ ) ?;
54
+ let mut buf_size = buf. len ( ) ;
55
+ let r = unsafe {
56
+ ( ( * protocol. as_ptr ( ) ) . read ) ( protocol. as_ptr ( ) , & mut buf_size, buf. as_mut_ptr ( ) )
57
+ } ;
58
+ if r. is_error ( ) { Err ( common:: status_to_io_error ( r) ) } else { Ok ( buf_size) }
52
59
}
53
60
54
61
pub ( crate ) fn read_to_end ( & self , buf : & mut Vec < u8 > ) -> io:: Result < usize > {
55
- let protocol = common:: open_protocol ( self . handle , uefi_pipe_protocol:: PROTOCOL_GUID ) ?;
56
- unsafe { uefi_pipe_protocol:: Protocol :: read_to_end ( protocol. as_ptr ( ) , buf) }
62
+ let protocol = common:: open_protocol :: < uefi_pipe_protocol:: Protocol > (
63
+ self . handle ,
64
+ uefi_pipe_protocol:: PROTOCOL_GUID ,
65
+ ) ?;
66
+ let buf_size = unsafe { ( ( * protocol. as_ptr ( ) ) . size ) ( protocol. as_ptr ( ) ) } ;
67
+ buf. reserve_exact ( buf_size) ;
68
+ let mut buf_size = buf. capacity ( ) ;
69
+ let r = unsafe {
70
+ ( ( * protocol. as_ptr ( ) ) . read ) ( protocol. as_ptr ( ) , & mut buf_size, buf. as_mut_ptr ( ) )
71
+ } ;
72
+ if r. is_error ( ) {
73
+ Err ( common:: status_to_io_error ( r) )
74
+ } else {
75
+ unsafe {
76
+ buf. set_len ( buf. len ( ) + buf_size) ;
77
+ }
78
+ Ok ( buf_size)
79
+ }
57
80
}
58
81
59
82
pub fn read_vectored ( & self , bufs : & mut [ IoSliceMut < ' _ > ] ) -> io:: Result < usize > {
@@ -66,8 +89,14 @@ impl AnonPipe {
66
89
}
67
90
68
91
pub fn write ( & self , buf : & [ u8 ] ) -> io:: Result < usize > {
69
- let protocol = common:: open_protocol ( self . handle , uefi_pipe_protocol:: PROTOCOL_GUID ) ?;
70
- unsafe { uefi_pipe_protocol:: Protocol :: write ( protocol. as_ptr ( ) , buf) }
92
+ let protocol = common:: open_protocol :: < uefi_pipe_protocol:: Protocol > (
93
+ self . handle ,
94
+ uefi_pipe_protocol:: PROTOCOL_GUID ,
95
+ ) ?;
96
+ let mut buf_size = buf. len ( ) ;
97
+ let r =
98
+ unsafe { ( ( * protocol. as_ptr ( ) ) . write ) ( protocol. as_ptr ( ) , & mut buf_size, buf. as_ptr ( ) ) } ;
99
+ if r. is_error ( ) { Err ( common:: status_to_io_error ( r) ) } else { Ok ( buf_size) }
71
100
}
72
101
73
102
pub fn write_vectored ( & self , bufs : & [ IoSlice < ' _ > ] ) -> io:: Result < usize > {
@@ -96,6 +125,7 @@ pub(crate) mod uefi_pipe_protocol {
96
125
use crate :: sys:: uefi:: common;
97
126
use io:: { Read , Write } ;
98
127
use r_efi:: efi:: Guid ;
128
+ use r_efi:: { eficall, eficall_abi} ;
99
129
100
130
pub ( crate ) const PROTOCOL_GUID : Guid = Guid :: from_fields (
101
131
0x3c4acb49 ,
@@ -120,26 +150,30 @@ pub(crate) mod uefi_pipe_protocol {
120
150
}
121
151
122
152
#[ inline]
123
- pub ( crate ) unsafe fn read ( data : * mut Pipedata , buf : & mut [ u8 ] ) -> io:: Result < usize > {
153
+ unsafe fn read ( data : * mut Pipedata , buf : & mut [ u8 ] ) -> io:: Result < usize > {
124
154
unsafe { ( * data) . data . read ( buf) }
125
155
}
126
156
127
157
#[ inline]
128
- pub ( crate ) unsafe fn read_to_end (
129
- data : * mut Pipedata ,
130
- buf : & mut Vec < u8 > ,
131
- ) -> io:: Result < usize > {
132
- unsafe { ( * data) . data . read_to_end ( buf) }
158
+ unsafe fn write ( data : * mut Pipedata , buf : & [ u8 ] ) -> io:: Result < usize > {
159
+ unsafe { ( * data) . data . write ( buf) }
133
160
}
134
161
135
162
#[ inline]
136
- pub ( crate ) unsafe fn write ( data : * mut Pipedata , buf : & [ u8 ] ) -> io :: Result < usize > {
137
- unsafe { ( * data) . data . write ( buf ) }
163
+ unsafe fn size ( data : * mut Pipedata ) -> usize {
164
+ unsafe { ( * data) . data . len ( ) }
138
165
}
139
166
}
140
167
168
+ type WriteSignature = eficall ! { fn ( * mut Protocol , * mut usize , * const u8 ) -> r_efi:: efi:: Status } ;
169
+ type ReadSignature = eficall ! { fn ( * mut Protocol , * mut usize , * mut u8 ) -> r_efi:: efi:: Status } ;
170
+ type SizeSignature = eficall ! { fn ( * mut Protocol ) -> usize } ;
171
+
141
172
#[ repr( C ) ]
142
173
pub ( crate ) struct Protocol {
174
+ pub read : ReadSignature ,
175
+ pub write : WriteSignature ,
176
+ pub size : SizeSignature ,
143
177
data : * mut Pipedata ,
144
178
}
145
179
@@ -150,39 +184,98 @@ pub(crate) mod uefi_pipe_protocol {
150
184
impl Protocol {
151
185
#[ inline]
152
186
pub ( crate ) fn with_data ( data : & mut Pipedata ) -> Self {
153
- Self { data }
187
+ Self {
188
+ data,
189
+ read : pipe_protocol_read,
190
+ write : pipe_protocol_write,
191
+ size : pipe_protocol_size,
192
+ }
154
193
}
155
194
156
195
#[ inline]
157
196
pub ( crate ) fn null ( ) -> Self {
158
- Self { data : crate :: ptr:: null_mut ( ) }
197
+ Self {
198
+ data : crate :: ptr:: null_mut ( ) ,
199
+ read : pipe_protocol_null_read,
200
+ write : pipe_protocol_null_write,
201
+ size : pipe_protocol_null_size,
202
+ }
203
+ }
204
+
205
+ unsafe fn read ( protocol : * mut Protocol , buf : & mut [ u8 ] ) -> io:: Result < usize > {
206
+ unsafe {
207
+ assert ! ( !( * protocol) . data. is_null( ) ) ;
208
+ Pipedata :: read ( ( * protocol) . data , buf)
209
+ }
159
210
}
160
211
161
- pub ( crate ) unsafe fn read ( protocol : * mut Protocol , buf : & mut [ u8 ] ) -> io:: Result < usize > {
162
- if unsafe { ( * protocol) . data . is_null ( ) } {
163
- Ok ( 0 )
164
- } else {
165
- unsafe { Pipedata :: read ( ( * protocol) . data , buf) }
212
+ unsafe fn write ( protocol : * mut Protocol , buf : & [ u8 ] ) -> io:: Result < usize > {
213
+ unsafe {
214
+ assert ! ( !( * protocol) . data. is_null( ) ) ;
215
+ Pipedata :: write ( ( * protocol) . data , buf)
166
216
}
167
217
}
168
218
169
- pub ( crate ) unsafe fn read_to_end (
170
- protocol : * mut Protocol ,
171
- buf : & mut Vec < u8 > ,
172
- ) -> io:: Result < usize > {
173
- if unsafe { ( * protocol) . data . is_null ( ) } {
174
- Ok ( 0 )
175
- } else {
176
- unsafe { Pipedata :: read_to_end ( ( * protocol) . data , buf) }
219
+ unsafe fn size ( protocol : * mut Protocol ) -> usize {
220
+ unsafe {
221
+ assert ! ( !( * protocol) . data. is_null( ) ) ;
222
+ Pipedata :: size ( ( * protocol) . data )
177
223
}
178
224
}
225
+ }
179
226
180
- pub ( crate ) unsafe fn write ( protocol : * mut Protocol , buf : & [ u8 ] ) -> io:: Result < usize > {
181
- if unsafe { ( * protocol) . data . is_null ( ) } {
182
- Ok ( buf. len ( ) )
183
- } else {
184
- unsafe { Pipedata :: write ( ( * protocol) . data , buf) }
227
+ extern "efiapi" fn pipe_protocol_read (
228
+ protocol : * mut Protocol ,
229
+ buf_size : * mut usize ,
230
+ buf : * mut u8 ,
231
+ ) -> r_efi:: efi:: Status {
232
+ let buffer = unsafe { crate :: slice:: from_raw_parts_mut ( buf, buf_size. read ( ) ) } ;
233
+ match unsafe { Protocol :: read ( protocol, buffer) } {
234
+ Ok ( x) => {
235
+ unsafe { buf_size. write ( x) } ;
236
+ r_efi:: efi:: Status :: SUCCESS
185
237
}
238
+ Err ( _) => r_efi:: efi:: Status :: ABORTED ,
186
239
}
187
240
}
241
+
242
+ extern "efiapi" fn pipe_protocol_write (
243
+ protocol : * mut Protocol ,
244
+ buf_size : * mut usize ,
245
+ buf : * const u8 ,
246
+ ) -> r_efi:: efi:: Status {
247
+ let buffer = unsafe { crate :: slice:: from_raw_parts ( buf, buf_size. read ( ) ) } ;
248
+ match unsafe { Protocol :: write ( protocol, buffer) } {
249
+ Ok ( x) => {
250
+ unsafe { buf_size. write ( x) } ;
251
+ r_efi:: efi:: Status :: SUCCESS
252
+ }
253
+ Err ( _) => r_efi:: efi:: Status :: ABORTED ,
254
+ }
255
+ }
256
+
257
+ extern "efiapi" fn pipe_protocol_size ( protocol : * mut Protocol ) -> usize {
258
+ unsafe { Protocol :: size ( protocol) }
259
+ }
260
+
261
+ extern "efiapi" fn pipe_protocol_null_write (
262
+ _protocol : * mut Protocol ,
263
+ _buf_size : * mut usize ,
264
+ _buf : * const u8 ,
265
+ ) -> r_efi:: efi:: Status {
266
+ r_efi:: efi:: Status :: SUCCESS
267
+ }
268
+
269
+ extern "efiapi" fn pipe_protocol_null_read (
270
+ _protocol : * mut Protocol ,
271
+ buf_size : * mut usize ,
272
+ _buf : * mut u8 ,
273
+ ) -> r_efi:: efi:: Status {
274
+ unsafe { buf_size. write ( 0 ) } ;
275
+ r_efi:: efi:: Status :: SUCCESS
276
+ }
277
+
278
+ extern "efiapi" fn pipe_protocol_null_size ( _protocol : * mut Protocol ) -> usize {
279
+ 0
280
+ }
188
281
}
0 commit comments