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