IScsiDriver.c 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891
  1. /** @file
  2. The entry point of IScsi driver.
  3. Copyright (c) 2019, NVIDIA Corporation. All rights reserved.
  4. Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
  5. (C) Copyright 2017 Hewlett Packard Enterprise Development LP<BR>
  6. SPDX-License-Identifier: BSD-2-Clause-Patent
  7. **/
  8. #include "IScsiImpl.h"
  9. EFI_DRIVER_BINDING_PROTOCOL gIScsiIp4DriverBinding = {
  10. IScsiIp4DriverBindingSupported,
  11. IScsiIp4DriverBindingStart,
  12. IScsiIp4DriverBindingStop,
  13. 0xa,
  14. NULL,
  15. NULL
  16. };
  17. EFI_DRIVER_BINDING_PROTOCOL gIScsiIp6DriverBinding = {
  18. IScsiIp6DriverBindingSupported,
  19. IScsiIp6DriverBindingStart,
  20. IScsiIp6DriverBindingStop,
  21. 0xa,
  22. NULL,
  23. NULL
  24. };
  25. EFI_GUID gIScsiV4PrivateGuid = ISCSI_V4_PRIVATE_GUID;
  26. EFI_GUID gIScsiV6PrivateGuid = ISCSI_V6_PRIVATE_GUID;
  27. ISCSI_PRIVATE_DATA *mPrivate = NULL;
  28. /**
  29. Tests to see if this driver supports the RemainingDevicePath.
  30. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  31. parameter is ignored by device drivers, and is optional for bus
  32. drivers. For bus drivers, if this parameter is not NULL, then
  33. the bus driver must determine if the bus controller specified
  34. by ControllerHandle and the child controller specified
  35. by RemainingDevicePath are both supported by this
  36. bus driver.
  37. @retval EFI_SUCCESS The RemainingDevicePath is supported or NULL.
  38. @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
  39. RemainingDevicePath is not supported by the driver specified by This.
  40. **/
  41. EFI_STATUS
  42. IScsiIsDevicePathSupported (
  43. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  44. )
  45. {
  46. EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;
  47. CurrentDevicePath = RemainingDevicePath;
  48. if (CurrentDevicePath != NULL) {
  49. while (!IsDevicePathEnd (CurrentDevicePath)) {
  50. if ((CurrentDevicePath->Type == MESSAGING_DEVICE_PATH) && (CurrentDevicePath->SubType == MSG_ISCSI_DP)) {
  51. return EFI_SUCCESS;
  52. }
  53. CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);
  54. }
  55. return EFI_UNSUPPORTED;
  56. }
  57. return EFI_SUCCESS;
  58. }
  59. /**
  60. Check whether an iSCSI HBA adapter already installs an AIP instance with
  61. network boot policy matching the value specified in PcdIScsiAIPNetworkBootPolicy.
  62. If yes, return EFI_SUCCESS.
  63. @retval EFI_SUCCESS Found an AIP with matching network boot policy.
  64. @retval EFI_NOT_FOUND AIP is unavailable or the network boot policy
  65. not matched.
  66. **/
  67. EFI_STATUS
  68. IScsiCheckAip (
  69. VOID
  70. )
  71. {
  72. UINTN AipHandleCount;
  73. EFI_HANDLE *AipHandleBuffer;
  74. UINTN AipIndex;
  75. EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;
  76. EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiPassThru;
  77. EFI_GUID *InfoTypesBuffer;
  78. UINTN InfoTypeBufferCount;
  79. UINTN TypeIndex;
  80. VOID *InfoBlock;
  81. UINTN InfoBlockSize;
  82. BOOLEAN Supported;
  83. EFI_ADAPTER_INFO_NETWORK_BOOT *NetworkBoot;
  84. EFI_STATUS Status;
  85. UINT8 NetworkBootPolicy;
  86. //
  87. // Check any AIP instances exist in system.
  88. //
  89. AipHandleCount = 0;
  90. AipHandleBuffer = NULL;
  91. Status = gBS->LocateHandleBuffer (
  92. ByProtocol,
  93. &gEfiAdapterInformationProtocolGuid,
  94. NULL,
  95. &AipHandleCount,
  96. &AipHandleBuffer
  97. );
  98. if (EFI_ERROR (Status) || (AipHandleCount == 0)) {
  99. return EFI_NOT_FOUND;
  100. }
  101. ASSERT (AipHandleBuffer != NULL);
  102. InfoBlock = NULL;
  103. for (AipIndex = 0; AipIndex < AipHandleCount; AipIndex++) {
  104. Status = gBS->HandleProtocol (
  105. AipHandleBuffer[AipIndex],
  106. &gEfiAdapterInformationProtocolGuid,
  107. (VOID *)&Aip
  108. );
  109. ASSERT_EFI_ERROR (Status);
  110. ASSERT (Aip != NULL);
  111. Status = gBS->HandleProtocol (
  112. AipHandleBuffer[AipIndex],
  113. &gEfiExtScsiPassThruProtocolGuid,
  114. (VOID *)&ExtScsiPassThru
  115. );
  116. if (EFI_ERROR (Status) || (ExtScsiPassThru == NULL)) {
  117. continue;
  118. }
  119. InfoTypesBuffer = NULL;
  120. InfoTypeBufferCount = 0;
  121. Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount);
  122. if (EFI_ERROR (Status) || (InfoTypesBuffer == NULL)) {
  123. continue;
  124. }
  125. //
  126. // Check whether the AIP instance has Network boot information block.
  127. //
  128. Supported = FALSE;
  129. for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {
  130. if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoNetworkBootGuid)) {
  131. Supported = TRUE;
  132. break;
  133. }
  134. }
  135. FreePool (InfoTypesBuffer);
  136. if (!Supported) {
  137. continue;
  138. }
  139. //
  140. // We now have network boot information block.
  141. //
  142. InfoBlock = NULL;
  143. InfoBlockSize = 0;
  144. Status = Aip->GetInformation (Aip, &gEfiAdapterInfoNetworkBootGuid, &InfoBlock, &InfoBlockSize);
  145. if (EFI_ERROR (Status) || (InfoBlock == NULL)) {
  146. continue;
  147. }
  148. //
  149. // Check whether the network boot policy matches.
  150. //
  151. NetworkBoot = (EFI_ADAPTER_INFO_NETWORK_BOOT *)InfoBlock;
  152. NetworkBootPolicy = PcdGet8 (PcdIScsiAIPNetworkBootPolicy);
  153. if (NetworkBootPolicy == STOP_UEFI_ISCSI_IF_HBA_INSTALL_AIP) {
  154. Status = EFI_SUCCESS;
  155. goto Exit;
  156. }
  157. if ((((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP4) != 0) &&
  158. !NetworkBoot->iScsiIpv4BootCapablity) ||
  159. (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP6) != 0) &&
  160. !NetworkBoot->iScsiIpv6BootCapablity) ||
  161. (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_OFFLOAD) != 0) &&
  162. !NetworkBoot->OffloadCapability) ||
  163. (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_MPIO) != 0) &&
  164. !NetworkBoot->iScsiMpioCapability) ||
  165. (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP4) != 0) &&
  166. !NetworkBoot->iScsiIpv4Boot) ||
  167. (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP6) != 0) &&
  168. !NetworkBoot->iScsiIpv6Boot))
  169. {
  170. FreePool (InfoBlock);
  171. continue;
  172. }
  173. Status = EFI_SUCCESS;
  174. goto Exit;
  175. }
  176. Status = EFI_NOT_FOUND;
  177. Exit:
  178. if (InfoBlock != NULL) {
  179. FreePool (InfoBlock);
  180. }
  181. if (AipHandleBuffer != NULL) {
  182. FreePool (AipHandleBuffer);
  183. }
  184. return Status;
  185. }
  186. /**
  187. Tests to see if this driver supports a given controller. This is the worker function for
  188. IScsiIp4(6)DriverBindingSupported.
  189. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  190. @param[in] ControllerHandle The handle of the controller to test. This handle
  191. must support a protocol interface that supplies
  192. an I/O abstraction to the driver.
  193. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  194. parameter is ignored by device drivers, and is optional for bus
  195. drivers. For bus drivers, if this parameter is not NULL, then
  196. the bus driver must determine if the bus controller specified
  197. by ControllerHandle and the child controller specified
  198. by RemainingDevicePath are both supported by this
  199. bus driver.
  200. @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
  201. @retval EFI_SUCCESS The device specified by ControllerHandle and
  202. RemainingDevicePath is supported by the driver specified by This.
  203. @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
  204. RemainingDevicePath is already being managed by the driver
  205. specified by This.
  206. @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
  207. RemainingDevicePath is not supported by the driver specified by This.
  208. **/
  209. EFI_STATUS
  210. EFIAPI
  211. IScsiSupported (
  212. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  213. IN EFI_HANDLE ControllerHandle,
  214. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
  215. IN UINT8 IpVersion
  216. )
  217. {
  218. EFI_STATUS Status;
  219. EFI_GUID *IScsiServiceBindingGuid;
  220. EFI_GUID *TcpServiceBindingGuid;
  221. EFI_GUID *DhcpServiceBindingGuid;
  222. EFI_GUID *DnsServiceBindingGuid;
  223. if (IpVersion == IP_VERSION_4) {
  224. IScsiServiceBindingGuid = &gIScsiV4PrivateGuid;
  225. TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
  226. DhcpServiceBindingGuid = &gEfiDhcp4ServiceBindingProtocolGuid;
  227. DnsServiceBindingGuid = &gEfiDns4ServiceBindingProtocolGuid;
  228. } else {
  229. IScsiServiceBindingGuid = &gIScsiV6PrivateGuid;
  230. TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
  231. DhcpServiceBindingGuid = &gEfiDhcp6ServiceBindingProtocolGuid;
  232. DnsServiceBindingGuid = &gEfiDns6ServiceBindingProtocolGuid;
  233. }
  234. Status = gBS->OpenProtocol (
  235. ControllerHandle,
  236. IScsiServiceBindingGuid,
  237. NULL,
  238. This->DriverBindingHandle,
  239. ControllerHandle,
  240. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  241. );
  242. if (!EFI_ERROR (Status)) {
  243. return EFI_ALREADY_STARTED;
  244. }
  245. Status = gBS->OpenProtocol (
  246. ControllerHandle,
  247. TcpServiceBindingGuid,
  248. NULL,
  249. This->DriverBindingHandle,
  250. ControllerHandle,
  251. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  252. );
  253. if (EFI_ERROR (Status)) {
  254. return EFI_UNSUPPORTED;
  255. }
  256. Status = IScsiIsDevicePathSupported (RemainingDevicePath);
  257. if (EFI_ERROR (Status)) {
  258. return EFI_UNSUPPORTED;
  259. }
  260. if (IScsiDhcpIsConfigured (ControllerHandle, IpVersion)) {
  261. Status = gBS->OpenProtocol (
  262. ControllerHandle,
  263. DhcpServiceBindingGuid,
  264. NULL,
  265. This->DriverBindingHandle,
  266. ControllerHandle,
  267. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  268. );
  269. if (EFI_ERROR (Status)) {
  270. return EFI_UNSUPPORTED;
  271. }
  272. }
  273. if (IScsiDnsIsConfigured (ControllerHandle)) {
  274. Status = gBS->OpenProtocol (
  275. ControllerHandle,
  276. DnsServiceBindingGuid,
  277. NULL,
  278. This->DriverBindingHandle,
  279. ControllerHandle,
  280. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  281. );
  282. if (EFI_ERROR (Status)) {
  283. return EFI_UNSUPPORTED;
  284. }
  285. }
  286. return EFI_SUCCESS;
  287. }
  288. /**
  289. Start to manage the controller. This is the worker function for
  290. IScsiIp4(6)DriverBindingStart.
  291. @param[in] Image Handle of the image.
  292. @param[in] ControllerHandle Handle of the controller.
  293. @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
  294. @retval EFI_SUCCESS This driver was started.
  295. @retval EFI_ALREADY_STARTED This driver is already running on this device.
  296. @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
  297. @retval EFI_NOT_FOUND There is no sufficient information to establish
  298. the iScsi session.
  299. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
  300. @retval EFI_DEVICE_ERROR Failed to get TCP connection device path.
  301. @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle
  302. because its interfaces are being used.
  303. **/
  304. EFI_STATUS
  305. IScsiStart (
  306. IN EFI_HANDLE Image,
  307. IN EFI_HANDLE ControllerHandle,
  308. IN UINT8 IpVersion
  309. )
  310. {
  311. EFI_STATUS Status;
  312. ISCSI_DRIVER_DATA *Private;
  313. LIST_ENTRY *Entry;
  314. LIST_ENTRY *NextEntry;
  315. ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
  316. ISCSI_SESSION *Session;
  317. UINT8 Index;
  318. EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExistIScsiExtScsiPassThru;
  319. ISCSI_DRIVER_DATA *ExistPrivate;
  320. UINT8 *AttemptConfigOrder;
  321. UINTN AttemptConfigOrderSize;
  322. UINT8 BootSelected;
  323. EFI_HANDLE *HandleBuffer;
  324. UINTN NumberOfHandles;
  325. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  326. EFI_GUID *IScsiPrivateGuid;
  327. EFI_GUID *TcpServiceBindingGuid;
  328. BOOLEAN NeedUpdate;
  329. VOID *Interface;
  330. EFI_GUID *ProtocolGuid;
  331. UINT8 NetworkBootPolicy;
  332. ISCSI_SESSION_CONFIG_NVDATA *NvData;
  333. //
  334. // Test to see if iSCSI driver supports the given controller.
  335. //
  336. if (IpVersion == IP_VERSION_4) {
  337. IScsiPrivateGuid = &gIScsiV4PrivateGuid;
  338. TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
  339. ProtocolGuid = &gEfiTcp4ProtocolGuid;
  340. } else if (IpVersion == IP_VERSION_6) {
  341. IScsiPrivateGuid = &gIScsiV6PrivateGuid;
  342. TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
  343. ProtocolGuid = &gEfiTcp6ProtocolGuid;
  344. } else {
  345. return EFI_INVALID_PARAMETER;
  346. }
  347. Status = gBS->OpenProtocol (
  348. ControllerHandle,
  349. IScsiPrivateGuid,
  350. NULL,
  351. Image,
  352. ControllerHandle,
  353. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  354. );
  355. if (!EFI_ERROR (Status)) {
  356. return EFI_ALREADY_STARTED;
  357. }
  358. Status = gBS->OpenProtocol (
  359. ControllerHandle,
  360. TcpServiceBindingGuid,
  361. NULL,
  362. Image,
  363. ControllerHandle,
  364. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  365. );
  366. if (EFI_ERROR (Status)) {
  367. return EFI_UNSUPPORTED;
  368. }
  369. NetworkBootPolicy = PcdGet8 (PcdIScsiAIPNetworkBootPolicy);
  370. if (NetworkBootPolicy == ALWAYS_USE_ISCSI_HBA_AND_IGNORE_UEFI_ISCSI) {
  371. return EFI_ABORTED;
  372. }
  373. if (NetworkBootPolicy != ALWAYS_USE_UEFI_ISCSI_AND_IGNORE_ISCSI_HBA) {
  374. //
  375. // Check existing iSCSI AIP.
  376. //
  377. Status = IScsiCheckAip ();
  378. if (!EFI_ERROR (Status)) {
  379. //
  380. // Find iSCSI AIP with specified network boot policy. return EFI_ABORTED.
  381. //
  382. return EFI_ABORTED;
  383. }
  384. }
  385. //
  386. // Record the incoming NIC info.
  387. //
  388. Status = IScsiAddNic (ControllerHandle, Image);
  389. if (EFI_ERROR (Status)) {
  390. return Status;
  391. }
  392. //
  393. // Create the instance private data.
  394. //
  395. Private = IScsiCreateDriverData (Image, ControllerHandle);
  396. if (Private == NULL) {
  397. return EFI_OUT_OF_RESOURCES;
  398. }
  399. //
  400. // Create a underlayer child instance, but not need to configure it. Just open ChildHandle
  401. // via BY_DRIVER. That is, establishing the relationship between ControllerHandle and ChildHandle.
  402. // Therefore, when DisconnectController(), especially VLAN virtual controller handle,
  403. // IScsiDriverBindingStop() will be called.
  404. //
  405. Status = NetLibCreateServiceChild (
  406. ControllerHandle,
  407. Image,
  408. TcpServiceBindingGuid,
  409. &Private->ChildHandle
  410. );
  411. if (EFI_ERROR (Status)) {
  412. goto ON_ERROR;
  413. }
  414. Status = gBS->OpenProtocol (
  415. Private->ChildHandle, /// Default Tcp child
  416. ProtocolGuid,
  417. &Interface,
  418. Image,
  419. ControllerHandle,
  420. EFI_OPEN_PROTOCOL_BY_DRIVER
  421. );
  422. if (EFI_ERROR (Status)) {
  423. goto ON_ERROR;
  424. }
  425. //
  426. // Always install private protocol no matter what happens later. We need to
  427. // keep the relationship between ControllerHandle and ChildHandle.
  428. //
  429. Status = gBS->InstallProtocolInterface (
  430. &ControllerHandle,
  431. IScsiPrivateGuid,
  432. EFI_NATIVE_INTERFACE,
  433. &Private->IScsiIdentifier
  434. );
  435. if (EFI_ERROR (Status)) {
  436. goto ON_ERROR;
  437. }
  438. if (IpVersion == IP_VERSION_4) {
  439. mPrivate->Ipv6Flag = FALSE;
  440. } else {
  441. mPrivate->Ipv6Flag = TRUE;
  442. }
  443. //
  444. // Get the current iSCSI configuration data.
  445. //
  446. Status = IScsiGetConfigData (Private);
  447. if (EFI_ERROR (Status)) {
  448. goto ON_ERROR;
  449. }
  450. //
  451. // If there is already a successul attempt, check whether this attempt is the
  452. // first "enabled for MPIO" attempt. If not, still try the first attempt.
  453. // In single path mode, try all attempts.
  454. //
  455. ExistPrivate = NULL;
  456. Status = EFI_NOT_FOUND;
  457. if (mPrivate->OneSessionEstablished && mPrivate->EnableMpio) {
  458. AttemptConfigData = NULL;
  459. NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
  460. AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
  461. if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
  462. break;
  463. }
  464. }
  465. if (AttemptConfigData == NULL) {
  466. goto ON_ERROR;
  467. }
  468. if (AttemptConfigData->AttemptConfigIndex == mPrivate->BootSelectedIndex) {
  469. goto ON_EXIT;
  470. }
  471. //
  472. // Uninstall the original ExtScsiPassThru first.
  473. //
  474. //
  475. // Locate all ExtScsiPassThru protocol instances.
  476. //
  477. Status = gBS->LocateHandleBuffer (
  478. ByProtocol,
  479. &gEfiExtScsiPassThruProtocolGuid,
  480. NULL,
  481. &NumberOfHandles,
  482. &HandleBuffer
  483. );
  484. if (EFI_ERROR (Status)) {
  485. goto ON_ERROR;
  486. }
  487. //
  488. // Find ExtScsiPassThru protocol instance produced by this driver.
  489. //
  490. ExistIScsiExtScsiPassThru = NULL;
  491. for (Index = 0; Index < NumberOfHandles && ExistIScsiExtScsiPassThru == NULL; Index++) {
  492. Status = gBS->HandleProtocol (
  493. HandleBuffer[Index],
  494. &gEfiDevicePathProtocolGuid,
  495. (VOID **)&DevicePath
  496. );
  497. if (EFI_ERROR (Status)) {
  498. continue;
  499. }
  500. while (!IsDevicePathEnd (DevicePath)) {
  501. if ((DevicePath->Type == MESSAGING_DEVICE_PATH) && (DevicePath->SubType == MSG_MAC_ADDR_DP)) {
  502. //
  503. // Get the ExtScsiPassThru protocol instance.
  504. //
  505. Status = gBS->HandleProtocol (
  506. HandleBuffer[Index],
  507. &gEfiExtScsiPassThruProtocolGuid,
  508. (VOID **)&ExistIScsiExtScsiPassThru
  509. );
  510. ASSERT_EFI_ERROR (Status);
  511. break;
  512. }
  513. DevicePath = NextDevicePathNode (DevicePath);
  514. }
  515. }
  516. FreePool (HandleBuffer);
  517. if (ExistIScsiExtScsiPassThru == NULL) {
  518. Status = EFI_NOT_FOUND;
  519. goto ON_ERROR;
  520. }
  521. ExistPrivate = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (ExistIScsiExtScsiPassThru);
  522. Status = gBS->UninstallProtocolInterface (
  523. ExistPrivate->ExtScsiPassThruHandle,
  524. &gEfiExtScsiPassThruProtocolGuid,
  525. &ExistPrivate->IScsiExtScsiPassThru
  526. );
  527. if (EFI_ERROR (Status)) {
  528. goto ON_ERROR;
  529. }
  530. }
  531. //
  532. // Install the Ext SCSI PASS THRU protocol.
  533. //
  534. Status = gBS->InstallProtocolInterface (
  535. &Private->ExtScsiPassThruHandle,
  536. &gEfiExtScsiPassThruProtocolGuid,
  537. EFI_NATIVE_INTERFACE,
  538. &Private->IScsiExtScsiPassThru
  539. );
  540. if (EFI_ERROR (Status)) {
  541. goto ON_ERROR;
  542. }
  543. BootSelected = 0;
  544. NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {
  545. AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
  546. //
  547. // Don't process the attempt that does not associate with the current NIC or
  548. // this attempt is disabled or established.
  549. //
  550. if ((AttemptConfigData->NicIndex != mPrivate->CurrentNic) ||
  551. (AttemptConfigData->SessionConfigData.Enabled == ISCSI_DISABLED) ||
  552. AttemptConfigData->ValidPath)
  553. {
  554. continue;
  555. }
  556. //
  557. // In multipath mode, don't process attempts configured for single path.
  558. // In default single path mode, don't process attempts configured for multipath.
  559. //
  560. if ((mPrivate->EnableMpio &&
  561. (AttemptConfigData->SessionConfigData.Enabled != ISCSI_ENABLED_FOR_MPIO)) ||
  562. (!mPrivate->EnableMpio &&
  563. (AttemptConfigData->SessionConfigData.Enabled != ISCSI_ENABLED)))
  564. {
  565. continue;
  566. }
  567. //
  568. // Don't process the attempt that fails to get the init/target information from DHCP.
  569. //
  570. if (AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp &&
  571. !AttemptConfigData->DhcpSuccess)
  572. {
  573. if (!mPrivate->EnableMpio && (mPrivate->ValidSinglePathCount > 0)) {
  574. mPrivate->ValidSinglePathCount--;
  575. }
  576. continue;
  577. }
  578. //
  579. // Don't process the autoconfigure path if it is already established.
  580. //
  581. if ((AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) &&
  582. AttemptConfigData->AutoConfigureSuccess)
  583. {
  584. continue;
  585. }
  586. //
  587. // Don't process the attempt if its IP mode is not in the current IP version.
  588. //
  589. if (!mPrivate->Ipv6Flag) {
  590. if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) {
  591. continue;
  592. }
  593. if ((AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) &&
  594. (AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6))
  595. {
  596. continue;
  597. }
  598. } else {
  599. if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) {
  600. continue;
  601. }
  602. if ((AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) &&
  603. (AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4))
  604. {
  605. continue;
  606. }
  607. }
  608. //
  609. // Fill in the Session and init it.
  610. //
  611. Session = (ISCSI_SESSION *)AllocateZeroPool (sizeof (ISCSI_SESSION));
  612. if (Session == NULL) {
  613. Status = EFI_OUT_OF_RESOURCES;
  614. goto ON_ERROR;
  615. }
  616. Session->Private = Private;
  617. Session->ConfigData = AttemptConfigData;
  618. Session->AuthType = AttemptConfigData->AuthenticationType;
  619. UnicodeSPrint (
  620. mPrivate->PortString,
  621. (UINTN)ISCSI_NAME_IFR_MAX_SIZE,
  622. L"Attempt %d",
  623. (UINTN)AttemptConfigData->AttemptConfigIndex
  624. );
  625. if (Session->AuthType == ISCSI_AUTH_TYPE_CHAP) {
  626. Session->AuthData.CHAP.AuthConfig = &AttemptConfigData->AuthConfigData.CHAP;
  627. }
  628. IScsiSessionInit (Session, FALSE);
  629. //
  630. // Try to login and create an iSCSI session according to the configuration.
  631. //
  632. Status = IScsiSessionLogin (Session);
  633. if (Status == EFI_MEDIA_CHANGED) {
  634. //
  635. // The specified target is not available, and the redirection information is
  636. // received. Login the session again with the updated target address.
  637. //
  638. Status = IScsiSessionLogin (Session);
  639. } else if (Status == EFI_NOT_READY) {
  640. Status = IScsiSessionReLogin (Session);
  641. }
  642. //
  643. // Restore the original user setting which specifies the proxy/virtual iSCSI target to NV region.
  644. //
  645. NvData = &AttemptConfigData->SessionConfigData;
  646. if (NvData->RedirectFlag) {
  647. NvData->TargetPort = NvData->OriginalTargetPort;
  648. CopyMem (&NvData->TargetIp, &NvData->OriginalTargetIp, sizeof (EFI_IP_ADDRESS));
  649. NvData->RedirectFlag = FALSE;
  650. gRT->SetVariable (
  651. mPrivate->PortString,
  652. &gEfiIScsiInitiatorNameProtocolGuid,
  653. ISCSI_CONFIG_VAR_ATTR,
  654. sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
  655. AttemptConfigData
  656. );
  657. }
  658. if (EFI_ERROR (Status)) {
  659. //
  660. // In Single path mode, only the successful attempt will be recorded in iBFT;
  661. // in multi-path mode, all the attempt entries in MPIO will be recorded in iBFT.
  662. //
  663. if (!mPrivate->EnableMpio && (mPrivate->ValidSinglePathCount > 0)) {
  664. mPrivate->ValidSinglePathCount--;
  665. }
  666. FreePool (Session);
  667. } else {
  668. AttemptConfigData->ValidPath = TRUE;
  669. //
  670. // Do not record the attempt in iBFT if it login with KRB5.
  671. // TODO: record KRB5 attempt information in the iSCSI device path.
  672. //
  673. if (Session->AuthType == ISCSI_AUTH_TYPE_KRB) {
  674. if (!mPrivate->EnableMpio && (mPrivate->ValidSinglePathCount > 0)) {
  675. mPrivate->ValidSinglePathCount--;
  676. }
  677. AttemptConfigData->ValidiBFTPath = FALSE;
  678. } else {
  679. AttemptConfigData->ValidiBFTPath = TRUE;
  680. }
  681. //
  682. // IScsi session success. Update the attempt state to NVR.
  683. //
  684. if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {
  685. AttemptConfigData->AutoConfigureSuccess = TRUE;
  686. }
  687. gRT->SetVariable (
  688. mPrivate->PortString,
  689. &gEfiIScsiInitiatorNameProtocolGuid,
  690. ISCSI_CONFIG_VAR_ATTR,
  691. sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
  692. AttemptConfigData
  693. );
  694. //
  695. // Select the first login session. Abort others.
  696. //
  697. if (Private->Session == NULL) {
  698. Private->Session = Session;
  699. BootSelected = AttemptConfigData->AttemptConfigIndex;
  700. //
  701. // Don't validate other attempt in multipath mode if one is success.
  702. //
  703. if (mPrivate->EnableMpio) {
  704. break;
  705. }
  706. } else {
  707. IScsiSessionAbort (Session);
  708. FreePool (Session);
  709. }
  710. }
  711. }
  712. //
  713. // All attempts configured for this driver instance are not valid.
  714. //
  715. if (Private->Session == NULL) {
  716. Status = gBS->UninstallProtocolInterface (
  717. Private->ExtScsiPassThruHandle,
  718. &gEfiExtScsiPassThruProtocolGuid,
  719. &Private->IScsiExtScsiPassThru
  720. );
  721. ASSERT_EFI_ERROR (Status);
  722. Private->ExtScsiPassThruHandle = NULL;
  723. //
  724. // Reinstall the original ExtScsiPassThru back.
  725. //
  726. if (mPrivate->OneSessionEstablished && (ExistPrivate != NULL)) {
  727. Status = gBS->InstallProtocolInterface (
  728. &ExistPrivate->ExtScsiPassThruHandle,
  729. &gEfiExtScsiPassThruProtocolGuid,
  730. EFI_NATIVE_INTERFACE,
  731. &ExistPrivate->IScsiExtScsiPassThru
  732. );
  733. if (EFI_ERROR (Status)) {
  734. goto ON_ERROR;
  735. }
  736. goto ON_EXIT;
  737. }
  738. Status = EFI_NOT_FOUND;
  739. goto ON_ERROR;
  740. }
  741. NeedUpdate = TRUE;
  742. //
  743. // More than one attempt successes.
  744. //
  745. if ((Private->Session != NULL) && mPrivate->OneSessionEstablished) {
  746. AttemptConfigOrder = IScsiGetVariableAndSize (
  747. L"AttemptOrder",
  748. &gIScsiConfigGuid,
  749. &AttemptConfigOrderSize
  750. );
  751. if (AttemptConfigOrder == NULL) {
  752. goto ON_ERROR;
  753. }
  754. for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
  755. if ((AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex) ||
  756. (AttemptConfigOrder[Index] == BootSelected))
  757. {
  758. break;
  759. }
  760. }
  761. if (mPrivate->EnableMpio) {
  762. //
  763. // Use the attempt in earlier order. Abort the later one in MPIO.
  764. //
  765. if (AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex) {
  766. IScsiSessionAbort (Private->Session);
  767. FreePool (Private->Session);
  768. Private->Session = NULL;
  769. gBS->UninstallProtocolInterface (
  770. Private->ExtScsiPassThruHandle,
  771. &gEfiExtScsiPassThruProtocolGuid,
  772. &Private->IScsiExtScsiPassThru
  773. );
  774. Private->ExtScsiPassThruHandle = NULL;
  775. //
  776. // Reinstall the original ExtScsiPassThru back.
  777. //
  778. Status = gBS->InstallProtocolInterface (
  779. &ExistPrivate->ExtScsiPassThruHandle,
  780. &gEfiExtScsiPassThruProtocolGuid,
  781. EFI_NATIVE_INTERFACE,
  782. &ExistPrivate->IScsiExtScsiPassThru
  783. );
  784. if (EFI_ERROR (Status)) {
  785. goto ON_ERROR;
  786. }
  787. goto ON_EXIT;
  788. } else {
  789. if (AttemptConfigOrder[Index] != BootSelected) {
  790. goto ON_ERROR;
  791. }
  792. mPrivate->BootSelectedIndex = BootSelected;
  793. //
  794. // Clear the resource in ExistPrivate.
  795. //
  796. gBS->UninstallProtocolInterface (
  797. ExistPrivate->Controller,
  798. IScsiPrivateGuid,
  799. &ExistPrivate->IScsiIdentifier
  800. );
  801. IScsiRemoveNic (ExistPrivate->Controller);
  802. if (ExistPrivate->Session != NULL) {
  803. IScsiSessionAbort (ExistPrivate->Session);
  804. }
  805. if (ExistPrivate->DevicePath != NULL) {
  806. Status = gBS->UninstallProtocolInterface (
  807. ExistPrivate->ExtScsiPassThruHandle,
  808. &gEfiDevicePathProtocolGuid,
  809. ExistPrivate->DevicePath
  810. );
  811. if (EFI_ERROR (Status)) {
  812. goto ON_ERROR;
  813. }
  814. FreePool (ExistPrivate->DevicePath);
  815. }
  816. gBS->CloseEvent (ExistPrivate->ExitBootServiceEvent);
  817. FreePool (ExistPrivate);
  818. }
  819. } else {
  820. //
  821. // Use the attempt in earlier order as boot selected in single path mode.
  822. //
  823. if (AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex) {
  824. NeedUpdate = FALSE;
  825. }
  826. }
  827. }
  828. if (NeedUpdate) {
  829. mPrivate->OneSessionEstablished = TRUE;
  830. mPrivate->BootSelectedIndex = BootSelected;
  831. }
  832. //
  833. // Duplicate the Session's tcp connection device path. The source port field
  834. // will be set to zero as one iSCSI session is comprised of several iSCSI
  835. // connections.
  836. //
  837. Private->DevicePath = IScsiGetTcpConnDevicePath (Private->Session);
  838. if (Private->DevicePath == NULL) {
  839. Status = EFI_DEVICE_ERROR;
  840. goto ON_ERROR;
  841. }
  842. //
  843. // Install the updated device path onto the ExtScsiPassThruHandle.
  844. //
  845. Status = gBS->InstallProtocolInterface (
  846. &Private->ExtScsiPassThruHandle,
  847. &gEfiDevicePathProtocolGuid,
  848. EFI_NATIVE_INTERFACE,
  849. Private->DevicePath
  850. );
  851. if (EFI_ERROR (Status)) {
  852. goto ON_ERROR;
  853. }
  854. //
  855. // ISCSI children should share the default Tcp child, just open the default Tcp child via BY_CHILD_CONTROLLER.
  856. //
  857. Status = gBS->OpenProtocol (
  858. Private->ChildHandle, /// Default Tcp child
  859. ProtocolGuid,
  860. &Interface,
  861. Image,
  862. Private->ExtScsiPassThruHandle,
  863. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  864. );
  865. if (EFI_ERROR (Status)) {
  866. gBS->UninstallMultipleProtocolInterfaces (
  867. Private->ExtScsiPassThruHandle,
  868. &gEfiExtScsiPassThruProtocolGuid,
  869. &Private->IScsiExtScsiPassThru,
  870. &gEfiDevicePathProtocolGuid,
  871. Private->DevicePath,
  872. NULL
  873. );
  874. goto ON_ERROR;
  875. }
  876. ON_EXIT:
  877. //
  878. // Update/Publish the iSCSI Boot Firmware Table.
  879. //
  880. if (mPrivate->BootSelectedIndex != 0) {
  881. IScsiPublishIbft ();
  882. }
  883. return EFI_SUCCESS;
  884. ON_ERROR:
  885. if (Private->Session != NULL) {
  886. IScsiSessionAbort (Private->Session);
  887. }
  888. return Status;
  889. }
  890. /**
  891. Stops a device controller or a bus controller. This is the worker function for
  892. IScsiIp4(6)DriverBindingStop.
  893. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  894. @param[in] ControllerHandle A handle to the device being stopped. The handle must
  895. support a bus specific I/O protocol for the driver
  896. to use to stop the device.
  897. @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
  898. @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
  899. if NumberOfChildren is 0.
  900. @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
  901. @retval EFI_SUCCESS The device was stopped.
  902. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
  903. @retval EFI_INVALID_PARAMETER Child handle is NULL.
  904. @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle
  905. because its interfaces are being used.
  906. **/
  907. EFI_STATUS
  908. EFIAPI
  909. IScsiStop (
  910. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  911. IN EFI_HANDLE ControllerHandle,
  912. IN UINTN NumberOfChildren,
  913. IN EFI_HANDLE *ChildHandleBuffer OPTIONAL,
  914. IN UINT8 IpVersion
  915. )
  916. {
  917. EFI_HANDLE IScsiController;
  918. EFI_STATUS Status;
  919. ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;
  920. ISCSI_DRIVER_DATA *Private;
  921. EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
  922. ISCSI_CONNECTION *Conn;
  923. EFI_GUID *ProtocolGuid;
  924. EFI_GUID *TcpServiceBindingGuid;
  925. EFI_GUID *TcpProtocolGuid;
  926. if (NumberOfChildren != 0) {
  927. //
  928. // We should have only one child.
  929. //
  930. Status = gBS->OpenProtocol (
  931. ChildHandleBuffer[0],
  932. &gEfiExtScsiPassThruProtocolGuid,
  933. (VOID **)&PassThru,
  934. This->DriverBindingHandle,
  935. ControllerHandle,
  936. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  937. );
  938. if (EFI_ERROR (Status)) {
  939. return EFI_DEVICE_ERROR;
  940. }
  941. Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru);
  942. Conn = NET_LIST_HEAD (&Private->Session->Conns, ISCSI_CONNECTION, Link);
  943. //
  944. // Previously the TCP protocol is opened BY_CHILD_CONTROLLER. Just close
  945. // the protocol here, but do not uninstall the device path protocol and
  946. // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.
  947. //
  948. if (IpVersion == IP_VERSION_4) {
  949. ProtocolGuid = &gEfiTcp4ProtocolGuid;
  950. } else {
  951. ProtocolGuid = &gEfiTcp6ProtocolGuid;
  952. }
  953. gBS->CloseProtocol (
  954. Private->ChildHandle,
  955. ProtocolGuid,
  956. Private->Image,
  957. Private->ExtScsiPassThruHandle
  958. );
  959. gBS->CloseProtocol (
  960. Conn->TcpIo.Handle,
  961. ProtocolGuid,
  962. Private->Image,
  963. Private->ExtScsiPassThruHandle
  964. );
  965. return EFI_SUCCESS;
  966. }
  967. //
  968. // Get the handle of the controller we are controlling.
  969. //
  970. if (IpVersion == IP_VERSION_4) {
  971. ProtocolGuid = &gIScsiV4PrivateGuid;
  972. TcpProtocolGuid = &gEfiTcp4ProtocolGuid;
  973. TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
  974. } else {
  975. ProtocolGuid = &gIScsiV6PrivateGuid;
  976. TcpProtocolGuid = &gEfiTcp6ProtocolGuid;
  977. TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
  978. }
  979. IScsiController = NetLibGetNicHandle (ControllerHandle, TcpProtocolGuid);
  980. if (IScsiController == NULL) {
  981. return EFI_SUCCESS;
  982. }
  983. Status = gBS->OpenProtocol (
  984. IScsiController,
  985. ProtocolGuid,
  986. (VOID **)&IScsiIdentifier,
  987. This->DriverBindingHandle,
  988. ControllerHandle,
  989. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  990. );
  991. if (EFI_ERROR (Status)) {
  992. return EFI_DEVICE_ERROR;
  993. }
  994. Private = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);
  995. ASSERT (Private != NULL);
  996. if (Private->ChildHandle != NULL) {
  997. Status = gBS->CloseProtocol (
  998. Private->ChildHandle,
  999. TcpProtocolGuid,
  1000. This->DriverBindingHandle,
  1001. IScsiController
  1002. );
  1003. ASSERT (!EFI_ERROR (Status));
  1004. Status = NetLibDestroyServiceChild (
  1005. IScsiController,
  1006. This->DriverBindingHandle,
  1007. TcpServiceBindingGuid,
  1008. Private->ChildHandle
  1009. );
  1010. ASSERT (!EFI_ERROR (Status));
  1011. }
  1012. gBS->UninstallProtocolInterface (
  1013. IScsiController,
  1014. ProtocolGuid,
  1015. &Private->IScsiIdentifier
  1016. );
  1017. //
  1018. // Remove this NIC.
  1019. //
  1020. IScsiRemoveNic (IScsiController);
  1021. //
  1022. // Update the iSCSI Boot Firmware Table.
  1023. //
  1024. IScsiPublishIbft ();
  1025. if (Private->Session != NULL) {
  1026. IScsiSessionAbort (Private->Session);
  1027. }
  1028. Status = IScsiCleanDriverData (Private);
  1029. if (EFI_ERROR (Status)) {
  1030. return Status;
  1031. }
  1032. return EFI_SUCCESS;
  1033. }
  1034. /**
  1035. Tests to see if this driver supports a given controller. If a child device is provided,
  1036. it tests to see if this driver supports creating a handle for the specified child device.
  1037. This function checks to see if the driver specified by This supports the device specified by
  1038. ControllerHandle. Drivers typically use the device path attached to
  1039. ControllerHandle and/or the services from the bus I/O abstraction attached to
  1040. ControllerHandle to determine if the driver supports ControllerHandle. This function
  1041. may be called many times during platform initialization. In order to reduce boot times, the tests
  1042. performed by this function must be very small and take as little time as possible to execute. This
  1043. function must not change the state of any hardware devices, and this function must be aware that the
  1044. device specified by ControllerHandle may already be managed by the same driver or a
  1045. different driver. This function must match its calls to AllocatePages() with FreePages(),
  1046. AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
  1047. Since ControllerHandle may have been previously started by the same driver, if a protocol is
  1048. already in the opened state, then it must not be closed with CloseProtocol(). This is required
  1049. to guarantee the state of ControllerHandle is not modified by this function.
  1050. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  1051. @param[in] ControllerHandle The handle of the controller to test. This handle
  1052. must support a protocol interface that supplies
  1053. an I/O abstraction to the driver.
  1054. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  1055. parameter is ignored by device drivers, and is optional for bus
  1056. drivers. For bus drivers, if this parameter is not NULL, then
  1057. the bus driver must determine if the bus controller specified
  1058. by ControllerHandle and the child controller specified
  1059. by RemainingDevicePath are both supported by this
  1060. bus driver.
  1061. @retval EFI_SUCCESS The device specified by ControllerHandle and
  1062. RemainingDevicePath is supported by the driver specified by This.
  1063. @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
  1064. RemainingDevicePath is already managed by the driver
  1065. specified by This.
  1066. @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
  1067. RemainingDevicePath is already managed by a different
  1068. driver or an application that requires exclusive access.
  1069. Currently not implemented.
  1070. @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
  1071. RemainingDevicePath is not supported by the driver specified by This.
  1072. **/
  1073. EFI_STATUS
  1074. EFIAPI
  1075. IScsiIp4DriverBindingSupported (
  1076. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  1077. IN EFI_HANDLE ControllerHandle,
  1078. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  1079. )
  1080. {
  1081. return IScsiSupported (
  1082. This,
  1083. ControllerHandle,
  1084. RemainingDevicePath,
  1085. IP_VERSION_4
  1086. );
  1087. }
  1088. /**
  1089. Starts a device controller or a bus controller.
  1090. The Start() function is designed to be invoked from the EFI boot service ConnectController().
  1091. As a result, much of the error checking on the parameters to Start() has been moved into this
  1092. common boot service. It is legal to call Start() from other locations,
  1093. but the following calling restrictions must be followed or the system behavior will not be deterministic.
  1094. 1. ControllerHandle must be a valid EFI_HANDLE.
  1095. 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
  1096. EFI_DEVICE_PATH_PROTOCOL.
  1097. 3. Prior to calling Start(), the Supported() function for the driver specified by This must
  1098. have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
  1099. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  1100. @param[in] ControllerHandle The handle of the controller to start. This handle
  1101. must support a protocol interface that supplies
  1102. an I/O abstraction to the driver.
  1103. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  1104. parameter is ignored by device drivers, and is optional for bus
  1105. drivers. For a bus driver, if this parameter is NULL, then handles
  1106. for all the children of Controller are created by this driver.
  1107. If this parameter is not NULL and the first Device Path Node is
  1108. not the End of Device Path Node, then only the handle for the
  1109. child device specified by the first Device Path Node of
  1110. RemainingDevicePath is created by this driver.
  1111. If the first Device Path Node of RemainingDevicePath is
  1112. the End of Device Path Node, no child handle is created by this
  1113. driver.
  1114. @retval EFI_SUCCESS The device was started.
  1115. @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
  1116. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
  1117. @retval Others The driver failed to start the device.
  1118. **/
  1119. EFI_STATUS
  1120. EFIAPI
  1121. IScsiIp4DriverBindingStart (
  1122. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  1123. IN EFI_HANDLE ControllerHandle,
  1124. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  1125. )
  1126. {
  1127. EFI_STATUS Status;
  1128. Status = IScsiStart (This->DriverBindingHandle, ControllerHandle, IP_VERSION_4);
  1129. if (Status == EFI_ALREADY_STARTED) {
  1130. Status = EFI_SUCCESS;
  1131. }
  1132. return Status;
  1133. }
  1134. /**
  1135. Stops a device controller or a bus controller.
  1136. The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
  1137. As a result, much of the error checking on the parameters to Stop() has been moved
  1138. into this common boot service. It is legal to call Stop() from other locations,
  1139. but the following calling restrictions must be followed or the system behavior will not be deterministic.
  1140. 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
  1141. same driver's Start() function.
  1142. 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
  1143. EFI_HANDLE. In addition, all of these handles must have been created in this driver's
  1144. Start() function, and the Start() function must have called OpenProtocol() on
  1145. ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
  1146. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  1147. @param[in] ControllerHandle A handle to the device being stopped. The handle must
  1148. support a bus specific I/O protocol for the driver
  1149. to use to stop the device.
  1150. @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
  1151. @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
  1152. if NumberOfChildren is 0.
  1153. @retval EFI_SUCCESS The device was stopped.
  1154. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
  1155. **/
  1156. EFI_STATUS
  1157. EFIAPI
  1158. IScsiIp4DriverBindingStop (
  1159. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  1160. IN EFI_HANDLE ControllerHandle,
  1161. IN UINTN NumberOfChildren,
  1162. IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
  1163. )
  1164. {
  1165. return IScsiStop (
  1166. This,
  1167. ControllerHandle,
  1168. NumberOfChildren,
  1169. ChildHandleBuffer,
  1170. IP_VERSION_4
  1171. );
  1172. }
  1173. /**
  1174. Tests to see if this driver supports a given controller. If a child device is provided,
  1175. it tests to see if this driver supports creating a handle for the specified child device.
  1176. This function checks to see if the driver specified by This supports the device specified by
  1177. ControllerHandle. Drivers typically use the device path attached to
  1178. ControllerHandle and/or the services from the bus I/O abstraction attached to
  1179. ControllerHandle to determine if the driver supports ControllerHandle. This function
  1180. may be called many times during platform initialization. In order to reduce boot times, the tests
  1181. performed by this function must be very small and take as little time as possible to execute. This
  1182. function must not change the state of any hardware devices, and this function must be aware that the
  1183. device specified by ControllerHandle may already be managed by the same driver or a
  1184. different driver. This function must match its calls to AllocatePages() with FreePages(),
  1185. AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
  1186. Since ControllerHandle may have been previously started by the same driver, if a protocol is
  1187. already in the opened state, then it must not be closed with CloseProtocol(). This is required
  1188. to guarantee the state of ControllerHandle is not modified by this function.
  1189. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  1190. @param[in] ControllerHandle The handle of the controller to test. This handle
  1191. must support a protocol interface that supplies
  1192. an I/O abstraction to the driver.
  1193. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  1194. parameter is ignored by device drivers, and is optional for bus
  1195. drivers. For bus drivers, if this parameter is not NULL, then
  1196. the bus driver must determine if the bus controller specified
  1197. by ControllerHandle and the child controller specified
  1198. by RemainingDevicePath are both supported by this
  1199. bus driver.
  1200. @retval EFI_SUCCESS The device specified by ControllerHandle and
  1201. RemainingDevicePath is supported by the driver specified by This.
  1202. @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
  1203. RemainingDevicePath is already managed by the driver
  1204. specified by This.
  1205. @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
  1206. RemainingDevicePath is already managed by a different
  1207. driver or an application that requires exclusive access.
  1208. Currently not implemented.
  1209. @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
  1210. RemainingDevicePath is not supported by the driver specified by This.
  1211. **/
  1212. EFI_STATUS
  1213. EFIAPI
  1214. IScsiIp6DriverBindingSupported (
  1215. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  1216. IN EFI_HANDLE ControllerHandle,
  1217. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  1218. )
  1219. {
  1220. return IScsiSupported (
  1221. This,
  1222. ControllerHandle,
  1223. RemainingDevicePath,
  1224. IP_VERSION_6
  1225. );
  1226. }
  1227. /**
  1228. Starts a device controller or a bus controller.
  1229. The Start() function is designed to be invoked from the EFI boot service ConnectController().
  1230. As a result, much of the error checking on the parameters to Start() has been moved into this
  1231. common boot service. It is legal to call Start() from other locations,
  1232. but the following calling restrictions must be followed or the system behavior will not be deterministic.
  1233. 1. ControllerHandle must be a valid EFI_HANDLE.
  1234. 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
  1235. EFI_DEVICE_PATH_PROTOCOL.
  1236. 3. Prior to calling Start(), the Supported() function for the driver specified by This must
  1237. have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
  1238. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  1239. @param[in] ControllerHandle The handle of the controller to start. This handle
  1240. must support a protocol interface that supplies
  1241. an I/O abstraction to the driver.
  1242. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  1243. parameter is ignored by device drivers, and is optional for bus
  1244. drivers. For a bus driver, if this parameter is NULL, then handles
  1245. for all the children of Controller are created by this driver.
  1246. If this parameter is not NULL and the first Device Path Node is
  1247. not the End of Device Path Node, then only the handle for the
  1248. child device specified by the first Device Path Node of
  1249. RemainingDevicePath is created by this driver.
  1250. If the first Device Path Node of RemainingDevicePath is
  1251. the End of Device Path Node, no child handle is created by this
  1252. driver.
  1253. @retval EFI_SUCCESS The device was started.
  1254. @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
  1255. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
  1256. @retval Others The driver failed to start the device.
  1257. **/
  1258. EFI_STATUS
  1259. EFIAPI
  1260. IScsiIp6DriverBindingStart (
  1261. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  1262. IN EFI_HANDLE ControllerHandle,
  1263. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  1264. )
  1265. {
  1266. EFI_STATUS Status;
  1267. Status = IScsiStart (This->DriverBindingHandle, ControllerHandle, IP_VERSION_6);
  1268. if (Status == EFI_ALREADY_STARTED) {
  1269. Status = EFI_SUCCESS;
  1270. }
  1271. return Status;
  1272. }
  1273. /**
  1274. Stops a device controller or a bus controller.
  1275. The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
  1276. As a result, much of the error checking on the parameters to Stop() has been moved
  1277. into this common boot service. It is legal to call Stop() from other locations,
  1278. but the following calling restrictions must be followed or the system behavior will not be deterministic.
  1279. 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
  1280. same driver's Start() function.
  1281. 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
  1282. EFI_HANDLE. In addition, all of these handles must have been created in this driver's
  1283. Start() function, and the Start() function must have called OpenProtocol() on
  1284. ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
  1285. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  1286. @param[in] ControllerHandle A handle to the device being stopped. The handle must
  1287. support a bus specific I/O protocol for the driver
  1288. to use to stop the device.
  1289. @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
  1290. @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
  1291. if NumberOfChildren is 0.
  1292. @retval EFI_SUCCESS The device was stopped.
  1293. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
  1294. **/
  1295. EFI_STATUS
  1296. EFIAPI
  1297. IScsiIp6DriverBindingStop (
  1298. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  1299. IN EFI_HANDLE ControllerHandle,
  1300. IN UINTN NumberOfChildren,
  1301. IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
  1302. )
  1303. {
  1304. return IScsiStop (
  1305. This,
  1306. ControllerHandle,
  1307. NumberOfChildren,
  1308. ChildHandleBuffer,
  1309. IP_VERSION_6
  1310. );
  1311. }
  1312. /**
  1313. Unload the iSCSI driver.
  1314. @param[in] ImageHandle The handle of the driver image.
  1315. @retval EFI_SUCCESS The driver is unloaded.
  1316. @retval EFI_DEVICE_ERROR An unexpected error occurred.
  1317. **/
  1318. EFI_STATUS
  1319. EFIAPI
  1320. IScsiUnload (
  1321. IN EFI_HANDLE ImageHandle
  1322. )
  1323. {
  1324. EFI_STATUS Status;
  1325. UINTN DeviceHandleCount;
  1326. EFI_HANDLE *DeviceHandleBuffer;
  1327. UINTN Index;
  1328. EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
  1329. EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
  1330. //
  1331. // Try to disconnect the driver from the devices it's controlling.
  1332. //
  1333. Status = gBS->LocateHandleBuffer (
  1334. AllHandles,
  1335. NULL,
  1336. NULL,
  1337. &DeviceHandleCount,
  1338. &DeviceHandleBuffer
  1339. );
  1340. if (EFI_ERROR (Status)) {
  1341. return Status;
  1342. }
  1343. //
  1344. // Disconnect the iSCSI4 driver from the controlled device.
  1345. //
  1346. for (Index = 0; Index < DeviceHandleCount; Index++) {
  1347. Status = IScsiTestManagedDevice (
  1348. DeviceHandleBuffer[Index],
  1349. gIScsiIp4DriverBinding.DriverBindingHandle,
  1350. &gEfiTcp4ProtocolGuid
  1351. )
  1352. ;
  1353. if (EFI_ERROR (Status)) {
  1354. continue;
  1355. }
  1356. Status = gBS->DisconnectController (
  1357. DeviceHandleBuffer[Index],
  1358. gIScsiIp4DriverBinding.DriverBindingHandle,
  1359. NULL
  1360. );
  1361. if (EFI_ERROR (Status)) {
  1362. goto ON_EXIT;
  1363. }
  1364. }
  1365. //
  1366. // Disconnect the iSCSI6 driver from the controlled device.
  1367. //
  1368. for (Index = 0; Index < DeviceHandleCount; Index++) {
  1369. Status = IScsiTestManagedDevice (
  1370. DeviceHandleBuffer[Index],
  1371. gIScsiIp6DriverBinding.DriverBindingHandle,
  1372. &gEfiTcp6ProtocolGuid
  1373. );
  1374. if (EFI_ERROR (Status)) {
  1375. continue;
  1376. }
  1377. Status = gBS->DisconnectController (
  1378. DeviceHandleBuffer[Index],
  1379. gIScsiIp6DriverBinding.DriverBindingHandle,
  1380. NULL
  1381. );
  1382. if (EFI_ERROR (Status)) {
  1383. goto ON_EXIT;
  1384. }
  1385. }
  1386. //
  1387. // Unload the iSCSI configuration form.
  1388. //
  1389. Status = IScsiConfigFormUnload (gIScsiIp4DriverBinding.DriverBindingHandle);
  1390. if (EFI_ERROR (Status)) {
  1391. goto ON_EXIT;
  1392. }
  1393. //
  1394. // Uninstall the protocols installed by iSCSI driver.
  1395. //
  1396. Status = gBS->UninstallMultipleProtocolInterfaces (
  1397. ImageHandle,
  1398. &gEfiAuthenticationInfoProtocolGuid,
  1399. &gIScsiAuthenticationInfo,
  1400. NULL
  1401. );
  1402. if (EFI_ERROR (Status)) {
  1403. goto ON_EXIT;
  1404. }
  1405. if (gIScsiControllerNameTable != NULL) {
  1406. Status = FreeUnicodeStringTable (gIScsiControllerNameTable);
  1407. if (EFI_ERROR (Status)) {
  1408. goto ON_EXIT;
  1409. }
  1410. gIScsiControllerNameTable = NULL;
  1411. }
  1412. //
  1413. // Uninstall the ComponentName and ComponentName2 protocol from iSCSI4 driver binding handle
  1414. // if it has been installed.
  1415. //
  1416. Status = gBS->HandleProtocol (
  1417. gIScsiIp4DriverBinding.DriverBindingHandle,
  1418. &gEfiComponentNameProtocolGuid,
  1419. (VOID **)&ComponentName
  1420. );
  1421. if (!EFI_ERROR (Status)) {
  1422. Status = gBS->UninstallMultipleProtocolInterfaces (
  1423. gIScsiIp4DriverBinding.DriverBindingHandle,
  1424. &gEfiComponentNameProtocolGuid,
  1425. ComponentName,
  1426. NULL
  1427. );
  1428. if (EFI_ERROR (Status)) {
  1429. goto ON_EXIT;
  1430. }
  1431. }
  1432. Status = gBS->HandleProtocol (
  1433. gIScsiIp4DriverBinding.DriverBindingHandle,
  1434. &gEfiComponentName2ProtocolGuid,
  1435. (VOID **)&ComponentName2
  1436. );
  1437. if (!EFI_ERROR (Status)) {
  1438. gBS->UninstallMultipleProtocolInterfaces (
  1439. gIScsiIp4DriverBinding.DriverBindingHandle,
  1440. &gEfiComponentName2ProtocolGuid,
  1441. ComponentName2,
  1442. NULL
  1443. );
  1444. if (EFI_ERROR (Status)) {
  1445. goto ON_EXIT;
  1446. }
  1447. }
  1448. //
  1449. // Uninstall the ComponentName and ComponentName2 protocol from iSCSI6 driver binding handle
  1450. // if it has been installed.
  1451. //
  1452. Status = gBS->HandleProtocol (
  1453. gIScsiIp6DriverBinding.DriverBindingHandle,
  1454. &gEfiComponentNameProtocolGuid,
  1455. (VOID **)&ComponentName
  1456. );
  1457. if (!EFI_ERROR (Status)) {
  1458. Status = gBS->UninstallMultipleProtocolInterfaces (
  1459. gIScsiIp6DriverBinding.DriverBindingHandle,
  1460. &gEfiComponentNameProtocolGuid,
  1461. ComponentName,
  1462. NULL
  1463. );
  1464. if (EFI_ERROR (Status)) {
  1465. goto ON_EXIT;
  1466. }
  1467. }
  1468. Status = gBS->HandleProtocol (
  1469. gIScsiIp6DriverBinding.DriverBindingHandle,
  1470. &gEfiComponentName2ProtocolGuid,
  1471. (VOID **)&ComponentName2
  1472. );
  1473. if (!EFI_ERROR (Status)) {
  1474. gBS->UninstallMultipleProtocolInterfaces (
  1475. gIScsiIp6DriverBinding.DriverBindingHandle,
  1476. &gEfiComponentName2ProtocolGuid,
  1477. ComponentName2,
  1478. NULL
  1479. );
  1480. if (EFI_ERROR (Status)) {
  1481. goto ON_EXIT;
  1482. }
  1483. }
  1484. //
  1485. // Uninstall the IScsiInitiatorNameProtocol and all the driver binding protocols.
  1486. //
  1487. Status = gBS->UninstallMultipleProtocolInterfaces (
  1488. gIScsiIp4DriverBinding.DriverBindingHandle,
  1489. &gEfiDriverBindingProtocolGuid,
  1490. &gIScsiIp4DriverBinding,
  1491. &gEfiIScsiInitiatorNameProtocolGuid,
  1492. &gIScsiInitiatorName,
  1493. NULL
  1494. );
  1495. if (EFI_ERROR (Status)) {
  1496. goto ON_EXIT;
  1497. }
  1498. Status = gBS->UninstallMultipleProtocolInterfaces (
  1499. gIScsiIp6DriverBinding.DriverBindingHandle,
  1500. &gEfiDriverBindingProtocolGuid,
  1501. &gIScsiIp6DriverBinding,
  1502. NULL
  1503. );
  1504. ON_EXIT:
  1505. if (DeviceHandleBuffer != NULL) {
  1506. FreePool (DeviceHandleBuffer);
  1507. }
  1508. return Status;
  1509. }
  1510. /**
  1511. This is the declaration of an EFI image entry point. This entry point is
  1512. the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
  1513. both device drivers and bus drivers.
  1514. The entry point for iSCSI driver which initializes the global variables and
  1515. installs the driver binding, component name protocol, iSCSI initiator name
  1516. protocol and Authentication Info protocol on its image.
  1517. @param[in] ImageHandle The firmware allocated handle for the UEFI image.
  1518. @param[in] SystemTable A pointer to the EFI System Table.
  1519. @retval EFI_SUCCESS The operation completed successfully.
  1520. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
  1521. **/
  1522. EFI_STATUS
  1523. EFIAPI
  1524. IScsiDriverEntryPoint (
  1525. IN EFI_HANDLE ImageHandle,
  1526. IN EFI_SYSTEM_TABLE *SystemTable
  1527. )
  1528. {
  1529. EFI_STATUS Status;
  1530. EFI_ISCSI_INITIATOR_NAME_PROTOCOL *IScsiInitiatorName;
  1531. EFI_AUTHENTICATION_INFO_PROTOCOL *AuthenticationInfo;
  1532. //
  1533. // There should be only one EFI_ISCSI_INITIATOR_NAME_PROTOCOL.
  1534. //
  1535. Status = gBS->LocateProtocol (
  1536. &gEfiIScsiInitiatorNameProtocolGuid,
  1537. NULL,
  1538. (VOID **)&IScsiInitiatorName
  1539. );
  1540. if (!EFI_ERROR (Status)) {
  1541. return EFI_ACCESS_DENIED;
  1542. }
  1543. //
  1544. // Initialize the EFI Driver Library.
  1545. //
  1546. Status = EfiLibInstallDriverBindingComponentName2 (
  1547. ImageHandle,
  1548. SystemTable,
  1549. &gIScsiIp4DriverBinding,
  1550. ImageHandle,
  1551. &gIScsiComponentName,
  1552. &gIScsiComponentName2
  1553. );
  1554. if (EFI_ERROR (Status)) {
  1555. return Status;
  1556. }
  1557. Status = EfiLibInstallDriverBindingComponentName2 (
  1558. ImageHandle,
  1559. SystemTable,
  1560. &gIScsiIp6DriverBinding,
  1561. NULL,
  1562. &gIScsiComponentName,
  1563. &gIScsiComponentName2
  1564. );
  1565. if (EFI_ERROR (Status)) {
  1566. goto Error1;
  1567. }
  1568. //
  1569. // Install the iSCSI Initiator Name Protocol.
  1570. //
  1571. Status = gBS->InstallProtocolInterface (
  1572. &ImageHandle,
  1573. &gEfiIScsiInitiatorNameProtocolGuid,
  1574. EFI_NATIVE_INTERFACE,
  1575. &gIScsiInitiatorName
  1576. );
  1577. if (EFI_ERROR (Status)) {
  1578. goto Error2;
  1579. }
  1580. //
  1581. // Create the private data structures.
  1582. //
  1583. IScsiCHAPInitHashList ();
  1584. mPrivate = AllocateZeroPool (sizeof (ISCSI_PRIVATE_DATA));
  1585. if (mPrivate == NULL) {
  1586. Status = EFI_OUT_OF_RESOURCES;
  1587. goto Error3;
  1588. }
  1589. InitializeListHead (&mPrivate->NicInfoList);
  1590. InitializeListHead (&mPrivate->AttemptConfigs);
  1591. //
  1592. // Initialize the configuration form of iSCSI.
  1593. //
  1594. Status = IScsiConfigFormInit (gIScsiIp4DriverBinding.DriverBindingHandle);
  1595. if (EFI_ERROR (Status)) {
  1596. goto Error4;
  1597. }
  1598. //
  1599. // Create the Maximum Attempts.
  1600. //
  1601. Status = IScsiCreateAttempts (PcdGet8 (PcdMaxIScsiAttemptNumber));
  1602. if (EFI_ERROR (Status)) {
  1603. goto Error5;
  1604. }
  1605. //
  1606. // Create Keywords for all the Attempts.
  1607. //
  1608. Status = IScsiCreateKeywords (PcdGet8 (PcdMaxIScsiAttemptNumber));
  1609. if (EFI_ERROR (Status)) {
  1610. goto Error6;
  1611. }
  1612. //
  1613. // There should be only one EFI_AUTHENTICATION_INFO_PROTOCOL. If already exists,
  1614. // do not produce the protocol instance.
  1615. //
  1616. Status = gBS->LocateProtocol (
  1617. &gEfiAuthenticationInfoProtocolGuid,
  1618. NULL,
  1619. (VOID **)&AuthenticationInfo
  1620. );
  1621. if (Status == EFI_NOT_FOUND) {
  1622. Status = gBS->InstallProtocolInterface (
  1623. &ImageHandle,
  1624. &gEfiAuthenticationInfoProtocolGuid,
  1625. EFI_NATIVE_INTERFACE,
  1626. &gIScsiAuthenticationInfo
  1627. );
  1628. if (EFI_ERROR (Status)) {
  1629. goto Error6;
  1630. }
  1631. }
  1632. return EFI_SUCCESS;
  1633. Error6:
  1634. IScsiCleanAttemptVariable ();
  1635. Error5:
  1636. IScsiConfigFormUnload (gIScsiIp4DriverBinding.DriverBindingHandle);
  1637. Error4:
  1638. if (mPrivate != NULL) {
  1639. FreePool (mPrivate);
  1640. mPrivate = NULL;
  1641. }
  1642. Error3:
  1643. gBS->UninstallMultipleProtocolInterfaces (
  1644. ImageHandle,
  1645. &gEfiIScsiInitiatorNameProtocolGuid,
  1646. &gIScsiInitiatorName,
  1647. NULL
  1648. );
  1649. Error2:
  1650. EfiLibUninstallDriverBindingComponentName2 (
  1651. &gIScsiIp6DriverBinding,
  1652. &gIScsiComponentName,
  1653. &gIScsiComponentName2
  1654. );
  1655. Error1:
  1656. EfiLibUninstallDriverBindingComponentName2 (
  1657. &gIScsiIp4DriverBinding,
  1658. &gIScsiComponentName,
  1659. &gIScsiComponentName2
  1660. );
  1661. return Status;
  1662. }