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