2 UEFI SCSI Library implementation
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
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>
18 #include <IndustryStandard/Scsi.h>
22 // Scsi Command Length
24 #define EFI_SCSI_OP_LENGTH_SIX 0x6
25 #define EFI_SCSI_OP_LENGTH_TEN 0xa
26 #define EFI_SCSI_OP_LENGTH_SIXTEEN 0x10
29 // The context structure used when non-blocking SCSI read/write operation
34 /// The SCSI request packet to send to the SCSI controller specified by
35 /// the device handle.
37 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
39 /// The length of the output sense data.
41 UINT8
*SenseDataLength
;
43 /// The status of the SCSI host adapter.
45 UINT8
*HostAdapterStatus
;
47 /// The status of the target SCSI device.
51 /// The length of the data buffer for the SCSI read/write command.
55 /// The caller event to be signaled when the SCSI read/write command
58 EFI_EVENT CallerEvent
;
59 } EFI_SCSI_LIB_ASYNC_CONTEXT
;
64 Execute Test Unit Ready SCSI command on a specific SCSI target.
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().
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
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.
106 @retval EFI_SUCCESS The command was executed successfully.
107 See HostAdapterStatus, TargetStatus, SenseDataLength,
108 and SenseData in that order for additional status
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.
132 ScsiTestUnitReadyCommand (
133 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
135 IN OUT VOID
*SenseData
, OPTIONAL
136 IN OUT UINT8
*SenseDataLength
,
137 OUT UINT8
*HostAdapterStatus
,
138 OUT UINT8
*TargetStatus
141 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
143 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_SIX
];
145 ASSERT (SenseDataLength
!= NULL
);
146 ASSERT (HostAdapterStatus
!= NULL
);
147 ASSERT (TargetStatus
!= NULL
);
148 ASSERT (ScsiIo
!= NULL
);
150 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
151 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_SIX
);
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
;
161 // Fill Cdb for Test Unit Ready Command
163 Cdb
[0] = EFI_SCSI_OP_TEST_UNIT_READY
;
164 CommandPacket
.CdbLength
= (UINT8
) EFI_SCSI_OP_LENGTH_SIX
;
165 CommandPacket
.SenseDataLength
= *SenseDataLength
;
167 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
169 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
170 *TargetStatus
= CommandPacket
.TargetStatus
;
171 *SenseDataLength
= CommandPacket
.SenseDataLength
;
178 Execute Inquiry SCSI command on a specific SCSI target.
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().
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
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.
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
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.
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
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.
268 ScsiInquiryCommandEx (
269 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
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
,
281 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
283 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_SIX
];
285 ASSERT (SenseDataLength
!= NULL
);
286 ASSERT (HostAdapterStatus
!= NULL
);
287 ASSERT (TargetStatus
!= NULL
);
288 ASSERT (InquiryDataLength
!= NULL
);
289 ASSERT (ScsiIo
!= NULL
);
291 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
292 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_SIX
);
294 CommandPacket
.Timeout
= Timeout
;
295 CommandPacket
.InDataBuffer
= InquiryDataBuffer
;
296 CommandPacket
.InTransferLength
= *InquiryDataLength
;
297 CommandPacket
.SenseData
= SenseData
;
298 CommandPacket
.SenseDataLength
= *SenseDataLength
;
299 CommandPacket
.Cdb
= Cdb
;
301 Cdb
[0] = EFI_SCSI_OP_INQUIRY
;
302 if (EnableVitalProductData
) {
307 if (*InquiryDataLength
> 0xff) {
308 *InquiryDataLength
= 0xff;
311 Cdb
[4] = (UINT8
) (*InquiryDataLength
);
312 CommandPacket
.CdbLength
= (UINT8
) EFI_SCSI_OP_LENGTH_SIX
;
313 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
315 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
317 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
318 *TargetStatus
= CommandPacket
.TargetStatus
;
319 *SenseDataLength
= CommandPacket
.SenseDataLength
;
320 *InquiryDataLength
= CommandPacket
.InTransferLength
;
327 Execute Inquiry SCSI command on a specific SCSI target.
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().
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
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.
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
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.
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
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.
416 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
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
427 return ScsiInquiryCommandEx (
436 EnableVitalProductData
,
442 Execute Mode Sense(10) SCSI command on a specific SCSI target.
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().
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
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
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
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
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
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.
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
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
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.
532 ScsiModeSense10Command (
533 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
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
,
546 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
548 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
550 ASSERT (SenseDataLength
!= NULL
);
551 ASSERT (HostAdapterStatus
!= NULL
);
552 ASSERT (TargetStatus
!= NULL
);
553 ASSERT (DataLength
!= NULL
);
554 ASSERT (ScsiIo
!= NULL
);
556 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
557 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
559 CommandPacket
.Timeout
= Timeout
;
560 CommandPacket
.InDataBuffer
= DataBuffer
;
561 CommandPacket
.SenseData
= SenseData
;
562 CommandPacket
.InTransferLength
= *DataLength
;
563 CommandPacket
.Cdb
= Cdb
;
565 // Fill Cdb for Mode Sense (10) Command
567 Cdb
[0] = EFI_SCSI_OP_MODE_SEN10
;
569 // DBDField is in Cdb[1] bit3 of (bit7..0)
571 Cdb
[1] = (UINT8
) ((DBDField
<< 3) & 0x08);
573 // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0
575 Cdb
[2] = (UINT8
) (((PageControl
<< 6) & 0xc0) | (PageCode
& 0x3f));
576 Cdb
[7] = (UINT8
) (*DataLength
>> 8);
577 Cdb
[8] = (UINT8
) (*DataLength
);
579 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
580 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
581 CommandPacket
.SenseDataLength
= *SenseDataLength
;
583 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
585 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
586 *TargetStatus
= CommandPacket
.TargetStatus
;
587 *SenseDataLength
= CommandPacket
.SenseDataLength
;
588 *DataLength
= CommandPacket
.InTransferLength
;
595 Execute Request Sense SCSI command on a specific SCSI target.
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().
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
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.
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.
628 ScsiRequestSenseCommand (
629 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
631 IN OUT VOID
*SenseData
, OPTIONAL
632 IN OUT UINT8
*SenseDataLength
,
633 OUT UINT8
*HostAdapterStatus
,
634 OUT UINT8
*TargetStatus
637 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
639 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_SIX
];
641 ASSERT (SenseDataLength
!= NULL
);
642 ASSERT (HostAdapterStatus
!= NULL
);
643 ASSERT (TargetStatus
!= NULL
);
644 ASSERT (ScsiIo
!= NULL
);
646 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
647 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_SIX
);
649 CommandPacket
.Timeout
= Timeout
;
650 CommandPacket
.InDataBuffer
= SenseData
;
651 CommandPacket
.SenseData
= NULL
;
652 CommandPacket
.InTransferLength
= *SenseDataLength
;
653 CommandPacket
.Cdb
= Cdb
;
655 // Fill Cdb for Request Sense Command
657 Cdb
[0] = EFI_SCSI_OP_REQUEST_SENSE
;
658 Cdb
[4] = (UINT8
) (*SenseDataLength
);
660 CommandPacket
.CdbLength
= (UINT8
) EFI_SCSI_OP_LENGTH_SIX
;
661 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
662 CommandPacket
.SenseDataLength
= 0;
664 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
666 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
667 *TargetStatus
= CommandPacket
.TargetStatus
;
668 *SenseDataLength
= (UINT8
) CommandPacket
.InTransferLength
;
675 Execute Read Capacity SCSI command on a specific SCSI target.
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().
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
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
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.
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.
720 ScsiReadCapacityCommand (
721 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
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
,
732 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
734 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
736 ASSERT (SenseDataLength
!= NULL
);
737 ASSERT (HostAdapterStatus
!= NULL
);
738 ASSERT (TargetStatus
!= NULL
);
739 ASSERT (DataLength
!= NULL
);
740 ASSERT (ScsiIo
!= NULL
);
742 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
743 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
745 CommandPacket
.Timeout
= Timeout
;
746 CommandPacket
.InDataBuffer
= DataBuffer
;
747 CommandPacket
.SenseData
= SenseData
;
748 CommandPacket
.InTransferLength
= *DataLength
;
749 CommandPacket
.Cdb
= Cdb
;
751 // Fill Cdb for Read Capacity Command
753 Cdb
[0] = EFI_SCSI_OP_READ_CAPACITY
;
756 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
758 ZeroMem ((Cdb
+ 2), 4);
763 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
764 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
765 CommandPacket
.SenseDataLength
= *SenseDataLength
;
767 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
769 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
770 *TargetStatus
= CommandPacket
.TargetStatus
;
771 *SenseDataLength
= CommandPacket
.SenseDataLength
;
772 *DataLength
= CommandPacket
.InTransferLength
;
779 Execute Read Capacity SCSI 16 command on a specific SCSI target.
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().
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
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
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.
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.
824 ScsiReadCapacity16Command (
825 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
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
,
836 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
840 ASSERT (SenseDataLength
!= NULL
);
841 ASSERT (HostAdapterStatus
!= NULL
);
842 ASSERT (TargetStatus
!= NULL
);
843 ASSERT (DataLength
!= NULL
);
844 ASSERT (ScsiIo
!= NULL
);
846 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
849 CommandPacket
.Timeout
= Timeout
;
850 CommandPacket
.InDataBuffer
= DataBuffer
;
851 CommandPacket
.SenseData
= SenseData
;
852 CommandPacket
.InTransferLength
= *DataLength
;
853 CommandPacket
.Cdb
= Cdb
;
855 // Fill Cdb for Read Capacity Command
857 Cdb
[0] = EFI_SCSI_OP_READ_CAPACITY16
;
861 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO.
863 ZeroMem ((Cdb
+ 2), 8);
869 CommandPacket
.CdbLength
= 16;
870 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
871 CommandPacket
.SenseDataLength
= *SenseDataLength
;
873 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
875 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
876 *TargetStatus
= CommandPacket
.TargetStatus
;
877 *SenseDataLength
= CommandPacket
.SenseDataLength
;
878 *DataLength
= CommandPacket
.InTransferLength
;
885 Execute Read(10) SCSI command on a specific SCSI target.
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().
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
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
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.
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.
932 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
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
,
944 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
946 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
948 ASSERT (SenseDataLength
!= NULL
);
949 ASSERT (HostAdapterStatus
!= NULL
);
950 ASSERT (TargetStatus
!= NULL
);
951 ASSERT (DataLength
!= NULL
);
952 ASSERT (ScsiIo
!= NULL
);
954 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
955 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
957 CommandPacket
.Timeout
= Timeout
;
958 CommandPacket
.InDataBuffer
= DataBuffer
;
959 CommandPacket
.SenseData
= SenseData
;
960 CommandPacket
.InTransferLength
= *DataLength
;
961 CommandPacket
.Cdb
= Cdb
;
963 // Fill Cdb for Read (10) Command
965 Cdb
[0] = EFI_SCSI_OP_READ10
;
966 WriteUnaligned32 ((UINT32
*)&Cdb
[2], SwapBytes32 (StartLba
));
967 WriteUnaligned16 ((UINT16
*)&Cdb
[7], SwapBytes16 ((UINT16
) SectorSize
));
969 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
970 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
971 CommandPacket
.SenseDataLength
= *SenseDataLength
;
973 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
975 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
976 *TargetStatus
= CommandPacket
.TargetStatus
;
977 *SenseDataLength
= CommandPacket
.SenseDataLength
;
978 *DataLength
= CommandPacket
.InTransferLength
;
985 Execute Write(10) SCSI command on a specific SCSI target.
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().
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
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
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.
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.
1031 ScsiWrite10Command (
1032 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
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
,
1041 IN UINT32 SectorSize
1044 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
1046 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
1048 ASSERT (SenseDataLength
!= NULL
);
1049 ASSERT (HostAdapterStatus
!= NULL
);
1050 ASSERT (TargetStatus
!= NULL
);
1051 ASSERT (DataLength
!= NULL
);
1052 ASSERT (ScsiIo
!= NULL
);
1054 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
1055 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
1057 CommandPacket
.Timeout
= Timeout
;
1058 CommandPacket
.OutDataBuffer
= DataBuffer
;
1059 CommandPacket
.SenseData
= SenseData
;
1060 CommandPacket
.OutTransferLength
= *DataLength
;
1061 CommandPacket
.Cdb
= Cdb
;
1063 // Fill Cdb for Write (10) Command
1065 Cdb
[0] = EFI_SCSI_OP_WRITE10
;
1066 WriteUnaligned32 ((UINT32
*)&Cdb
[2], SwapBytes32 (StartLba
));
1067 WriteUnaligned16 ((UINT16
*)&Cdb
[7], SwapBytes16 ((UINT16
) SectorSize
));
1069 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
1070 CommandPacket
.DataDirection
= EFI_SCSI_DATA_OUT
;
1071 CommandPacket
.SenseDataLength
= *SenseDataLength
;
1073 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
1075 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
1076 *TargetStatus
= CommandPacket
.TargetStatus
;
1077 *SenseDataLength
= CommandPacket
.SenseDataLength
;
1078 *DataLength
= CommandPacket
.OutTransferLength
;
1084 Execute Read(16) SCSI command on a specific SCSI target.
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().
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
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
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.
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.
1131 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
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
,
1140 IN UINT32 SectorSize
1143 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
1145 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_SIXTEEN
];
1147 ASSERT (SenseDataLength
!= NULL
);
1148 ASSERT (HostAdapterStatus
!= NULL
);
1149 ASSERT (TargetStatus
!= NULL
);
1150 ASSERT (DataLength
!= NULL
);
1151 ASSERT (ScsiIo
!= NULL
);
1153 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
1154 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_SIXTEEN
);
1156 CommandPacket
.Timeout
= Timeout
;
1157 CommandPacket
.InDataBuffer
= DataBuffer
;
1158 CommandPacket
.SenseData
= SenseData
;
1159 CommandPacket
.InTransferLength
= *DataLength
;
1160 CommandPacket
.Cdb
= Cdb
;
1162 // Fill Cdb for Read (16) Command
1164 Cdb
[0] = EFI_SCSI_OP_READ16
;
1165 WriteUnaligned64 ((UINT64
*)&Cdb
[2], SwapBytes64 (StartLba
));
1166 WriteUnaligned32 ((UINT32
*)&Cdb
[10], SwapBytes32 (SectorSize
));
1168 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_SIXTEEN
;
1169 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
1170 CommandPacket
.SenseDataLength
= *SenseDataLength
;
1172 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
1174 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
1175 *TargetStatus
= CommandPacket
.TargetStatus
;
1176 *SenseDataLength
= CommandPacket
.SenseDataLength
;
1177 *DataLength
= CommandPacket
.InTransferLength
;
1184 Execute Write(16) SCSI command on a specific SCSI target.
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().
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
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
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.
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.
1230 ScsiWrite16Command (
1231 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
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
,
1240 IN UINT32 SectorSize
1243 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
1245 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_SIXTEEN
];
1247 ASSERT (SenseDataLength
!= NULL
);
1248 ASSERT (HostAdapterStatus
!= NULL
);
1249 ASSERT (TargetStatus
!= NULL
);
1250 ASSERT (DataLength
!= NULL
);
1251 ASSERT (ScsiIo
!= NULL
);
1253 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
1254 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_SIXTEEN
);
1256 CommandPacket
.Timeout
= Timeout
;
1257 CommandPacket
.OutDataBuffer
= DataBuffer
;
1258 CommandPacket
.SenseData
= SenseData
;
1259 CommandPacket
.OutTransferLength
= *DataLength
;
1260 CommandPacket
.Cdb
= Cdb
;
1262 // Fill Cdb for Write (16) Command
1264 Cdb
[0] = EFI_SCSI_OP_WRITE16
;
1265 WriteUnaligned64 ((UINT64
*)&Cdb
[2], SwapBytes64 (StartLba
));
1266 WriteUnaligned32 ((UINT32
*)&Cdb
[10], SwapBytes32 (SectorSize
));
1268 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_SIXTEEN
;
1269 CommandPacket
.DataDirection
= EFI_SCSI_DATA_OUT
;
1270 CommandPacket
.SenseDataLength
= *SenseDataLength
;
1272 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
1274 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
1275 *TargetStatus
= CommandPacket
.TargetStatus
;
1276 *SenseDataLength
= CommandPacket
.SenseDataLength
;
1277 *DataLength
= CommandPacket
.OutTransferLength
;
1284 Internal helper notify function in which update the result of the
1285 non-blocking SCSI Read/Write commands and signal caller event.
1287 @param Event The instance of EFI_EVENT.
1288 @param Context The parameter passed in.
1298 EFI_SCSI_LIB_ASYNC_CONTEXT
*LibContext
;
1299 EFI_SCSI_IO_SCSI_REQUEST_PACKET
*CommandPacket
;
1300 EFI_EVENT CallerEvent
;
1302 LibContext
= (EFI_SCSI_LIB_ASYNC_CONTEXT
*) Context
;
1303 CommandPacket
= &LibContext
->CommandPacket
;
1304 CallerEvent
= LibContext
->CallerEvent
;
1307 // Update SCSI Read/Write operation results
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
;
1315 *LibContext
->DataLength
= CommandPacket
->OutTransferLength
;
1318 if (CommandPacket
->Cdb
!= NULL
) {
1319 FreePool (CommandPacket
->Cdb
);
1323 gBS
->CloseEvent (Event
);
1324 gBS
->SignalEvent (CallerEvent
);
1329 Execute blocking/non-blocking Read(10) SCSI command on a specific SCSI
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
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().
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.
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.
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
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
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
1397 @retval EFI_OUT_OF_RESOURCES The request could not be completed due
1398 to a lack of resources.
1403 ScsiRead10CommandEx (
1404 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
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
,
1413 IN UINT32 SectorSize
,
1414 IN EFI_EVENT Event OPTIONAL
1417 EFI_SCSI_LIB_ASYNC_CONTEXT
*Context
;
1418 EFI_SCSI_IO_SCSI_REQUEST_PACKET
*CommandPacket
;
1421 EFI_EVENT SelfEvent
;
1423 if (Event
== NULL
) {
1424 return ScsiRead10Command (
1438 ASSERT (SenseDataLength
!= NULL
);
1439 ASSERT (HostAdapterStatus
!= NULL
);
1440 ASSERT (TargetStatus
!= NULL
);
1441 ASSERT (DataLength
!= NULL
);
1442 ASSERT (ScsiIo
!= NULL
);
1444 Context
= AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT
));
1445 if (Context
== NULL
) {
1446 return EFI_OUT_OF_RESOURCES
;
1449 Cdb
= AllocateZeroPool (EFI_SCSI_OP_LENGTH_TEN
);
1451 Status
= EFI_OUT_OF_RESOURCES
;
1455 Context
->SenseDataLength
= SenseDataLength
;
1456 Context
->HostAdapterStatus
= HostAdapterStatus
;
1457 Context
->TargetStatus
= TargetStatus
;
1458 Context
->CallerEvent
= Event
;
1460 CommandPacket
= &Context
->CommandPacket
;
1461 CommandPacket
->Timeout
= Timeout
;
1462 CommandPacket
->InDataBuffer
= DataBuffer
;
1463 CommandPacket
->SenseData
= SenseData
;
1464 CommandPacket
->InTransferLength
= *DataLength
;
1465 CommandPacket
->Cdb
= Cdb
;
1467 // Fill Cdb for Read (10) Command
1469 Cdb
[0] = EFI_SCSI_OP_READ10
;
1470 WriteUnaligned32 ((UINT32
*)&Cdb
[2], SwapBytes32 (StartLba
));
1471 WriteUnaligned16 ((UINT16
*)&Cdb
[7], SwapBytes16 ((UINT16
) SectorSize
));
1473 CommandPacket
->CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
1474 CommandPacket
->DataDirection
= EFI_SCSI_DATA_IN
;
1475 CommandPacket
->SenseDataLength
= *SenseDataLength
;
1480 Status
= gBS
->CreateEvent (
1487 if (EFI_ERROR(Status
)) {
1491 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, CommandPacket
, SelfEvent
);
1492 if (EFI_ERROR(Status
)) {
1494 // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()
1495 // returns with error, close the event here.
1497 gBS
->CloseEvent (SelfEvent
);
1504 if (Context
!= NULL
) {
1513 Execute blocking/non-blocking Write(10) SCSI command on a specific SCSI
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
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().
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.
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.
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
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
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
1581 @retval EFI_OUT_OF_RESOURCES The request could not be completed due
1582 to a lack of resources.
1587 ScsiWrite10CommandEx (
1588 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
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
,
1597 IN UINT32 SectorSize
,
1598 IN EFI_EVENT Event OPTIONAL
1601 EFI_SCSI_LIB_ASYNC_CONTEXT
*Context
;
1602 EFI_SCSI_IO_SCSI_REQUEST_PACKET
*CommandPacket
;
1605 EFI_EVENT SelfEvent
;
1607 if (Event
== NULL
) {
1608 return ScsiWrite10Command (
1622 ASSERT (SenseDataLength
!= NULL
);
1623 ASSERT (HostAdapterStatus
!= NULL
);
1624 ASSERT (TargetStatus
!= NULL
);
1625 ASSERT (DataLength
!= NULL
);
1626 ASSERT (ScsiIo
!= NULL
);
1628 Context
= AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT
));
1629 if (Context
== NULL
) {
1630 return EFI_OUT_OF_RESOURCES
;
1633 Cdb
= AllocateZeroPool (EFI_SCSI_OP_LENGTH_TEN
);
1635 Status
= EFI_OUT_OF_RESOURCES
;
1639 Context
->SenseDataLength
= SenseDataLength
;
1640 Context
->HostAdapterStatus
= HostAdapterStatus
;
1641 Context
->TargetStatus
= TargetStatus
;
1642 Context
->CallerEvent
= Event
;
1644 CommandPacket
= &Context
->CommandPacket
;
1645 CommandPacket
->Timeout
= Timeout
;
1646 CommandPacket
->OutDataBuffer
= DataBuffer
;
1647 CommandPacket
->SenseData
= SenseData
;
1648 CommandPacket
->OutTransferLength
= *DataLength
;
1649 CommandPacket
->Cdb
= Cdb
;
1651 // Fill Cdb for Write (10) Command
1653 Cdb
[0] = EFI_SCSI_OP_WRITE10
;
1654 WriteUnaligned32 ((UINT32
*)&Cdb
[2], SwapBytes32 (StartLba
));
1655 WriteUnaligned16 ((UINT16
*)&Cdb
[7], SwapBytes16 ((UINT16
) SectorSize
));
1657 CommandPacket
->CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
1658 CommandPacket
->DataDirection
= EFI_SCSI_DATA_OUT
;
1659 CommandPacket
->SenseDataLength
= *SenseDataLength
;
1664 Status
= gBS
->CreateEvent (
1671 if (EFI_ERROR(Status
)) {
1675 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, CommandPacket
, SelfEvent
);
1676 if (EFI_ERROR(Status
)) {
1678 // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()
1679 // returns with error, close the event here.
1681 gBS
->CloseEvent (SelfEvent
);
1688 if (Context
!= NULL
) {
1697 Execute blocking/non-blocking Read(16) SCSI command on a specific SCSI
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
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().
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.
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.
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
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
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
1765 @retval EFI_OUT_OF_RESOURCES The request could not be completed due
1766 to a lack of resources.
1771 ScsiRead16CommandEx (
1772 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
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
,
1781 IN UINT32 SectorSize
,
1782 IN EFI_EVENT Event OPTIONAL
1785 EFI_SCSI_LIB_ASYNC_CONTEXT
*Context
;
1786 EFI_SCSI_IO_SCSI_REQUEST_PACKET
*CommandPacket
;
1789 EFI_EVENT SelfEvent
;
1791 if (Event
== NULL
) {
1792 return ScsiRead16Command (
1806 ASSERT (SenseDataLength
!= NULL
);
1807 ASSERT (HostAdapterStatus
!= NULL
);
1808 ASSERT (TargetStatus
!= NULL
);
1809 ASSERT (DataLength
!= NULL
);
1810 ASSERT (ScsiIo
!= NULL
);
1812 Context
= AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT
));
1813 if (Context
== NULL
) {
1814 return EFI_OUT_OF_RESOURCES
;
1817 Cdb
= AllocateZeroPool (EFI_SCSI_OP_LENGTH_SIXTEEN
);
1819 Status
= EFI_OUT_OF_RESOURCES
;
1823 Context
->SenseDataLength
= SenseDataLength
;
1824 Context
->HostAdapterStatus
= HostAdapterStatus
;
1825 Context
->TargetStatus
= TargetStatus
;
1826 Context
->CallerEvent
= Event
;
1828 CommandPacket
= &Context
->CommandPacket
;
1829 CommandPacket
->Timeout
= Timeout
;
1830 CommandPacket
->InDataBuffer
= DataBuffer
;
1831 CommandPacket
->SenseData
= SenseData
;
1832 CommandPacket
->InTransferLength
= *DataLength
;
1833 CommandPacket
->Cdb
= Cdb
;
1835 // Fill Cdb for Read (16) Command
1837 Cdb
[0] = EFI_SCSI_OP_READ16
;
1838 WriteUnaligned64 ((UINT64
*)&Cdb
[2], SwapBytes64 (StartLba
));
1839 WriteUnaligned32 ((UINT32
*)&Cdb
[10], SwapBytes32 (SectorSize
));
1841 CommandPacket
->CdbLength
= EFI_SCSI_OP_LENGTH_SIXTEEN
;
1842 CommandPacket
->DataDirection
= EFI_SCSI_DATA_IN
;
1843 CommandPacket
->SenseDataLength
= *SenseDataLength
;
1848 Status
= gBS
->CreateEvent (
1855 if (EFI_ERROR(Status
)) {
1859 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, CommandPacket
, SelfEvent
);
1860 if (EFI_ERROR(Status
)) {
1862 // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()
1863 // returns with error, close the event here.
1865 gBS
->CloseEvent (SelfEvent
);
1872 if (Context
!= NULL
) {
1881 Execute blocking/non-blocking Write(16) SCSI command on a specific SCSI
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
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().
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.
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.
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
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
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
1949 @retval EFI_OUT_OF_RESOURCES The request could not be completed due
1950 to a lack of resources.
1955 ScsiWrite16CommandEx (
1956 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
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
,
1965 IN UINT32 SectorSize
,
1966 IN EFI_EVENT Event OPTIONAL
1969 EFI_SCSI_LIB_ASYNC_CONTEXT
*Context
;
1970 EFI_SCSI_IO_SCSI_REQUEST_PACKET
*CommandPacket
;
1973 EFI_EVENT SelfEvent
;
1975 if (Event
== NULL
) {
1976 return ScsiWrite16Command (
1990 ASSERT (SenseDataLength
!= NULL
);
1991 ASSERT (HostAdapterStatus
!= NULL
);
1992 ASSERT (TargetStatus
!= NULL
);
1993 ASSERT (DataLength
!= NULL
);
1994 ASSERT (ScsiIo
!= NULL
);
1996 Context
= AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT
));
1997 if (Context
== NULL
) {
1998 return EFI_OUT_OF_RESOURCES
;
2001 Cdb
= AllocateZeroPool (EFI_SCSI_OP_LENGTH_SIXTEEN
);
2003 Status
= EFI_OUT_OF_RESOURCES
;
2007 Context
->SenseDataLength
= SenseDataLength
;
2008 Context
->HostAdapterStatus
= HostAdapterStatus
;
2009 Context
->TargetStatus
= TargetStatus
;
2010 Context
->CallerEvent
= Event
;
2012 CommandPacket
= &Context
->CommandPacket
;
2013 CommandPacket
->Timeout
= Timeout
;
2014 CommandPacket
->OutDataBuffer
= DataBuffer
;
2015 CommandPacket
->SenseData
= SenseData
;
2016 CommandPacket
->OutTransferLength
= *DataLength
;
2017 CommandPacket
->Cdb
= Cdb
;
2019 // Fill Cdb for Write (16) Command
2021 Cdb
[0] = EFI_SCSI_OP_WRITE16
;
2022 WriteUnaligned64 ((UINT64
*)&Cdb
[2], SwapBytes64 (StartLba
));
2023 WriteUnaligned32 ((UINT32
*)&Cdb
[10], SwapBytes32 (SectorSize
));
2025 CommandPacket
->CdbLength
= EFI_SCSI_OP_LENGTH_SIXTEEN
;
2026 CommandPacket
->DataDirection
= EFI_SCSI_DATA_OUT
;
2027 CommandPacket
->SenseDataLength
= *SenseDataLength
;
2032 Status
= gBS
->CreateEvent (
2039 if (EFI_ERROR(Status
)) {
2043 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, CommandPacket
, SelfEvent
);
2044 if (EFI_ERROR(Status
)) {
2046 // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()
2047 // returns with error, close the event here.
2049 gBS
->CloseEvent (SelfEvent
);
2056 if (Context
!= NULL
) {