]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IScsiDxe/IScsiExtScsiPassThru.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiExtScsiPassThru.c
CommitLineData
4c5a5e0c 1/** @file\r
2 The implementation of EFI_EXT_SCSI_PASS_THRU_PROTOCOL.\r
3\r
f75a7f56 4Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
ecf98fbc 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
4c5a5e0c 6\r
7**/\r
8\r
9#include "IScsiImpl.h"\r
10\r
d1050b9d 11EFI_EXT_SCSI_PASS_THRU_PROTOCOL gIScsiExtScsiPassThruProtocolTemplate = {\r
4c5a5e0c 12 NULL,\r
13 IScsiExtScsiPassThruFunction,\r
14 IScsiExtScsiPassThruGetNextTargetLun,\r
15 IScsiExtScsiPassThruBuildDevicePath,\r
16 IScsiExtScsiPassThruGetTargetLun,\r
17 IScsiExtScsiPassThruResetChannel,\r
18 IScsiExtScsiPassThruResetTargetLun,\r
19 IScsiExtScsiPassThruGetNextTarget\r
20};\r
21\r
4c5a5e0c 22/**\r
23 Sends a SCSI Request Packet to a SCSI device that is attached to the SCSI channel.\r
24 This function supports both blocking I/O and nonblocking I/O. The blocking I/O\r
f75a7f56 25 functionality is required, and the nonblocking I/O functionality is optional.\r
4c5a5e0c 26\r
27 @param[in] This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.\r
28 @param[in] Target The Target is an array of size TARGET_MAX_BYTES and it\r
29 represents the id of the SCSI device to send the SCSI\r
30 Request Packet. Each transport driver may choose to\r
31 utilize a subset of this size to suit the needs\r
f75a7f56 32 of transport target representation. For example, a\r
4c5a5e0c 33 Fibre Channel driver may use only 8 bytes (WWN)\r
34 to represent an FC target.\r
35 @param[in] Lun The LUN of the SCSI device to send the SCSI Request Packet.\r
36 @param[in, out] Packet A pointer to the SCSI Request Packet to send to the\r
f75a7f56 37 SCSI device specified by Target and Lun.\r
4c5a5e0c 38 @param[in] Event If nonblocking I/O is not supported then Event is ignored,\r
39 and blocking I/O is performed. If Event is NULL, then\r
40 blocking I/O is performed. If Event is not NULL and non\r
41 blocking I/O is supported, then nonblocking I/O is performed,\r
42 and Event will be signaled when the SCSI Request Packet\r
43 completes.\r
44\r
45 @retval EFI_SUCCESS The SCSI Request Packet was sent by the host. For\r
f75a7f56 46 bi-directional commands, InTransferLength bytes\r
4c5a5e0c 47 were transferred from InDataBuffer.\r
48 For write and bi-directional commands, OutTransferLength\r
49 bytes were transferred by OutDataBuffer.\r
50 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was not executed.\r
51 The number of bytes that could be transferred is\r
52 returned in InTransferLength. For write and\r
53 bi-directional commands, OutTransferLength bytes\r
54 were transferred by OutDataBuffer.\r
55 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
56 there are too many SCSI Request Packets already\r
57 queued. The caller may retry later.\r
58 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send\r
f75a7f56 59 the SCSI Request Packet.\r
4c5a5e0c 60 @retval EFI_INVALID_PARAMETER Target, Lun, or the contents of ScsiRequestPacket,\r
61 are invalid.\r
62 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
63 is not supported by the host adapter.\r
64 This includes the case of Bi-directional SCSI\r
65 commands not supported by the implementation.\r
66 The SCSI Request Packet was not sent,\r
67 so no additional status information is available.\r
68 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI\r
69 Request Packet to execute.\r
70\r
71**/\r
72EFI_STATUS\r
73EFIAPI\r
74IScsiExtScsiPassThruFunction (\r
d1050b9d
MK
75 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
76 IN UINT8 *Target,\r
77 IN UINT64 Lun,\r
78 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,\r
79 IN EFI_EVENT Event OPTIONAL\r
4c5a5e0c 80 )\r
81{\r
cb162780
FS
82 EFI_STATUS Status;\r
83 ISCSI_DRIVER_DATA *Private;\r
f75a7f56 84\r
4c5a5e0c 85 if (Target[0] != 0) {\r
86 return EFI_INVALID_PARAMETER;\r
87 }\r
88\r
89 if ((Packet == NULL) || (Packet->Cdb == NULL)) {\r
90 return EFI_INVALID_PARAMETER;\r
91 }\r
92\r
cb162780
FS
93 Status = IScsiExecuteScsiCommand (This, Target, Lun, Packet);\r
94 if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_READY)) {\r
95 //\r
96 // Try to reinstate the session and re-execute the Scsi command.\r
97 //\r
98 Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (This);\r
99 if (EFI_ERROR (IScsiSessionReinstatement (Private->Session))) {\r
100 return EFI_DEVICE_ERROR;\r
101 }\r
102\r
103 Status = IScsiExecuteScsiCommand (This, Target, Lun, Packet);\r
104 }\r
105\r
106 return Status;\r
4c5a5e0c 107}\r
108\r
4c5a5e0c 109/**\r
110 Used to retrieve the list of legal Target IDs and LUNs for SCSI devices on\r
111 a SCSI channel. These can either be the list SCSI devices that are actually\r
112 present on the SCSI channel, or the list of legal Target Ids and LUNs for the\r
f75a7f56
LG
113 SCSI channel. Regardless, the caller of this function must probe the Target ID\r
114 and LUN returned to see if a SCSI device is actually present at that location\r
115 on the SCSI channel.\r
4c5a5e0c 116\r
117 @param[in] This The EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.\r
118 @param[in, out] Target On input, a pointer to the Target ID of a SCSI\r
119 device present on the SCSI channel. On output, a\r
120 pointer to the Target ID of the next SCSI device\r
121 present on a SCSI channel. An input value of\r
122 0xFFFFFFFF retrieves the Target ID of the first\r
123 SCSI device present on a SCSI channel.\r
124 @param[in, out] Lun On input, a pointer to the LUN of a SCSI device\r
125 present on the SCSI channel. On output, a pointer\r
126 to the LUN of the next SCSI device present on a\r
127 SCSI channel.\r
128\r
129 @retval EFI_SUCCESS The Target ID and Lun of the next SCSI device on\r
130 the SCSI channel was returned in Target and Lun.\r
131 @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI\r
132 channel.\r
133 @retval EFI_INVALID_PARAMETER Target is not 0xFFFFFFFF,and Target and Lun were\r
134 not returned on a previous call to\r
135 GetNextDevice().\r
136\r
137**/\r
138EFI_STATUS\r
139EFIAPI\r
140IScsiExtScsiPassThruGetNextTargetLun (\r
141 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
142 IN OUT UINT8 **Target,\r
143 IN OUT UINT64 *Lun\r
144 )\r
145{\r
d1050b9d
MK
146 ISCSI_DRIVER_DATA *Private;\r
147 ISCSI_SESSION_CONFIG_NVDATA *ConfigNvData;\r
148 UINT8 TargetId[TARGET_MAX_BYTES];\r
4c5a5e0c 149\r
d1050b9d
MK
150 Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (This);\r
151 ConfigNvData = &Private->Session->ConfigData->SessionConfigData;\r
4c5a5e0c 152\r
d1050b9d 153 if (((*Target)[0] == 0) && (CompareMem (Lun, ConfigNvData->BootLun, sizeof (UINT64)) == 0)) {\r
4c5a5e0c 154 //\r
155 // Only one <Target, Lun> pair per iSCSI Driver instance.\r
156 //\r
157 return EFI_NOT_FOUND;\r
158 }\r
159\r
160 SetMem (TargetId, TARGET_MAX_BYTES, 0xFF);\r
161 if (CompareMem (*Target, TargetId, TARGET_MAX_BYTES) == 0) {\r
162 (*Target)[0] = 0;\r
163 CopyMem (Lun, ConfigNvData->BootLun, sizeof (UINT64));\r
164\r
165 return EFI_SUCCESS;\r
166 }\r
167\r
168 return EFI_INVALID_PARAMETER;\r
169}\r
170\r
4c5a5e0c 171/**\r
172 Allocate and build a device path node for a SCSI device on a SCSI channel.\r
173\r
174 @param[in] This Protocol instance pointer.\r
175 @param[in] Target The Target ID of the SCSI device for which a\r
176 device path node is to be allocated and built.\r
177 @param[in] Lun The LUN of the SCSI device for which a device\r
178 path node is to be allocated and built.\r
179 @param[in, out] DevicePath A pointer to a single device path node that\r
180 describes the SCSI device specified by Target and\r
181 Lun. This function is responsible for allocating\r
182 the buffer DevicePath with the boot service\r
183 AllocatePool(). It is the caller's\r
184 responsibility to free DevicePath when the caller\r
185 is finished with DevicePath.\r
186\r
187 @retval EFI_SUCCESS The device path node that describes the SCSI\r
188 device specified by Target and Lun was allocated\r
189 and returned in DevicePath.\r
190 @retval EFI_NOT_FOUND The SCSI devices specified by Target and Lun does\r
191 not exist on the SCSI channel.\r
192 @retval EFI_INVALID_PARAMETER DevicePath is NULL.\r
193 @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate\r
194 DevicePath.\r
195\r
196**/\r
197EFI_STATUS\r
198EFIAPI\r
199IScsiExtScsiPassThruBuildDevicePath (\r
200 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
201 IN UINT8 *Target,\r
202 IN UINT64 Lun,\r
203 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
204 )\r
205{\r
d1050b9d
MK
206 ISCSI_DRIVER_DATA *Private;\r
207 ISCSI_SESSION *Session;\r
208 ISCSI_SESSION_CONFIG_NVDATA *ConfigNvData;\r
209 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfig;\r
210 EFI_DEV_PATH *Node;\r
211 UINTN DevPathNodeLen;\r
4c5a5e0c 212\r
cf260a47 213 if (DevicePath == NULL) {\r
4c5a5e0c 214 return EFI_INVALID_PARAMETER;\r
215 }\r
216\r
217 if (Target[0] != 0) {\r
218 return EFI_NOT_FOUND;\r
219 }\r
220\r
d1050b9d
MK
221 Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (This);\r
222 Session = Private->Session;\r
223 ConfigNvData = &Session->ConfigData->SessionConfigData;\r
224 AuthConfig = Session->AuthData.CHAP.AuthConfig;\r
4c5a5e0c 225\r
226 if (CompareMem (&Lun, ConfigNvData->BootLun, sizeof (UINT64)) != 0) {\r
227 return EFI_NOT_FOUND;\r
228 }\r
229\r
d1050b9d
MK
230 DevPathNodeLen = sizeof (ISCSI_DEVICE_PATH) + AsciiStrLen (ConfigNvData->TargetName) + 1;\r
231 Node = AllocateZeroPool (DevPathNodeLen);\r
4c5a5e0c 232 if (Node == NULL) {\r
233 return EFI_OUT_OF_RESOURCES;\r
234 }\r
235\r
236 Node->DevPath.Type = MESSAGING_DEVICE_PATH;\r
237 Node->DevPath.SubType = MSG_ISCSI_DP;\r
238 SetDevicePathNodeLength (&Node->DevPath, DevPathNodeLen);\r
239\r
240 //\r
241 // 0 for TCP, others are reserved.\r
242 //\r
243 Node->Iscsi.NetworkProtocol = 0;\r
244\r
d1050b9d 245 Node->Iscsi.LoginOption = 0;\r
4c5a5e0c 246\r
247 switch (Session->AuthType) {\r
d1050b9d
MK
248 case ISCSI_AUTH_TYPE_NONE:\r
249 Node->Iscsi.LoginOption |= 0x0800;\r
250 break;\r
251\r
252 case ISCSI_AUTH_TYPE_CHAP:\r
253 //\r
254 // Bit12: 0=CHAP_BI, 1=CHAP_UNI\r
255 //\r
256 if (AuthConfig->CHAPType == ISCSI_CHAP_UNI) {\r
257 Node->Iscsi.LoginOption |= 0x1000;\r
258 }\r
259\r
260 break;\r
261\r
262 default:\r
263 break;\r
4c5a5e0c 264 }\r
265\r
266 CopyMem (&Node->Iscsi.Lun, ConfigNvData->BootLun, sizeof (UINT64));\r
267 Node->Iscsi.TargetPortalGroupTag = Session->TargetPortalGroupTag;\r
d1050b9d 268 AsciiStrCpyS ((CHAR8 *)Node + sizeof (ISCSI_DEVICE_PATH), AsciiStrLen (ConfigNvData->TargetName) + 1, ConfigNvData->TargetName);\r
4c5a5e0c 269\r
d1050b9d 270 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)Node;\r
4c5a5e0c 271\r
272 return EFI_SUCCESS;\r
273}\r
274\r
4c5a5e0c 275/**\r
276 Translate a device path node to a Target ID and LUN.\r
277\r
278 @param[in] This Protocol instance pointer.\r
279 @param[in] DevicePath A pointer to the device path node that describes\r
280 a SCSI device on the SCSI channel.\r
281 @param[out] Target A pointer to the Target ID of a SCSI device on\r
282 the SCSI channel.\r
283 @param[out] Lun A pointer to the LUN of a SCSI device on the SCSI\r
284 channel.\r
285\r
286 @retval EFI_SUCCESS DevicePath was successfully translated to a\r
287 Target ID and LUN, and they were returned in\r
288 Target and Lun.\r
289 @retval EFI_INVALID_PARAMETER DevicePath/Target/Lun is NULL.\r
290 @retval EFI_UNSUPPORTED This driver does not support the device path node\r
291 type in DevicePath.\r
f75a7f56 292 @retval EFI_NOT_FOUND A valid translation does not exist from DevicePath\r
4c5a5e0c 293 to a TargetID and LUN.\r
294\r
295**/\r
296EFI_STATUS\r
297EFIAPI\r
298IScsiExtScsiPassThruGetTargetLun (\r
299 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
300 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
301 OUT UINT8 **Target,\r
302 OUT UINT64 *Lun\r
303 )\r
304{\r
d1050b9d
MK
305 ISCSI_DRIVER_DATA *Private;\r
306 ISCSI_SESSION_CONFIG_NVDATA *ConfigNvData;\r
4c5a5e0c 307\r
308 if ((DevicePath == NULL) || (Target == NULL) || (Lun == NULL)) {\r
309 return EFI_INVALID_PARAMETER;\r
310 }\r
311\r
312 if ((DevicePath->Type != MESSAGING_DEVICE_PATH) ||\r
313 (DevicePath->SubType != MSG_ISCSI_DP) ||\r
314 (DevicePathNodeLength (DevicePath) <= sizeof (ISCSI_DEVICE_PATH))\r
d1050b9d
MK
315 )\r
316 {\r
4c5a5e0c 317 return EFI_UNSUPPORTED;\r
318 }\r
319\r
d1050b9d
MK
320 Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (This);\r
321 ConfigNvData = &Private->Session->ConfigData->SessionConfigData;\r
4c5a5e0c 322\r
323 SetMem (*Target, TARGET_MAX_BYTES, 0xFF);\r
324 (*Target)[0] = 0;\r
325\r
d1050b9d 326 if (AsciiStrCmp (ConfigNvData->TargetName, (CHAR8 *)DevicePath + sizeof (ISCSI_DEVICE_PATH)) != 0) {\r
4c5a5e0c 327 return EFI_UNSUPPORTED;\r
328 }\r
329\r
330 CopyMem (Lun, ConfigNvData->BootLun, sizeof (UINT64));\r
331\r
332 return EFI_SUCCESS;\r
333}\r
334\r
4c5a5e0c 335/**\r
336 Resets a SCSI channel. This operation resets all the SCSI devices connected to\r
337 the SCSI channel.\r
338\r
339 @param[in] This Protocol instance pointer.\r
340\r
341 @retval EFI_UNSUPPORTED It is not supported.\r
342\r
343**/\r
344EFI_STATUS\r
345EFIAPI\r
346IScsiExtScsiPassThruResetChannel (\r
347 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This\r
348 )\r
349{\r
350 return EFI_UNSUPPORTED;\r
351}\r
352\r
4c5a5e0c 353/**\r
354 Resets a SCSI device that is connected to a SCSI channel.\r
355\r
356 @param[in] This Protocol instance pointer.\r
357 @param[in] Target The Target ID of the SCSI device to reset.\r
358 @param[in] Lun The LUN of the SCSI device to reset.\r
359\r
360 @retval EFI_UNSUPPORTED It is not supported.\r
361\r
362**/\r
363EFI_STATUS\r
364EFIAPI\r
365IScsiExtScsiPassThruResetTargetLun (\r
366 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
367 IN UINT8 *Target,\r
368 IN UINT64 Lun\r
369 )\r
370{\r
371 return EFI_UNSUPPORTED;\r
372}\r
373\r
374/**\r
f75a7f56 375 Retrieve the list of legal Target IDs for SCSI devices on a SCSI channel.\r
4c5a5e0c 376\r
377 @param[in] This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL\r
378 instance.\r
379 @param[in, out] Target (TARGET_MAX_BYTES) of a SCSI device present on\r
380 the SCSI channel. On output, a pointer to the\r
381 Target ID (an array of TARGET_MAX_BYTES) of the\r
382 next SCSI device present on a SCSI channel.\r
383 An input value of 0xF(all bytes in the array are 0xF)\r
384 in the Target array retrieves the Target ID of the\r
f75a7f56 385 first SCSI device present on a SCSI channel.\r
4c5a5e0c 386\r
387 @retval EFI_SUCCESS The Target ID of the next SCSI device on the SCSI\r
388 channel was returned in Target.\r
389 @retval EFI_INVALID_PARAMETER Target or Lun is NULL.\r
390 @retval EFI_TIMEOUT Target array is not all 0xF, and Target was not\r
391 returned on a previous call to GetNextTarget().\r
392 @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel.\r
393\r
394**/\r
395EFI_STATUS\r
396EFIAPI\r
397IScsiExtScsiPassThruGetNextTarget (\r
398 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
399 IN OUT UINT8 **Target\r
400 )\r
401{\r
d1050b9d 402 UINT8 TargetId[TARGET_MAX_BYTES];\r
4c5a5e0c 403\r
404 SetMem (TargetId, TARGET_MAX_BYTES, 0xFF);\r
405\r
406 if (CompareMem (*Target, TargetId, TARGET_MAX_BYTES) == 0) {\r
407 (*Target)[0] = 0;\r
408 return EFI_SUCCESS;\r
409 } else if ((*Target)[0] == 0) {\r
410 return EFI_NOT_FOUND;\r
411 } else {\r
412 return EFI_INVALID_PARAMETER;\r
413 }\r
414}\r