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