]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/UefiScsiLib/UefiScsiLib.c
MdePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdePkg / Library / UefiScsiLib / UefiScsiLib.c
1 /** @file
2 UEFI SCSI Library implementation
3
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9
10 #include <Uefi.h>
11 #include <Library/BaseLib.h>
12 #include <Library/DebugLib.h>
13 #include <Library/UefiScsiLib.h>
14 #include <Library/BaseMemoryLib.h>
15 #include <Library/MemoryAllocationLib.h>
16 #include <Library/UefiBootServicesTableLib.h>
17
18 #include <IndustryStandard/Scsi.h>
19
20
21 //
22 // Scsi Command Length
23 //
24 #define EFI_SCSI_OP_LENGTH_SIX 0x6
25 #define EFI_SCSI_OP_LENGTH_TEN 0xa
26 #define EFI_SCSI_OP_LENGTH_SIXTEEN 0x10
27
28 //
29 // The context structure used when non-blocking SCSI read/write operation
30 // completes.
31 //
32 typedef struct {
33 ///
34 /// The SCSI request packet to send to the SCSI controller specified by
35 /// the device handle.
36 ///
37 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
38 ///
39 /// The length of the output sense data.
40 ///
41 UINT8 *SenseDataLength;
42 ///
43 /// The status of the SCSI host adapter.
44 ///
45 UINT8 *HostAdapterStatus;
46 ///
47 /// The status of the target SCSI device.
48 ///
49 UINT8 *TargetStatus;
50 ///
51 /// The length of the data buffer for the SCSI read/write command.
52 ///
53 UINT32 *DataLength;
54 ///
55 /// The caller event to be signaled when the SCSI read/write command
56 /// completes.
57 ///
58 EFI_EVENT CallerEvent;
59 } EFI_SCSI_LIB_ASYNC_CONTEXT;
60
61
62
63 /**
64 Execute Test Unit Ready SCSI command on a specific SCSI target.
65
66 Executes the Test Unit Ready command on the SCSI target specified by ScsiIo.
67 If Timeout is zero, then this function waits indefinitely for the command to complete.
68 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
69 If ScsiIo is NULL, then ASSERT().
70 If SenseDataLength is NULL, then ASSERT().
71 If HostAdapterStatus is NULL, then ASSERT().
72 If TargetStatus is NULL, then ASSERT().
73
74 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
75 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
76 gets returned.
77
78 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
79 for the specific SCSI target.
80 @param[in] Timeout The timeout in 100 ns units to use for the execution
81 of this SCSI Request Packet. A Timeout value of
82 zero means that this function will wait indefinitely
83 for the SCSI Request Packet to execute. If Timeout
84 is greater than zero, then this function will return
85 EFI_TIMEOUT if the time required to execute the SCSI
86 Request Packet is greater than Timeout.
87 @param[in, out] SenseData A pointer to sense data that was generated by
88 the execution of the SCSI Request Packet. This
89 buffer must be allocated by the caller.
90 If SenseDataLength is 0, then this parameter is
91 optional and may be NULL.
92 @param[in, out] SenseDataLength On input, a pointer to the length in bytes of
93 the SenseData buffer. On output, a pointer to
94 the number of bytes written to the SenseData buffer.
95 @param[out] HostAdapterStatus The status of the SCSI Host Controller that produces
96 the SCSI bus containing the SCSI target specified by
97 ScsiIo when the SCSI Request Packet was executed.
98 See the EFI SCSI I/O Protocol in the UEFI Specification
99 for details on the possible return values.
100 @param[out] TargetStatus The status returned by the SCSI target specified
101 by ScsiIo when the SCSI Request Packet was executed
102 on the SCSI Host Controller. See the EFI SCSI I/O
103 Protocol in the UEFI Specification for details on
104 the possible return values.
105
106 @retval EFI_SUCCESS The command was executed successfully.
107 See HostAdapterStatus, TargetStatus, SenseDataLength,
108 and SenseData in that order for additional status
109 information.
110 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
111 there are too many SCSI Command Packets already
112 queued. The SCSI Request Packet was not sent, so
113 no additional status information is available.
114 The caller may retry again later.
115 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
116 SCSI Request Packet. See HostAdapterStatus,
117 TargetStatus, SenseDataLength, and SenseData in that
118 order for additional status information.
119 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
120 is not supported by the SCSI initiator(i.e., SCSI
121 Host Controller). The SCSI Request Packet was not
122 sent, so no additional status information is available.
123 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request
124 Packet to execute. See HostAdapterStatus, TargetStatus,
125 SenseDataLength, and SenseData in that order for
126 additional status information.
127 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
128
129 **/
130 EFI_STATUS
131 EFIAPI
132 ScsiTestUnitReadyCommand (
133 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
134 IN UINT64 Timeout,
135 IN OUT VOID *SenseData, OPTIONAL
136 IN OUT UINT8 *SenseDataLength,
137 OUT UINT8 *HostAdapterStatus,
138 OUT UINT8 *TargetStatus
139 )
140 {
141 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
142 EFI_STATUS Status;
143 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
144
145 ASSERT (SenseDataLength != NULL);
146 ASSERT (HostAdapterStatus != NULL);
147 ASSERT (TargetStatus != NULL);
148 ASSERT (ScsiIo != NULL);
149
150 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
151 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
152
153 CommandPacket.Timeout = Timeout;
154 CommandPacket.InDataBuffer = NULL;
155 CommandPacket.InTransferLength= 0;
156 CommandPacket.OutDataBuffer = NULL;
157 CommandPacket.OutTransferLength= 0;
158 CommandPacket.SenseData = SenseData;
159 CommandPacket.Cdb = Cdb;
160 //
161 // Fill Cdb for Test Unit Ready Command
162 //
163 Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;
164 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
165 CommandPacket.SenseDataLength = *SenseDataLength;
166
167 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
168
169 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
170 *TargetStatus = CommandPacket.TargetStatus;
171 *SenseDataLength = CommandPacket.SenseDataLength;
172
173 return Status;
174 }
175
176
177 /**
178 Execute Inquiry SCSI command on a specific SCSI target.
179
180 Executes the Inquiry command on the SCSI target specified by ScsiIo.
181 If Timeout is zero, then this function waits indefinitely for the command to complete.
182 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
183 If ScsiIo is NULL, then ASSERT().
184 If SenseDataLength is NULL, then ASSERT().
185 If HostAdapterStatus is NULL, then ASSERT().
186 If TargetStatus is NULL, then ASSERT().
187 If InquiryDataLength is NULL, then ASSERT().
188
189 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
190 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
191 gets returned.
192
193 If InquiryDataLength is non-zero and InquiryDataBuffer is not NULL, InquiryDataBuffer
194 must meet buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
195 EFI_INVALID_PARAMETER gets returned.
196
197 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
198 for the specific SCSI target.
199 @param[in] Timeout The timeout in 100 ns units to use for the
200 execution of this SCSI Request Packet. A Timeout
201 value of zero means that this function will wait
202 indefinitely for the SCSI Request Packet to execute.
203 If Timeout is greater than zero, then this function
204 will return EFI_TIMEOUT if the time required to
205 execute the SCSI Request Packet is greater than Timeout.
206 @param[in, out] SenseData A pointer to sense data that was generated
207 by the execution of the SCSI Request Packet.
208 This buffer must be allocated by the caller.
209 If SenseDataLength is 0, then this parameter
210 is optional and may be NULL.
211 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
212 On output, the number of bytes written to the SenseData buffer.
213 @param[out] HostAdapterStatus The status of the SCSI Host Controller that
214 produces the SCSI bus containing the SCSI
215 target specified by ScsiIo when the SCSI
216 Request Packet was executed. See the EFI
217 SCSI I/O Protocol in the UEFI Specification
218 for details on the possible return values.
219 @param[out] TargetStatus The status returned by the SCSI target specified
220 by ScsiIo when the SCSI Request Packet was
221 executed on the SCSI Host Controller.
222 See the EFI SCSI I/O Protocol in the UEFI
223 Specification for details on the possible
224 return values.
225 @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated
226 by the execution of the SCSI Request Packet.
227 This buffer must be allocated by the caller.
228 If InquiryDataLength is 0, then this parameter
229 is optional and may be NULL.
230 @param[in, out] InquiryDataLength On input, a pointer to the length in bytes
231 of the InquiryDataBuffer buffer.
232 On output, a pointer to the number of bytes
233 written to the InquiryDataBuffer buffer.
234 @param[in] EnableVitalProductData If TRUE, then the supported vital product
235 data for the PageCode is returned in InquiryDataBuffer.
236 If FALSE, then the standard inquiry data is
237 returned in InquiryDataBuffer and PageCode is ignored.
238 @param[in] PageCode The page code of the vital product data.
239 It's ignored if EnableVitalProductData is FALSE.
240
241 @retval EFI_SUCCESS The command executed successfully. See HostAdapterStatus,
242 TargetStatus, SenseDataLength, and SenseData in that order
243 for additional status information.
244 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
245 InquiryDataBuffer could not be transferred. The actual
246 number of bytes transferred is returned in InquiryDataLength.
247 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there
248 are too many SCSI Command Packets already queued.
249 The SCSI Request Packet was not sent, so no additional
250 status information is available. The caller may retry again later.
251 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI
252 Request Packet. See HostAdapterStatus, TargetStatus,
253 SenseDataLength, and SenseData in that order for additional
254 status information.
255 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not
256 supported by the SCSI initiator(i.e., SCSI Host Controller).
257 The SCSI Request Packet was not sent, so no additional
258 status information is available.
259 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request
260 Packet to execute. See HostAdapterStatus, TargetStatus,
261 SenseDataLength, and SenseData in that order for
262 additional status information.
263 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
264
265 **/
266 EFI_STATUS
267 EFIAPI
268 ScsiInquiryCommandEx (
269 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
270 IN UINT64 Timeout,
271 IN OUT VOID *SenseData, OPTIONAL
272 IN OUT UINT8 *SenseDataLength,
273 OUT UINT8 *HostAdapterStatus,
274 OUT UINT8 *TargetStatus,
275 IN OUT VOID *InquiryDataBuffer, OPTIONAL
276 IN OUT UINT32 *InquiryDataLength,
277 IN BOOLEAN EnableVitalProductData,
278 IN UINT8 PageCode
279 )
280 {
281 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
282 EFI_STATUS Status;
283 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
284
285 ASSERT (SenseDataLength != NULL);
286 ASSERT (HostAdapterStatus != NULL);
287 ASSERT (TargetStatus != NULL);
288 ASSERT (InquiryDataLength != NULL);
289 ASSERT (ScsiIo != NULL);
290
291 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
292 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
293
294 CommandPacket.Timeout = Timeout;
295 CommandPacket.InDataBuffer = InquiryDataBuffer;
296 CommandPacket.InTransferLength= *InquiryDataLength;
297 CommandPacket.SenseData = SenseData;
298 CommandPacket.SenseDataLength = *SenseDataLength;
299 CommandPacket.Cdb = Cdb;
300
301 Cdb[0] = EFI_SCSI_OP_INQUIRY;
302 if (EnableVitalProductData) {
303 Cdb[1] |= 0x01;
304 Cdb[2] = PageCode;
305 }
306
307 if (*InquiryDataLength > 0xff) {
308 *InquiryDataLength = 0xff;
309 }
310
311 Cdb[4] = (UINT8) (*InquiryDataLength);
312 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
313 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
314
315 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
316
317 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
318 *TargetStatus = CommandPacket.TargetStatus;
319 *SenseDataLength = CommandPacket.SenseDataLength;
320 *InquiryDataLength = CommandPacket.InTransferLength;
321
322 return Status;
323 }
324
325
326 /**
327 Execute Inquiry SCSI command on a specific SCSI target.
328
329 Executes the Inquiry command on the SCSI target specified by ScsiIo.
330 If Timeout is zero, then this function waits indefinitely for the command to complete.
331 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
332 If ScsiIo is NULL, then ASSERT().
333 If SenseDataLength is NULL, then ASSERT().
334 If HostAdapterStatus is NULL, then ASSERT().
335 If TargetStatus is NULL, then ASSERT().
336 If InquiryDataLength is NULL, then ASSERT().
337
338 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
339 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
340 gets returned.
341
342 If InquiryDataLength is non-zero and InquiryDataBuffer is not NULL, InquiryDataBuffer
343 must meet buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
344 EFI_INVALID_PARAMETER gets returned.
345
346 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
347 for the specific SCSI target.
348 @param[in] Timeout The timeout in 100 ns units to use for the
349 execution of this SCSI Request Packet. A Timeout
350 value of zero means that this function will wait
351 indefinitely for the SCSI Request Packet to execute.
352 If Timeout is greater than zero, then this function
353 will return EFI_TIMEOUT if the time required to
354 execute the SCSI Request Packet is greater than Timeout.
355 @param[in, out] SenseData A pointer to sense data that was generated
356 by the execution of the SCSI Request Packet.
357 This buffer must be allocated by the caller.
358 If SenseDataLength is 0, then this parameter
359 is optional and may be NULL.
360 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
361 On output, the number of bytes written to the SenseData buffer.
362 @param[out] HostAdapterStatus The status of the SCSI Host Controller that
363 produces the SCSI bus containing the SCSI
364 target specified by ScsiIo when the SCSI
365 Request Packet was executed. See the EFI
366 SCSI I/O Protocol in the UEFI Specification
367 for details on the possible return values.
368 @param[out] TargetStatus The status returned by the SCSI target specified
369 by ScsiIo when the SCSI Request Packet was
370 executed on the SCSI Host Controller.
371 See the EFI SCSI I/O Protocol in the UEFI
372 Specification for details on the possible
373 return values.
374 @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated
375 by the execution of the SCSI Request Packet.
376 This buffer must be allocated by the caller.
377 If InquiryDataLength is 0, then this parameter
378 is optional and may be NULL.
379 @param[in, out] InquiryDataLength On input, a pointer to the length in bytes
380 of the InquiryDataBuffer buffer.
381 On output, a pointer to the number of bytes
382 written to the InquiryDataBuffer buffer.
383 @param[in] EnableVitalProductData If TRUE, then the supported vital product
384 data is returned in InquiryDataBuffer.
385 If FALSE, then the standard inquiry data is
386 returned in InquiryDataBuffer.
387
388 @retval EFI_SUCCESS The command was executed successfully. See HostAdapterStatus,
389 TargetStatus, SenseDataLength, and SenseData in that order
390 for additional status information.
391 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
392 InquiryDataBuffer could not be transferred. The actual
393 number of bytes transferred is returned in InquiryDataLength.
394 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there
395 are too many SCSI Command Packets already queued.
396 The SCSI Request Packet was not sent, so no additional
397 status information is available. The caller may retry again later.
398 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI
399 Request Packet. See HostAdapterStatus, TargetStatus,
400 SenseDataLength, and SenseData in that order for additional
401 status information.
402 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not
403 supported by the SCSI initiator(i.e., SCSI Host Controller).
404 The SCSI Request Packet was not sent, so no additional
405 status information is available.
406 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request
407 Packet to execute. See HostAdapterStatus, TargetStatus,
408 SenseDataLength, and SenseData in that order for
409 additional status information.
410 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
411
412 **/
413 EFI_STATUS
414 EFIAPI
415 ScsiInquiryCommand (
416 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
417 IN UINT64 Timeout,
418 IN OUT VOID *SenseData, OPTIONAL
419 IN OUT UINT8 *SenseDataLength,
420 OUT UINT8 *HostAdapterStatus,
421 OUT UINT8 *TargetStatus,
422 IN OUT VOID *InquiryDataBuffer, OPTIONAL
423 IN OUT UINT32 *InquiryDataLength,
424 IN BOOLEAN EnableVitalProductData
425 )
426 {
427 return ScsiInquiryCommandEx (
428 ScsiIo,
429 Timeout,
430 SenseData,
431 SenseDataLength,
432 HostAdapterStatus,
433 TargetStatus,
434 InquiryDataBuffer,
435 InquiryDataLength,
436 EnableVitalProductData,
437 0
438 );
439 }
440
441 /**
442 Execute Mode Sense(10) SCSI command on a specific SCSI target.
443
444 Executes the SCSI Mode Sense(10) command on the SCSI target specified by ScsiIo.
445 If Timeout is zero, then this function waits indefinitely for the command to complete.
446 If Timeout is greater than zero, then the command is executed and will timeout
447 after Timeout 100 ns units. The DBDField, PageControl, and PageCode parameters
448 are used to construct the CDB for this SCSI command.
449 If ScsiIo is NULL, then ASSERT().
450 If SenseDataLength is NULL, then ASSERT().
451 If HostAdapterStatus is NULL, then ASSERT().
452 If TargetStatus is NULL, then ASSERT().
453 If DataLength is NULL, then ASSERT().
454
455 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
456 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
457 gets returned.
458
459 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
460 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
461 gets returned.
462
463 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
464 for the specific SCSI target.
465 @param[in] Timeout The timeout in 100 ns units to use for the
466 execution of this SCSI Request Packet. A Timeout
467 value of zero means that this function will wait
468 indefinitely for the SCSI Request Packet to execute.
469 If Timeout is greater than zero, then this function
470 will return EFI_TIMEOUT if the time required to
471 execute the SCSI Request Packet is greater than Timeout.
472 @param[in, out] SenseData A pointer to sense data that was generated
473 by the execution of the SCSI Request Packet.
474 This buffer must be allocated by the caller.
475 If SenseDataLength is 0, then this parameter
476 is optional and may be NULL.
477 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
478 On output, the number of bytes written to the SenseData buffer.
479 @param[out] HostAdapterStatus The status of the SCSI Host Controller that
480 produces the SCSI bus containing the SCSI target
481 specified by ScsiIo when the SCSI Request Packet
482 was executed. See the EFI SCSI I/O Protocol in the
483 UEFI Specification for details on the possible
484 return values.
485 @param[out] TargetStatus The status returned by the SCSI target specified
486 by ScsiIo when the SCSI Request Packet was executed
487 on the SCSI Host Controller. See the EFI SCSI
488 I/O Protocol in the UEFI Specification for details
489 on the possible return values.
490 @param[in, out] DataBuffer A pointer to data that was generated by the
491 execution of the SCSI Request Packet. This
492 buffer must be allocated by the caller. If
493 DataLength is 0, then this parameter is optional
494 and may be NULL.
495 @param[in, out] DataLength On input, a pointer to the length in bytes of
496 the DataBuffer buffer. On output, a pointer
497 to the number of bytes written to the DataBuffer
498 buffer.
499 @param[in] DBDField Specifies the DBD field of the CDB for this SCSI Command.
500 @param[in] PageControl Specifies the PC field of the CDB for this SCSI Command.
501 @param[in] PageCode Specifies the Page Control field of the CDB for this SCSI Command.
502
503 @retval EFI_SUCCESS The command was executed successfully.
504 See HostAdapterStatus, TargetStatus, SenseDataLength,
505 and SenseData in that order for additional status information.
506 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the
507 entire DataBuffer could not be transferred.
508 The actual number of bytes transferred is returned
509 in DataLength.
510 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
511 there are too many SCSI Command Packets already queued.
512 The SCSI Request Packet was not sent, so no additional
513 status information is available. The caller may retry
514 again later.
515 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
516 SCSI Request Packet. See HostAdapterStatus, TargetStatus,
517 SenseDataLength, and SenseData in that order for
518 additional status information.
519 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
520 is not supported by the SCSI initiator(i.e., SCSI
521 Host Controller). The SCSI Request Packet was not
522 sent, so no additional status information is available.
523 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
524 Request Packet to execute. See HostAdapterStatus,
525 TargetStatus, SenseDataLength, and SenseData in that
526 order for additional status information.
527 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
528
529 **/
530 EFI_STATUS
531 EFIAPI
532 ScsiModeSense10Command (
533 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
534 IN UINT64 Timeout,
535 IN OUT VOID *SenseData, OPTIONAL
536 IN OUT UINT8 *SenseDataLength,
537 OUT UINT8 *HostAdapterStatus,
538 OUT UINT8 *TargetStatus,
539 IN OUT VOID *DataBuffer, OPTIONAL
540 IN OUT UINT32 *DataLength,
541 IN UINT8 DBDField, OPTIONAL
542 IN UINT8 PageControl,
543 IN UINT8 PageCode
544 )
545 {
546 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
547 EFI_STATUS Status;
548 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
549
550 ASSERT (SenseDataLength != NULL);
551 ASSERT (HostAdapterStatus != NULL);
552 ASSERT (TargetStatus != NULL);
553 ASSERT (DataLength != NULL);
554 ASSERT (ScsiIo != NULL);
555
556 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
557 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
558
559 CommandPacket.Timeout = Timeout;
560 CommandPacket.InDataBuffer = DataBuffer;
561 CommandPacket.SenseData = SenseData;
562 CommandPacket.InTransferLength= *DataLength;
563 CommandPacket.Cdb = Cdb;
564 //
565 // Fill Cdb for Mode Sense (10) Command
566 //
567 Cdb[0] = EFI_SCSI_OP_MODE_SEN10;
568 //
569 // DBDField is in Cdb[1] bit3 of (bit7..0)
570 //
571 Cdb[1] = (UINT8) ((DBDField << 3) & 0x08);
572 //
573 // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0
574 //
575 Cdb[2] = (UINT8) (((PageControl << 6) & 0xc0) | (PageCode & 0x3f));
576 Cdb[7] = (UINT8) (*DataLength >> 8);
577 Cdb[8] = (UINT8) (*DataLength);
578
579 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
580 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
581 CommandPacket.SenseDataLength = *SenseDataLength;
582
583 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
584
585 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
586 *TargetStatus = CommandPacket.TargetStatus;
587 *SenseDataLength = CommandPacket.SenseDataLength;
588 *DataLength = CommandPacket.InTransferLength;
589
590 return Status;
591 }
592
593
594 /**
595 Execute Request Sense SCSI command on a specific SCSI target.
596
597 Executes the Request Sense command on the SCSI target specified by ScsiIo.
598 If Timeout is zero, then this function waits indefinitely for the command to complete.
599 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
600 If ScsiIo is NULL, then ASSERT().
601 If SenseDataLength is NULL, then ASSERT().
602 If HostAdapterStatus is NULL, then ASSERT().
603 If TargetStatus is NULL, then ASSERT().
604
605 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
606 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
607 gets returned.
608
609 @param[in] ScsiIo A pointer to SCSI IO protocol.
610 @param[in] Timeout The length of timeout period.
611 @param[in, out] SenseData A pointer to output sense data.
612 @param[in, out] SenseDataLength The length of output sense data.
613 @param[out] HostAdapterStatus The status of Host Adapter.
614 @param[out] TargetStatus The status of the target.
615
616 @retval EFI_SUCCESS Command is executed successfully.
617 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are
618 too many SCSI Command Packets already queued.
619 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
620 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
621 the SCSI initiator(i.e., SCSI Host Controller)
622 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
623 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
624
625 **/
626 EFI_STATUS
627 EFIAPI
628 ScsiRequestSenseCommand (
629 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
630 IN UINT64 Timeout,
631 IN OUT VOID *SenseData, OPTIONAL
632 IN OUT UINT8 *SenseDataLength,
633 OUT UINT8 *HostAdapterStatus,
634 OUT UINT8 *TargetStatus
635 )
636 {
637 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
638 EFI_STATUS Status;
639 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
640
641 ASSERT (SenseDataLength != NULL);
642 ASSERT (HostAdapterStatus != NULL);
643 ASSERT (TargetStatus != NULL);
644 ASSERT (ScsiIo != NULL);
645
646 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
647 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
648
649 CommandPacket.Timeout = Timeout;
650 CommandPacket.InDataBuffer = SenseData;
651 CommandPacket.SenseData = NULL;
652 CommandPacket.InTransferLength= *SenseDataLength;
653 CommandPacket.Cdb = Cdb;
654 //
655 // Fill Cdb for Request Sense Command
656 //
657 Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;
658 Cdb[4] = (UINT8) (*SenseDataLength);
659
660 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
661 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
662 CommandPacket.SenseDataLength = 0;
663
664 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
665
666 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
667 *TargetStatus = CommandPacket.TargetStatus;
668 *SenseDataLength = (UINT8) CommandPacket.InTransferLength;
669
670 return Status;
671 }
672
673
674 /**
675 Execute Read Capacity SCSI command on a specific SCSI target.
676
677 Executes the SCSI Read Capacity command on the SCSI target specified by ScsiIo.
678 If Timeout is zero, then this function waits indefinitely for the command to complete.
679 If Timeout is greater than zero, then the command is executed and will timeout after
680 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.
681 If ScsiIo is NULL, then ASSERT().
682 If SenseDataLength is NULL, then ASSERT().
683 If HostAdapterStatus is NULL, then ASSERT().
684 If TargetStatus is NULL, then ASSERT().
685 If DataLength is NULL, then ASSERT().
686
687 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
688 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
689 gets returned.
690
691 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
692 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
693 gets returned.
694
695 @param[in] ScsiIo A pointer to SCSI IO protocol.
696 @param[in] Timeout The length of timeout period.
697 @param[in, out] SenseData A pointer to output sense data.
698 @param[in, out] SenseDataLength The length of output sense data.
699 @param[out] HostAdapterStatus The status of Host Adapter.
700 @param[out] TargetStatus The status of the target.
701 @param[in, out] DataBuffer A pointer to a data buffer.
702 @param[in, out] DataLength The length of data buffer.
703 @param[in] Pmi Partial medium indicator.
704
705 @retval EFI_SUCCESS Command is executed successfully.
706 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
707 DataBuffer could not be transferred. The actual
708 number of bytes transferred is returned in DataLength.
709 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
710 there are too many SCSI Command Packets already queued.
711 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
712 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
713 is not supported by the SCSI initiator(i.e., SCSI Host Controller)
714 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
715 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
716
717 **/
718 EFI_STATUS
719 EFIAPI
720 ScsiReadCapacityCommand (
721 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
722 IN UINT64 Timeout,
723 IN OUT VOID *SenseData, OPTIONAL
724 IN OUT UINT8 *SenseDataLength,
725 OUT UINT8 *HostAdapterStatus,
726 OUT UINT8 *TargetStatus,
727 IN OUT VOID *DataBuffer, OPTIONAL
728 IN OUT UINT32 *DataLength,
729 IN BOOLEAN Pmi
730 )
731 {
732 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
733 EFI_STATUS Status;
734 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
735
736 ASSERT (SenseDataLength != NULL);
737 ASSERT (HostAdapterStatus != NULL);
738 ASSERT (TargetStatus != NULL);
739 ASSERT (DataLength != NULL);
740 ASSERT (ScsiIo != NULL);
741
742 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
743 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
744
745 CommandPacket.Timeout = Timeout;
746 CommandPacket.InDataBuffer = DataBuffer;
747 CommandPacket.SenseData = SenseData;
748 CommandPacket.InTransferLength= *DataLength;
749 CommandPacket.Cdb = Cdb;
750 //
751 // Fill Cdb for Read Capacity Command
752 //
753 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;
754 if (!Pmi) {
755 //
756 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
757 //
758 ZeroMem ((Cdb + 2), 4);
759 } else {
760 Cdb[8] |= 0x01;
761 }
762
763 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
764 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
765 CommandPacket.SenseDataLength = *SenseDataLength;
766
767 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
768
769 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
770 *TargetStatus = CommandPacket.TargetStatus;
771 *SenseDataLength = CommandPacket.SenseDataLength;
772 *DataLength = CommandPacket.InTransferLength;
773
774 return Status;
775 }
776
777
778 /**
779 Execute Read Capacity SCSI 16 command on a specific SCSI target.
780
781 Executes the SCSI Read Capacity 16 command on the SCSI target specified by ScsiIo.
782 If Timeout is zero, then this function waits indefinitely for the command to complete.
783 If Timeout is greater than zero, then the command is executed and will timeout after
784 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.
785 If ScsiIo is NULL, then ASSERT().
786 If SenseDataLength is NULL, then ASSERT().
787 If HostAdapterStatus is NULL, then ASSERT().
788 If TargetStatus is NULL, then ASSERT().
789 If DataLength is NULL, then ASSERT().
790
791 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
792 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
793 gets returned.
794
795 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
796 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
797 gets returned.
798
799 @param[in] ScsiIo A pointer to SCSI IO protocol.
800 @param[in] Timeout The length of timeout period.
801 @param[in, out] SenseData A pointer to output sense data.
802 @param[in, out] SenseDataLength The length of output sense data.
803 @param[out] HostAdapterStatus The status of Host Adapter.
804 @param[out] TargetStatus The status of the target.
805 @param[in, out] DataBuffer A pointer to a data buffer.
806 @param[in, out] DataLength The length of data buffer.
807 @param[in] Pmi Partial medium indicator.
808
809 @retval EFI_SUCCESS Command is executed successfully.
810 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
811 DataBuffer could not be transferred. The actual
812 number of bytes transferred is returned in DataLength.
813 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
814 there are too many SCSI Command Packets already queued.
815 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
816 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
817 is not supported by the SCSI initiator(i.e., SCSI Host Controller)
818 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
819 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
820
821 **/
822 EFI_STATUS
823 EFIAPI
824 ScsiReadCapacity16Command (
825 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
826 IN UINT64 Timeout,
827 IN OUT VOID *SenseData, OPTIONAL
828 IN OUT UINT8 *SenseDataLength,
829 OUT UINT8 *HostAdapterStatus,
830 OUT UINT8 *TargetStatus,
831 IN OUT VOID *DataBuffer, OPTIONAL
832 IN OUT UINT32 *DataLength,
833 IN BOOLEAN Pmi
834 )
835 {
836 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
837 EFI_STATUS Status;
838 UINT8 Cdb[16];
839
840 ASSERT (SenseDataLength != NULL);
841 ASSERT (HostAdapterStatus != NULL);
842 ASSERT (TargetStatus != NULL);
843 ASSERT (DataLength != NULL);
844 ASSERT (ScsiIo != NULL);
845
846 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
847 ZeroMem (Cdb, 16);
848
849 CommandPacket.Timeout = Timeout;
850 CommandPacket.InDataBuffer = DataBuffer;
851 CommandPacket.SenseData = SenseData;
852 CommandPacket.InTransferLength= *DataLength;
853 CommandPacket.Cdb = Cdb;
854 //
855 // Fill Cdb for Read Capacity Command
856 //
857 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16;
858 Cdb[1] = 0x10;
859 if (!Pmi) {
860 //
861 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO.
862 //
863 ZeroMem ((Cdb + 2), 8);
864 } else {
865 Cdb[14] |= 0x01;
866 }
867
868 Cdb[13] = 0x20;
869 CommandPacket.CdbLength = 16;
870 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
871 CommandPacket.SenseDataLength = *SenseDataLength;
872
873 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
874
875 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
876 *TargetStatus = CommandPacket.TargetStatus;
877 *SenseDataLength = CommandPacket.SenseDataLength;
878 *DataLength = CommandPacket.InTransferLength;
879
880 return Status;
881 }
882
883
884 /**
885 Execute Read(10) SCSI command on a specific SCSI target.
886
887 Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.
888 If Timeout is zero, then this function waits indefinitely for the command to complete.
889 If Timeout is greater than zero, then the command is executed and will timeout
890 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to
891 construct the CDB for this SCSI command.
892 If ScsiIo is NULL, then ASSERT().
893 If SenseDataLength is NULL, then ASSERT().
894 If HostAdapterStatus is NULL, then ASSERT().
895 If TargetStatus is NULL, then ASSERT().
896 If DataLength is NULL, then ASSERT().
897
898 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
899 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
900 gets returned.
901
902 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
903 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
904 gets returned.
905
906 @param[in] ScsiIo A pointer to SCSI IO protocol.
907 @param[in] Timeout The length of timeout period.
908 @param[in, out] SenseData A pointer to output sense data.
909 @param[in, out] SenseDataLength The length of output sense data.
910 @param[out] HostAdapterStatus The status of Host Adapter.
911 @param[out] TargetStatus The status of the target.
912 @param[in, out] DataBuffer Read 10 command data.
913 @param[in, out] DataLength The length of data buffer.
914 @param[in] StartLba The start address of LBA.
915 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.
916
917 @retval EFI_SUCCESS Command is executed successfully.
918 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
919 not be transferred. The actual number of bytes transferred is returned in DataLength.
920 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
921 SCSI Command Packets already queued.
922 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
923 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
924 the SCSI initiator(i.e., SCSI Host Controller)
925 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
926 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
927
928 **/
929 EFI_STATUS
930 EFIAPI
931 ScsiRead10Command (
932 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
933 IN UINT64 Timeout,
934 IN OUT VOID *SenseData, OPTIONAL
935 IN OUT UINT8 *SenseDataLength,
936 OUT UINT8 *HostAdapterStatus,
937 OUT UINT8 *TargetStatus,
938 IN OUT VOID *DataBuffer, OPTIONAL
939 IN OUT UINT32 *DataLength,
940 IN UINT32 StartLba,
941 IN UINT32 SectorSize
942 )
943 {
944 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
945 EFI_STATUS Status;
946 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
947
948 ASSERT (SenseDataLength != NULL);
949 ASSERT (HostAdapterStatus != NULL);
950 ASSERT (TargetStatus != NULL);
951 ASSERT (DataLength != NULL);
952 ASSERT (ScsiIo != NULL);
953
954 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
955 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
956
957 CommandPacket.Timeout = Timeout;
958 CommandPacket.InDataBuffer = DataBuffer;
959 CommandPacket.SenseData = SenseData;
960 CommandPacket.InTransferLength= *DataLength;
961 CommandPacket.Cdb = Cdb;
962 //
963 // Fill Cdb for Read (10) Command
964 //
965 Cdb[0] = EFI_SCSI_OP_READ10;
966 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));
967 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));
968
969 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
970 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
971 CommandPacket.SenseDataLength = *SenseDataLength;
972
973 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
974
975 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
976 *TargetStatus = CommandPacket.TargetStatus;
977 *SenseDataLength = CommandPacket.SenseDataLength;
978 *DataLength = CommandPacket.InTransferLength;
979
980 return Status;
981 }
982
983
984 /**
985 Execute Write(10) SCSI command on a specific SCSI target.
986
987 Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.
988 If Timeout is zero, then this function waits indefinitely for the command to complete.
989 If Timeout is greater than zero, then the command is executed and will timeout after
990 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct
991 the CDB for this SCSI command.
992 If ScsiIo is NULL, then ASSERT().
993 If SenseDataLength is NULL, then ASSERT().
994 If HostAdapterStatus is NULL, then ASSERT().
995 If TargetStatus is NULL, then ASSERT().
996 If DataLength is NULL, then ASSERT().
997
998 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
999 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
1000 gets returned.
1001
1002 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
1003 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
1004 gets returned.
1005
1006 @param[in] ScsiIo SCSI IO Protocol to use
1007 @param[in] Timeout The length of timeout period.
1008 @param[in, out] SenseData A pointer to output sense data.
1009 @param[in, out] SenseDataLength The length of output sense data.
1010 @param[out] HostAdapterStatus The status of Host Adapter.
1011 @param[out] TargetStatus The status of the target.
1012 @param[in, out] DataBuffer A pointer to a data buffer.
1013 @param[in, out] DataLength The length of data buffer.
1014 @param[in] StartLba The start address of LBA.
1015 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.
1016
1017 @retval EFI_SUCCESS Command is executed successfully.
1018 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
1019 not be transferred. The actual number of bytes transferred is returned in DataLength.
1020 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
1021 SCSI Command Packets already queued.
1022 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
1023 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
1024 the SCSI initiator(i.e., SCSI Host Controller)
1025 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
1026 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
1027
1028 **/
1029 EFI_STATUS
1030 EFIAPI
1031 ScsiWrite10Command (
1032 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
1033 IN UINT64 Timeout,
1034 IN OUT VOID *SenseData, OPTIONAL
1035 IN OUT UINT8 *SenseDataLength,
1036 OUT UINT8 *HostAdapterStatus,
1037 OUT UINT8 *TargetStatus,
1038 IN OUT VOID *DataBuffer, OPTIONAL
1039 IN OUT UINT32 *DataLength,
1040 IN UINT32 StartLba,
1041 IN UINT32 SectorSize
1042 )
1043 {
1044 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
1045 EFI_STATUS Status;
1046 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
1047
1048 ASSERT (SenseDataLength != NULL);
1049 ASSERT (HostAdapterStatus != NULL);
1050 ASSERT (TargetStatus != NULL);
1051 ASSERT (DataLength != NULL);
1052 ASSERT (ScsiIo != NULL);
1053
1054 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
1055 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
1056
1057 CommandPacket.Timeout = Timeout;
1058 CommandPacket.OutDataBuffer = DataBuffer;
1059 CommandPacket.SenseData = SenseData;
1060 CommandPacket.OutTransferLength= *DataLength;
1061 CommandPacket.Cdb = Cdb;
1062 //
1063 // Fill Cdb for Write (10) Command
1064 //
1065 Cdb[0] = EFI_SCSI_OP_WRITE10;
1066 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));
1067 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));
1068
1069 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
1070 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;
1071 CommandPacket.SenseDataLength = *SenseDataLength;
1072
1073 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
1074
1075 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
1076 *TargetStatus = CommandPacket.TargetStatus;
1077 *SenseDataLength = CommandPacket.SenseDataLength;
1078 *DataLength = CommandPacket.OutTransferLength;
1079
1080 return Status;
1081 }
1082
1083 /**
1084 Execute Read(16) SCSI command on a specific SCSI target.
1085
1086 Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo.
1087 If Timeout is zero, then this function waits indefinitely for the command to complete.
1088 If Timeout is greater than zero, then the command is executed and will timeout
1089 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to
1090 construct the CDB for this SCSI command.
1091 If ScsiIo is NULL, then ASSERT().
1092 If SenseDataLength is NULL, then ASSERT().
1093 If HostAdapterStatus is NULL, then ASSERT().
1094 If TargetStatus is NULL, then ASSERT().
1095 If DataLength is NULL, then ASSERT().
1096
1097 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
1098 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
1099 gets returned.
1100
1101 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
1102 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
1103 gets returned.
1104
1105 @param[in] ScsiIo A pointer to SCSI IO protocol.
1106 @param[in] Timeout The length of timeout period.
1107 @param[in, out] SenseData A pointer to output sense data.
1108 @param[in, out] SenseDataLength The length of output sense data.
1109 @param[out] HostAdapterStatus The status of Host Adapter.
1110 @param[out] TargetStatus The status of the target.
1111 @param[in, out] DataBuffer Read 16 command data.
1112 @param[in, out] DataLength The length of data buffer.
1113 @param[in] StartLba The start address of LBA.
1114 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.
1115
1116 @retval EFI_SUCCESS Command is executed successfully.
1117 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
1118 not be transferred. The actual number of bytes transferred is returned in DataLength.
1119 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
1120 SCSI Command Packets already queued.
1121 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
1122 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
1123 the SCSI initiator(i.e., SCSI Host Controller)
1124 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
1125 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
1126
1127 **/
1128 EFI_STATUS
1129 EFIAPI
1130 ScsiRead16Command (
1131 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
1132 IN UINT64 Timeout,
1133 IN OUT VOID *SenseData, OPTIONAL
1134 IN OUT UINT8 *SenseDataLength,
1135 OUT UINT8 *HostAdapterStatus,
1136 OUT UINT8 *TargetStatus,
1137 IN OUT VOID *DataBuffer, OPTIONAL
1138 IN OUT UINT32 *DataLength,
1139 IN UINT64 StartLba,
1140 IN UINT32 SectorSize
1141 )
1142 {
1143 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
1144 EFI_STATUS Status;
1145 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN];
1146
1147 ASSERT (SenseDataLength != NULL);
1148 ASSERT (HostAdapterStatus != NULL);
1149 ASSERT (TargetStatus != NULL);
1150 ASSERT (DataLength != NULL);
1151 ASSERT (ScsiIo != NULL);
1152
1153 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
1154 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN);
1155
1156 CommandPacket.Timeout = Timeout;
1157 CommandPacket.InDataBuffer = DataBuffer;
1158 CommandPacket.SenseData = SenseData;
1159 CommandPacket.InTransferLength = *DataLength;
1160 CommandPacket.Cdb = Cdb;
1161 //
1162 // Fill Cdb for Read (16) Command
1163 //
1164 Cdb[0] = EFI_SCSI_OP_READ16;
1165 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
1166 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));
1167
1168 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;
1169 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
1170 CommandPacket.SenseDataLength = *SenseDataLength;
1171
1172 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
1173
1174 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
1175 *TargetStatus = CommandPacket.TargetStatus;
1176 *SenseDataLength = CommandPacket.SenseDataLength;
1177 *DataLength = CommandPacket.InTransferLength;
1178
1179 return Status;
1180 }
1181
1182
1183 /**
1184 Execute Write(16) SCSI command on a specific SCSI target.
1185
1186 Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo.
1187 If Timeout is zero, then this function waits indefinitely for the command to complete.
1188 If Timeout is greater than zero, then the command is executed and will timeout after
1189 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct
1190 the CDB for this SCSI command.
1191 If ScsiIo is NULL, then ASSERT().
1192 If SenseDataLength is NULL, then ASSERT().
1193 If HostAdapterStatus is NULL, then ASSERT().
1194 If TargetStatus is NULL, then ASSERT().
1195 If DataLength is NULL, then ASSERT().
1196
1197 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
1198 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
1199 gets returned.
1200
1201 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
1202 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
1203 gets returned.
1204
1205 @param[in] ScsiIo SCSI IO Protocol to use
1206 @param[in] Timeout The length of timeout period.
1207 @param[in, out] SenseData A pointer to output sense data.
1208 @param[in, out] SenseDataLength The length of output sense data.
1209 @param[out] HostAdapterStatus The status of Host Adapter.
1210 @param[out] TargetStatus The status of the target.
1211 @param[in, out] DataBuffer A pointer to a data buffer.
1212 @param[in, out] DataLength The length of data buffer.
1213 @param[in] StartLba The start address of LBA.
1214 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.
1215
1216 @retval EFI_SUCCESS Command is executed successfully.
1217 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
1218 not be transferred. The actual number of bytes transferred is returned in DataLength.
1219 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
1220 SCSI Command Packets already queued.
1221 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
1222 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
1223 the SCSI initiator(i.e., SCSI Host Controller)
1224 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
1225 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
1226
1227 **/
1228 EFI_STATUS
1229 EFIAPI
1230 ScsiWrite16Command (
1231 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
1232 IN UINT64 Timeout,
1233 IN OUT VOID *SenseData, OPTIONAL
1234 IN OUT UINT8 *SenseDataLength,
1235 OUT UINT8 *HostAdapterStatus,
1236 OUT UINT8 *TargetStatus,
1237 IN OUT VOID *DataBuffer, OPTIONAL
1238 IN OUT UINT32 *DataLength,
1239 IN UINT64 StartLba,
1240 IN UINT32 SectorSize
1241 )
1242 {
1243 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
1244 EFI_STATUS Status;
1245 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN];
1246
1247 ASSERT (SenseDataLength != NULL);
1248 ASSERT (HostAdapterStatus != NULL);
1249 ASSERT (TargetStatus != NULL);
1250 ASSERT (DataLength != NULL);
1251 ASSERT (ScsiIo != NULL);
1252
1253 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
1254 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN);
1255
1256 CommandPacket.Timeout = Timeout;
1257 CommandPacket.OutDataBuffer = DataBuffer;
1258 CommandPacket.SenseData = SenseData;
1259 CommandPacket.OutTransferLength = *DataLength;
1260 CommandPacket.Cdb = Cdb;
1261 //
1262 // Fill Cdb for Write (16) Command
1263 //
1264 Cdb[0] = EFI_SCSI_OP_WRITE16;
1265 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
1266 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));
1267
1268 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;
1269 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;
1270 CommandPacket.SenseDataLength = *SenseDataLength;
1271
1272 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
1273
1274 *HostAdapterStatus = CommandPacket.HostAdapterStatus;
1275 *TargetStatus = CommandPacket.TargetStatus;
1276 *SenseDataLength = CommandPacket.SenseDataLength;
1277 *DataLength = CommandPacket.OutTransferLength;
1278
1279 return Status;
1280 }
1281
1282
1283 /**
1284 Internal helper notify function in which update the result of the
1285 non-blocking SCSI Read/Write commands and signal caller event.
1286
1287 @param Event The instance of EFI_EVENT.
1288 @param Context The parameter passed in.
1289
1290 **/
1291 VOID
1292 EFIAPI
1293 ScsiLibNotify (
1294 IN EFI_EVENT Event,
1295 IN VOID *Context
1296 )
1297 {
1298 EFI_SCSI_LIB_ASYNC_CONTEXT *LibContext;
1299 EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
1300 EFI_EVENT CallerEvent;
1301
1302 LibContext = (EFI_SCSI_LIB_ASYNC_CONTEXT *) Context;
1303 CommandPacket = &LibContext->CommandPacket;
1304 CallerEvent = LibContext->CallerEvent;
1305
1306 //
1307 // Update SCSI Read/Write operation results
1308 //
1309 *LibContext->SenseDataLength = CommandPacket->SenseDataLength;
1310 *LibContext->HostAdapterStatus = CommandPacket->HostAdapterStatus;
1311 *LibContext->TargetStatus = CommandPacket->TargetStatus;
1312 if (CommandPacket->InDataBuffer != NULL) {
1313 *LibContext->DataLength = CommandPacket->InTransferLength;
1314 } else {
1315 *LibContext->DataLength = CommandPacket->OutTransferLength;
1316 }
1317
1318 if (CommandPacket->Cdb != NULL) {
1319 FreePool (CommandPacket->Cdb);
1320 }
1321 FreePool (Context);
1322
1323 gBS->CloseEvent (Event);
1324 gBS->SignalEvent (CallerEvent);
1325 }
1326
1327
1328 /**
1329 Execute blocking/non-blocking Read(10) SCSI command on a specific SCSI
1330 target.
1331
1332 Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.
1333 When Event is NULL, blocking command will be executed. Otherwise non-blocking
1334 command will be executed.
1335 For blocking I/O, if Timeout is zero, this function will wait indefinitely
1336 for the command to complete. If Timeout is greater than zero, then the
1337 command is executed and will timeout after Timeout 100 ns units.
1338 For non-blocking I/O, if Timeout is zero, Event will be signaled only after
1339 the command to completes. If Timeout is greater than zero, Event will also be
1340 signaled after Timeout 100 ns units.
1341 The StartLba and SectorSize parameters are used to construct the CDB for this
1342 SCSI command.
1343
1344 If ScsiIo is NULL, then ASSERT().
1345 If SenseDataLength is NULL, then ASSERT().
1346 If HostAdapterStatus is NULL, then ASSERT().
1347 If TargetStatus is NULL, then ASSERT().
1348 If DataLength is NULL, then ASSERT().
1349
1350 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
1351 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
1352 EFI_INVALID_PARAMETER gets returned.
1353
1354 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
1355 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
1356 EFI_INVALID_PARAMETER gets returned.
1357
1358 @param[in] ScsiIo A pointer to SCSI IO protocol.
1359 @param[in] Timeout The length of timeout period.
1360 @param[in, out] SenseData A pointer to output sense data.
1361 @param[in, out] SenseDataLength The length of output sense data.
1362 @param[out] HostAdapterStatus The status of Host Adapter.
1363 @param[out] TargetStatus The status of the target.
1364 @param[in, out] DataBuffer Read 16 command data.
1365 @param[in, out] DataLength The length of data buffer.
1366 @param[in] StartLba The start address of LBA.
1367 @param[in] SectorSize The number of contiguous logical blocks
1368 of data that shall be transferred.
1369 @param[in] Event If the SCSI target does not support
1370 non-blocking I/O, then Event is ignored,
1371 and blocking I/O is performed. If Event
1372 is NULL, then blocking I/O is performed.
1373 If Event is not NULL and non-blocking
1374 I/O is supported, then non-blocking I/O
1375 is performed, and Event will be signaled
1376 when the SCSI Read(10) command
1377 completes.
1378
1379 @retval EFI_SUCCESS Command is executed successfully.
1380 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
1381 but the entire DataBuffer could not be
1382 transferred. The actual number of bytes
1383 transferred is returned in DataLength.
1384 @retval EFI_NOT_READY The SCSI Request Packet could not be
1385 sent because there are too many SCSI
1386 Command Packets already queued.
1387 @retval EFI_DEVICE_ERROR A device error occurred while attempting
1388 to send SCSI Request Packet.
1389 @retval EFI_UNSUPPORTED The command described by the SCSI
1390 Request Packet is not supported by the
1391 SCSI initiator(i.e., SCSI Host
1392 Controller)
1393 @retval EFI_TIMEOUT A timeout occurred while waiting for the
1394 SCSI Request Packet to execute.
1395 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
1396 are invalid.
1397 @retval EFI_OUT_OF_RESOURCES The request could not be completed due
1398 to a lack of resources.
1399
1400 **/
1401 EFI_STATUS
1402 EFIAPI
1403 ScsiRead10CommandEx (
1404 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
1405 IN UINT64 Timeout,
1406 IN OUT VOID *SenseData, OPTIONAL
1407 IN OUT UINT8 *SenseDataLength,
1408 OUT UINT8 *HostAdapterStatus,
1409 OUT UINT8 *TargetStatus,
1410 IN OUT VOID *DataBuffer, OPTIONAL
1411 IN OUT UINT32 *DataLength,
1412 IN UINT32 StartLba,
1413 IN UINT32 SectorSize,
1414 IN EFI_EVENT Event OPTIONAL
1415 )
1416 {
1417 EFI_SCSI_LIB_ASYNC_CONTEXT *Context;
1418 EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
1419 EFI_STATUS Status;
1420 UINT8 *Cdb;
1421 EFI_EVENT SelfEvent;
1422
1423 if (Event == NULL) {
1424 return ScsiRead10Command (
1425 ScsiIo,
1426 Timeout,
1427 SenseData,
1428 SenseDataLength,
1429 HostAdapterStatus,
1430 TargetStatus,
1431 DataBuffer,
1432 DataLength,
1433 StartLba,
1434 SectorSize
1435 );
1436 }
1437
1438 ASSERT (SenseDataLength != NULL);
1439 ASSERT (HostAdapterStatus != NULL);
1440 ASSERT (TargetStatus != NULL);
1441 ASSERT (DataLength != NULL);
1442 ASSERT (ScsiIo != NULL);
1443
1444 Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));
1445 if (Context == NULL) {
1446 return EFI_OUT_OF_RESOURCES;
1447 }
1448
1449 Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_TEN);
1450 if (Cdb == NULL) {
1451 Status = EFI_OUT_OF_RESOURCES;
1452 goto ErrorExit;
1453 }
1454
1455 Context->SenseDataLength = SenseDataLength;
1456 Context->HostAdapterStatus = HostAdapterStatus;
1457 Context->TargetStatus = TargetStatus;
1458 Context->CallerEvent = Event;
1459
1460 CommandPacket = &Context->CommandPacket;
1461 CommandPacket->Timeout = Timeout;
1462 CommandPacket->InDataBuffer = DataBuffer;
1463 CommandPacket->SenseData = SenseData;
1464 CommandPacket->InTransferLength = *DataLength;
1465 CommandPacket->Cdb = Cdb;
1466 //
1467 // Fill Cdb for Read (10) Command
1468 //
1469 Cdb[0] = EFI_SCSI_OP_READ10;
1470 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));
1471 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));
1472
1473 CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_TEN;
1474 CommandPacket->DataDirection = EFI_SCSI_DATA_IN;
1475 CommandPacket->SenseDataLength = *SenseDataLength;
1476
1477 //
1478 // Create Event
1479 //
1480 Status = gBS->CreateEvent (
1481 EVT_NOTIFY_SIGNAL,
1482 TPL_NOTIFY,
1483 ScsiLibNotify,
1484 Context,
1485 &SelfEvent
1486 );
1487 if (EFI_ERROR(Status)) {
1488 goto ErrorExit;
1489 }
1490
1491 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);
1492 if (EFI_ERROR(Status)) {
1493 //
1494 // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()
1495 // returns with error, close the event here.
1496 //
1497 gBS->CloseEvent (SelfEvent);
1498 goto ErrorExit;
1499 } else {
1500 return EFI_SUCCESS;
1501 }
1502
1503 ErrorExit:
1504 if (Context != NULL) {
1505 FreePool (Context);
1506 }
1507
1508 return Status;
1509 }
1510
1511
1512 /**
1513 Execute blocking/non-blocking Write(10) SCSI command on a specific SCSI
1514 target.
1515
1516 Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.
1517 When Event is NULL, blocking command will be executed. Otherwise non-blocking
1518 command will be executed.
1519 For blocking I/O, if Timeout is zero, this function will wait indefinitely
1520 for the command to complete. If Timeout is greater than zero, then the
1521 command is executed and will timeout after Timeout 100 ns units.
1522 For non-blocking I/O, if Timeout is zero, Event will be signaled only after
1523 the command to completes. If Timeout is greater than zero, Event will also be
1524 signaled after Timeout 100 ns units.
1525 The StartLba and SectorSize parameters are used to construct the CDB for this
1526 SCSI command.
1527
1528 If ScsiIo is NULL, then ASSERT().
1529 If SenseDataLength is NULL, then ASSERT().
1530 If HostAdapterStatus is NULL, then ASSERT().
1531 If TargetStatus is NULL, then ASSERT().
1532 If DataLength is NULL, then ASSERT().
1533
1534 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
1535 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
1536 EFI_INVALID_PARAMETER gets returned.
1537
1538 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
1539 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
1540 EFI_INVALID_PARAMETER gets returned.
1541
1542 @param[in] ScsiIo SCSI IO Protocol to use
1543 @param[in] Timeout The length of timeout period.
1544 @param[in, out] SenseData A pointer to output sense data.
1545 @param[in, out] SenseDataLength The length of output sense data.
1546 @param[out] HostAdapterStatus The status of Host Adapter.
1547 @param[out] TargetStatus The status of the target.
1548 @param[in, out] DataBuffer A pointer to a data buffer.
1549 @param[in, out] DataLength The length of data buffer.
1550 @param[in] StartLba The start address of LBA.
1551 @param[in] SectorSize The number of contiguous logical blocks
1552 of data that shall be transferred.
1553 @param[in] Event If the SCSI target does not support
1554 non-blocking I/O, then Event is ignored,
1555 and blocking I/O is performed. If Event
1556 is NULL, then blocking I/O is performed.
1557 If Event is not NULL and non-blocking
1558 I/O is supported, then non-blocking I/O
1559 is performed, and Event will be signaled
1560 when the SCSI Write(10) command
1561 completes.
1562
1563 @retval EFI_SUCCESS Command is executed successfully.
1564 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
1565 but the entire DataBuffer could not be
1566 transferred. The actual number of bytes
1567 transferred is returned in DataLength.
1568 @retval EFI_NOT_READY The SCSI Request Packet could not be
1569 sent because there are too many SCSI
1570 Command Packets already queued.
1571 @retval EFI_DEVICE_ERROR A device error occurred while attempting
1572 to send SCSI Request Packet.
1573 @retval EFI_UNSUPPORTED The command described by the SCSI
1574 Request Packet is not supported by the
1575 SCSI initiator(i.e., SCSI Host
1576 Controller)
1577 @retval EFI_TIMEOUT A timeout occurred while waiting for the
1578 SCSI Request Packet to execute.
1579 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
1580 are invalid.
1581 @retval EFI_OUT_OF_RESOURCES The request could not be completed due
1582 to a lack of resources.
1583
1584 **/
1585 EFI_STATUS
1586 EFIAPI
1587 ScsiWrite10CommandEx (
1588 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
1589 IN UINT64 Timeout,
1590 IN OUT VOID *SenseData, OPTIONAL
1591 IN OUT UINT8 *SenseDataLength,
1592 OUT UINT8 *HostAdapterStatus,
1593 OUT UINT8 *TargetStatus,
1594 IN OUT VOID *DataBuffer, OPTIONAL
1595 IN OUT UINT32 *DataLength,
1596 IN UINT32 StartLba,
1597 IN UINT32 SectorSize,
1598 IN EFI_EVENT Event OPTIONAL
1599 )
1600 {
1601 EFI_SCSI_LIB_ASYNC_CONTEXT *Context;
1602 EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
1603 EFI_STATUS Status;
1604 UINT8 *Cdb;
1605 EFI_EVENT SelfEvent;
1606
1607 if (Event == NULL) {
1608 return ScsiWrite10Command (
1609 ScsiIo,
1610 Timeout,
1611 SenseData,
1612 SenseDataLength,
1613 HostAdapterStatus,
1614 TargetStatus,
1615 DataBuffer,
1616 DataLength,
1617 StartLba,
1618 SectorSize
1619 );
1620 }
1621
1622 ASSERT (SenseDataLength != NULL);
1623 ASSERT (HostAdapterStatus != NULL);
1624 ASSERT (TargetStatus != NULL);
1625 ASSERT (DataLength != NULL);
1626 ASSERT (ScsiIo != NULL);
1627
1628 Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));
1629 if (Context == NULL) {
1630 return EFI_OUT_OF_RESOURCES;
1631 }
1632
1633 Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_TEN);
1634 if (Cdb == NULL) {
1635 Status = EFI_OUT_OF_RESOURCES;
1636 goto ErrorExit;
1637 }
1638
1639 Context->SenseDataLength = SenseDataLength;
1640 Context->HostAdapterStatus = HostAdapterStatus;
1641 Context->TargetStatus = TargetStatus;
1642 Context->CallerEvent = Event;
1643
1644 CommandPacket = &Context->CommandPacket;
1645 CommandPacket->Timeout = Timeout;
1646 CommandPacket->OutDataBuffer = DataBuffer;
1647 CommandPacket->SenseData = SenseData;
1648 CommandPacket->OutTransferLength = *DataLength;
1649 CommandPacket->Cdb = Cdb;
1650 //
1651 // Fill Cdb for Write (10) Command
1652 //
1653 Cdb[0] = EFI_SCSI_OP_WRITE10;
1654 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));
1655 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));
1656
1657 CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_TEN;
1658 CommandPacket->DataDirection = EFI_SCSI_DATA_OUT;
1659 CommandPacket->SenseDataLength = *SenseDataLength;
1660
1661 //
1662 // Create Event
1663 //
1664 Status = gBS->CreateEvent (
1665 EVT_NOTIFY_SIGNAL,
1666 TPL_NOTIFY,
1667 ScsiLibNotify,
1668 Context,
1669 &SelfEvent
1670 );
1671 if (EFI_ERROR(Status)) {
1672 goto ErrorExit;
1673 }
1674
1675 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);
1676 if (EFI_ERROR(Status)) {
1677 //
1678 // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()
1679 // returns with error, close the event here.
1680 //
1681 gBS->CloseEvent (SelfEvent);
1682 goto ErrorExit;
1683 } else {
1684 return EFI_SUCCESS;
1685 }
1686
1687 ErrorExit:
1688 if (Context != NULL) {
1689 FreePool (Context);
1690 }
1691
1692 return Status;
1693 }
1694
1695
1696 /**
1697 Execute blocking/non-blocking Read(16) SCSI command on a specific SCSI
1698 target.
1699
1700 Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo.
1701 When Event is NULL, blocking command will be executed. Otherwise non-blocking
1702 command will be executed.
1703 For blocking I/O, if Timeout is zero, this function will wait indefinitely
1704 for the command to complete. If Timeout is greater than zero, then the
1705 command is executed and will timeout after Timeout 100 ns units.
1706 For non-blocking I/O, if Timeout is zero, Event will be signaled only after
1707 the command to completes. If Timeout is greater than zero, Event will also be
1708 signaled after Timeout 100 ns units.
1709 The StartLba and SectorSize parameters are used to construct the CDB for this
1710 SCSI command.
1711
1712 If ScsiIo is NULL, then ASSERT().
1713 If SenseDataLength is NULL, then ASSERT().
1714 If HostAdapterStatus is NULL, then ASSERT().
1715 If TargetStatus is NULL, then ASSERT().
1716 If DataLength is NULL, then ASSERT().
1717
1718 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
1719 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
1720 EFI_INVALID_PARAMETER gets returned.
1721
1722 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
1723 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
1724 EFI_INVALID_PARAMETER gets returned.
1725
1726 @param[in] ScsiIo A pointer to SCSI IO protocol.
1727 @param[in] Timeout The length of timeout period.
1728 @param[in, out] SenseData A pointer to output sense data.
1729 @param[in, out] SenseDataLength The length of output sense data.
1730 @param[out] HostAdapterStatus The status of Host Adapter.
1731 @param[out] TargetStatus The status of the target.
1732 @param[in, out] DataBuffer Read 16 command data.
1733 @param[in, out] DataLength The length of data buffer.
1734 @param[in] StartLba The start address of LBA.
1735 @param[in] SectorSize The number of contiguous logical blocks
1736 of data that shall be transferred.
1737 @param[in] Event If the SCSI target does not support
1738 non-blocking I/O, then Event is ignored,
1739 and blocking I/O is performed. If Event
1740 is NULL, then blocking I/O is performed.
1741 If Event is not NULL and non-blocking
1742 I/O is supported, then non-blocking I/O
1743 is performed, and Event will be signaled
1744 when the SCSI Read(16) command
1745 completes.
1746
1747 @retval EFI_SUCCESS Command is executed successfully.
1748 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
1749 but the entire DataBuffer could not be
1750 transferred. The actual number of bytes
1751 transferred is returned in DataLength.
1752 @retval EFI_NOT_READY The SCSI Request Packet could not be
1753 sent because there are too many SCSI
1754 Command Packets already queued.
1755 @retval EFI_DEVICE_ERROR A device error occurred while attempting
1756 to send SCSI Request Packet.
1757 @retval EFI_UNSUPPORTED The command described by the SCSI
1758 Request Packet is not supported by the
1759 SCSI initiator(i.e., SCSI Host
1760 Controller)
1761 @retval EFI_TIMEOUT A timeout occurred while waiting for the
1762 SCSI Request Packet to execute.
1763 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
1764 are invalid.
1765 @retval EFI_OUT_OF_RESOURCES The request could not be completed due
1766 to a lack of resources.
1767
1768 **/
1769 EFI_STATUS
1770 EFIAPI
1771 ScsiRead16CommandEx (
1772 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
1773 IN UINT64 Timeout,
1774 IN OUT VOID *SenseData, OPTIONAL
1775 IN OUT UINT8 *SenseDataLength,
1776 OUT UINT8 *HostAdapterStatus,
1777 OUT UINT8 *TargetStatus,
1778 IN OUT VOID *DataBuffer, OPTIONAL
1779 IN OUT UINT32 *DataLength,
1780 IN UINT64 StartLba,
1781 IN UINT32 SectorSize,
1782 IN EFI_EVENT Event OPTIONAL
1783 )
1784 {
1785 EFI_SCSI_LIB_ASYNC_CONTEXT *Context;
1786 EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
1787 EFI_STATUS Status;
1788 UINT8 *Cdb;
1789 EFI_EVENT SelfEvent;
1790
1791 if (Event == NULL) {
1792 return ScsiRead16Command (
1793 ScsiIo,
1794 Timeout,
1795 SenseData,
1796 SenseDataLength,
1797 HostAdapterStatus,
1798 TargetStatus,
1799 DataBuffer,
1800 DataLength,
1801 StartLba,
1802 SectorSize
1803 );
1804 }
1805
1806 ASSERT (SenseDataLength != NULL);
1807 ASSERT (HostAdapterStatus != NULL);
1808 ASSERT (TargetStatus != NULL);
1809 ASSERT (DataLength != NULL);
1810 ASSERT (ScsiIo != NULL);
1811
1812 Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));
1813 if (Context == NULL) {
1814 return EFI_OUT_OF_RESOURCES;
1815 }
1816
1817 Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_SIXTEEN);
1818 if (Cdb == NULL) {
1819 Status = EFI_OUT_OF_RESOURCES;
1820 goto ErrorExit;
1821 }
1822
1823 Context->SenseDataLength = SenseDataLength;
1824 Context->HostAdapterStatus = HostAdapterStatus;
1825 Context->TargetStatus = TargetStatus;
1826 Context->CallerEvent = Event;
1827
1828 CommandPacket = &Context->CommandPacket;
1829 CommandPacket->Timeout = Timeout;
1830 CommandPacket->InDataBuffer = DataBuffer;
1831 CommandPacket->SenseData = SenseData;
1832 CommandPacket->InTransferLength = *DataLength;
1833 CommandPacket->Cdb = Cdb;
1834 //
1835 // Fill Cdb for Read (16) Command
1836 //
1837 Cdb[0] = EFI_SCSI_OP_READ16;
1838 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
1839 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));
1840
1841 CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;
1842 CommandPacket->DataDirection = EFI_SCSI_DATA_IN;
1843 CommandPacket->SenseDataLength = *SenseDataLength;
1844
1845 //
1846 // Create Event
1847 //
1848 Status = gBS->CreateEvent (
1849 EVT_NOTIFY_SIGNAL,
1850 TPL_NOTIFY,
1851 ScsiLibNotify,
1852 Context,
1853 &SelfEvent
1854 );
1855 if (EFI_ERROR(Status)) {
1856 goto ErrorExit;
1857 }
1858
1859 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);
1860 if (EFI_ERROR(Status)) {
1861 //
1862 // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()
1863 // returns with error, close the event here.
1864 //
1865 gBS->CloseEvent (SelfEvent);
1866 goto ErrorExit;
1867 } else {
1868 return EFI_SUCCESS;
1869 }
1870
1871 ErrorExit:
1872 if (Context != NULL) {
1873 FreePool (Context);
1874 }
1875
1876 return Status;
1877 }
1878
1879
1880 /**
1881 Execute blocking/non-blocking Write(16) SCSI command on a specific SCSI
1882 target.
1883
1884 Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo.
1885 When Event is NULL, blocking command will be executed. Otherwise non-blocking
1886 command will be executed.
1887 For blocking I/O, if Timeout is zero, this function will wait indefinitely
1888 for the command to complete. If Timeout is greater than zero, then the
1889 command is executed and will timeout after Timeout 100 ns units.
1890 For non-blocking I/O, if Timeout is zero, Event will be signaled only after
1891 the command to completes. If Timeout is greater than zero, Event will also be
1892 signaled after Timeout 100 ns units.
1893 The StartLba and SectorSize parameters are used to construct the CDB for this
1894 SCSI command.
1895
1896 If ScsiIo is NULL, then ASSERT().
1897 If SenseDataLength is NULL, then ASSERT().
1898 If HostAdapterStatus is NULL, then ASSERT().
1899 If TargetStatus is NULL, then ASSERT().
1900 If DataLength is NULL, then ASSERT().
1901
1902 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
1903 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
1904 EFI_INVALID_PARAMETER gets returned.
1905
1906 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
1907 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
1908 EFI_INVALID_PARAMETER gets returned.
1909
1910 @param[in] ScsiIo SCSI IO Protocol to use
1911 @param[in] Timeout The length of timeout period.
1912 @param[in, out] SenseData A pointer to output sense data.
1913 @param[in, out] SenseDataLength The length of output sense data.
1914 @param[out] HostAdapterStatus The status of Host Adapter.
1915 @param[out] TargetStatus The status of the target.
1916 @param[in, out] DataBuffer A pointer to a data buffer.
1917 @param[in, out] DataLength The length of data buffer.
1918 @param[in] StartLba The start address of LBA.
1919 @param[in] SectorSize The number of contiguous logical blocks
1920 of data that shall be transferred.
1921 @param[in] Event If the SCSI target does not support
1922 non-blocking I/O, then Event is ignored,
1923 and blocking I/O is performed. If Event
1924 is NULL, then blocking I/O is performed.
1925 If Event is not NULL and non-blocking
1926 I/O is supported, then non-blocking I/O
1927 is performed, and Event will be signaled
1928 when the SCSI Write(16) command
1929 completes.
1930
1931 @retval EFI_SUCCESS Command is executed successfully.
1932 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
1933 but the entire DataBuffer could not be
1934 transferred. The actual number of bytes
1935 transferred is returned in DataLength.
1936 @retval EFI_NOT_READY The SCSI Request Packet could not be
1937 sent because there are too many SCSI
1938 Command Packets already queued.
1939 @retval EFI_DEVICE_ERROR A device error occurred while attempting
1940 to send SCSI Request Packet.
1941 @retval EFI_UNSUPPORTED The command described by the SCSI
1942 Request Packet is not supported by the
1943 SCSI initiator(i.e., SCSI Host
1944 Controller)
1945 @retval EFI_TIMEOUT A timeout occurred while waiting for the
1946 SCSI Request Packet to execute.
1947 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
1948 are invalid.
1949 @retval EFI_OUT_OF_RESOURCES The request could not be completed due
1950 to a lack of resources.
1951
1952 **/
1953 EFI_STATUS
1954 EFIAPI
1955 ScsiWrite16CommandEx (
1956 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
1957 IN UINT64 Timeout,
1958 IN OUT VOID *SenseData, OPTIONAL
1959 IN OUT UINT8 *SenseDataLength,
1960 OUT UINT8 *HostAdapterStatus,
1961 OUT UINT8 *TargetStatus,
1962 IN OUT VOID *DataBuffer, OPTIONAL
1963 IN OUT UINT32 *DataLength,
1964 IN UINT64 StartLba,
1965 IN UINT32 SectorSize,
1966 IN EFI_EVENT Event OPTIONAL
1967 )
1968 {
1969 EFI_SCSI_LIB_ASYNC_CONTEXT *Context;
1970 EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
1971 EFI_STATUS Status;
1972 UINT8 *Cdb;
1973 EFI_EVENT SelfEvent;
1974
1975 if (Event == NULL) {
1976 return ScsiWrite16Command (
1977 ScsiIo,
1978 Timeout,
1979 SenseData,
1980 SenseDataLength,
1981 HostAdapterStatus,
1982 TargetStatus,
1983 DataBuffer,
1984 DataLength,
1985 StartLba,
1986 SectorSize
1987 );
1988 }
1989
1990 ASSERT (SenseDataLength != NULL);
1991 ASSERT (HostAdapterStatus != NULL);
1992 ASSERT (TargetStatus != NULL);
1993 ASSERT (DataLength != NULL);
1994 ASSERT (ScsiIo != NULL);
1995
1996 Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));
1997 if (Context == NULL) {
1998 return EFI_OUT_OF_RESOURCES;
1999 }
2000
2001 Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_SIXTEEN);
2002 if (Cdb == NULL) {
2003 Status = EFI_OUT_OF_RESOURCES;
2004 goto ErrorExit;
2005 }
2006
2007 Context->SenseDataLength = SenseDataLength;
2008 Context->HostAdapterStatus = HostAdapterStatus;
2009 Context->TargetStatus = TargetStatus;
2010 Context->CallerEvent = Event;
2011
2012 CommandPacket = &Context->CommandPacket;
2013 CommandPacket->Timeout = Timeout;
2014 CommandPacket->OutDataBuffer = DataBuffer;
2015 CommandPacket->SenseData = SenseData;
2016 CommandPacket->OutTransferLength = *DataLength;
2017 CommandPacket->Cdb = Cdb;
2018 //
2019 // Fill Cdb for Write (16) Command
2020 //
2021 Cdb[0] = EFI_SCSI_OP_WRITE16;
2022 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
2023 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));
2024
2025 CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;
2026 CommandPacket->DataDirection = EFI_SCSI_DATA_OUT;
2027 CommandPacket->SenseDataLength = *SenseDataLength;
2028
2029 //
2030 // Create Event
2031 //
2032 Status = gBS->CreateEvent (
2033 EVT_NOTIFY_SIGNAL,
2034 TPL_NOTIFY,
2035 ScsiLibNotify,
2036 Context,
2037 &SelfEvent
2038 );
2039 if (EFI_ERROR(Status)) {
2040 goto ErrorExit;
2041 }
2042
2043 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);
2044 if (EFI_ERROR(Status)) {
2045 //
2046 // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()
2047 // returns with error, close the event here.
2048 //
2049 gBS->CloseEvent (SelfEvent);
2050 goto ErrorExit;
2051 } else {
2052 return EFI_SUCCESS;
2053 }
2054
2055 ErrorExit:
2056 if (Context != NULL) {
2057 FreePool (Context);
2058 }
2059
2060 return Status;
2061 }