TianoCore EDK2 master
Loading...
Searching...
No Matches
PlatformHostInterfaceBmcUsbNicLib.c
Go to the documentation of this file.
1
12
13static EFI_GUID mPlatformHostInterfaceBmcUsbNicReadinessGuid =
14 BMC_USB_NIC_HOST_INTERFASCE_READINESS_GUID;
15static EFI_EVENT mPlatformHostInterfaceSnpEvent = NULL;
16static VOID *mPlatformHostInterfaceSnpRegistration = NULL;
17
18static LIST_ENTRY mBmcUsbNic;
19static LIST_ENTRY mBmcIpmiLan;
20
29BOOLEAN
31 VOID
32 )
33{
35 EDKII_REDFISH_CREDENTIAL2_PROTOCOL *CredentialProtocol;
36 CHAR8 *UserName;
37 CHAR8 *Password;
38 BOOLEAN ReturnBool;
39 EFI_STATUS Status;
40
41 DEBUG ((DEBUG_MANAGEABILITY, "%a: Entry\n", __func__));
42
43 ReturnBool = FALSE;
44 //
45 // Locate HII credential protocol.
46 //
47 Status = gBS->LocateProtocol (
48 &gEdkIIRedfishCredential2ProtocolGuid,
49 NULL,
50 (VOID **)&CredentialProtocol
51 );
52 if (EFI_ERROR (Status)) {
53 ASSERT_EFI_ERROR (Status);
54 return FALSE;
55 }
56
57 Status = CredentialProtocol->GetAuthInfo (
58 CredentialProtocol,
59 &AuthMethod,
60 &UserName,
61 &Password
62 );
63 if (!EFI_ERROR (Status)) {
64 ZeroMem (Password, AsciiStrSize (Password));
65 FreePool (Password);
66 ZeroMem (UserName, AsciiStrSize (UserName));
67 FreePool (UserName);
68 ReturnBool = TRUE;
69 } else {
70 if (Status == EFI_ACCESS_DENIED) {
71 // bootstrap credential support was disabled
72 ReturnBool = TRUE;
73 }
74 }
75
76 DEBUG ((
78 " Redfish Credential Bootstrapping is %a\n",
79 ReturnBool ? "supported" : "not supported"
80 ));
81 return ReturnBool;
82}
83
96 IN UINT8 *DeviceType,
97 OUT REDFISH_INTERFACE_DATA **DeviceDescriptor
98 )
99{
101 REDFISH_INTERFACE_DATA *InterfaceData;
102
103 DEBUG ((DEBUG_MANAGEABILITY, "%a: Entry\n", __func__));
104
105 if (IsListEmpty (&mBmcUsbNic)) {
106 return EFI_NOT_FOUND;
107 }
108
109 // Check if BMC exposed USB NIC is found and ready for using.
110 ThisInstance = (HOST_INTERFACE_BMC_USB_NIC_INFO *)GetFirstNode (&mBmcUsbNic);
111 while (TRUE) {
112 if (ThisInstance->IsExposedByBmc && ThisInstance->IsSuppportedHostInterface) {
113 *DeviceType = REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2;
114
115 // Fill up REDFISH_INTERFACE_DATA defined in Redfish host interface spec v1.3
117 if (InterfaceData == NULL) {
118 DEBUG ((DEBUG_ERROR, "Failed to allocate memory for REDFISH_INTERFACE_DATA\n"));
119 return EFI_OUT_OF_RESOURCES;
120 }
121
122 InterfaceData->DeviceType = REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2;
124 InterfaceData->DeviceDescriptor.UsbDeviceV2.IdVendor = ThisInstance->UsbVendorId;
125 InterfaceData->DeviceDescriptor.UsbDeviceV2.IdProduct = ThisInstance->UsbProductId;
127 CopyMem (
128 (VOID *)&InterfaceData->DeviceDescriptor.UsbDeviceV2.MacAddress,
129 (VOID *)ThisInstance->MacAddress,
130 sizeof (InterfaceData->DeviceDescriptor.UsbDeviceV2.MacAddress)
131 );
132 InterfaceData->DeviceDescriptor.UsbDeviceV2.Characteristics |= (UINT16)ThisInstance->CredentialBootstrapping;
134 *DeviceDescriptor = InterfaceData;
135 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " REDFISH_INTERFACE_DATA is returned successfully.\n"));
136 return EFI_SUCCESS;
137 }
138
139 if (IsNodeAtEnd (&mBmcUsbNic, &ThisInstance->NextInstance)) {
140 break;
141 }
142
143 ThisInstance = (HOST_INTERFACE_BMC_USB_NIC_INFO *)
144 GetNextNode (&mBmcUsbNic, &ThisInstance->NextInstance);
145 }
146
147 return EFI_NOT_FOUND;
148}
149
166 IN UINT8 IndexOfProtocolData
167 )
168{
170 MC_HOST_INTERFACE_PROTOCOL_RECORD *ThisProtocolRecord;
171 REDFISH_OVER_IP_PROTOCOL_DATA *RedfishOverIpData;
172 UINT8 HostNameLength;
173 CHAR8 *HostNameString;
174
175 DEBUG ((DEBUG_MANAGEABILITY, "%a: Entry\n", __func__));
176
177 if (IsListEmpty (&mBmcUsbNic) || (IndexOfProtocolData > 0)) {
178 return EFI_NOT_FOUND;
179 }
180
181 ThisInstance = (HOST_INTERFACE_BMC_USB_NIC_INFO *)GetFirstNode (&mBmcUsbNic);
182 while (TRUE) {
183 if (ThisInstance->IsExposedByBmc && ThisInstance->IsSuppportedHostInterface) {
184 // Get the host name before allocating memory.
185 HostNameString = (CHAR8 *)PcdGetPtr (PcdRedfishHostName);
186 HostNameLength = (UINT8)AsciiStrSize (HostNameString);
189 sizeof (REDFISH_OVER_IP_PROTOCOL_DATA) - 1 +
190 HostNameLength
191 );
192 if (ThisProtocolRecord == NULL) {
193 DEBUG ((DEBUG_ERROR, " Allocate memory fail for MC_HOST_INTERFACE_PROTOCOL_RECORD.\n"));
194 return EFI_OUT_OF_RESOURCES;
195 }
196
197 ThisProtocolRecord->ProtocolType = MCHostInterfaceProtocolTypeRedfishOverIP;
198 ThisProtocolRecord->ProtocolTypeDataLen = sizeof (REDFISH_OVER_IP_PROTOCOL_DATA) -1 + HostNameLength;
199 RedfishOverIpData = (REDFISH_OVER_IP_PROTOCOL_DATA *)&ThisProtocolRecord->ProtocolTypeData[0];
200 //
201 // Fill up REDFISH_OVER_IP_PROTOCOL_DATA
202 //
203
204 // Service UUID
205 ZeroMem ((VOID *)&RedfishOverIpData->ServiceUuid, sizeof (EFI_GUID));
206 if (StrLen ((CONST CHAR16 *)PcdGetPtr (PcdRedfishServiceUuid)) != 0) {
207 StrToGuid ((CONST CHAR16 *)PcdGetPtr (PcdRedfishServiceUuid), &RedfishOverIpData->ServiceUuid);
208 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Service UUID: %g", &RedfishOverIpData->ServiceUuid));
209 }
210
211 // HostIpAddressFormat and RedfishServiceIpDiscoveryType
212 RedfishOverIpData->HostIpAssignmentType = RedfishHostIpAssignmentUnknown;
213 RedfishOverIpData->RedfishServiceIpDiscoveryType = RedfishHostIpAssignmentUnknown;
214 if (ThisInstance->IpAssignedType == IpmiStaticAddrsss) {
215 RedfishOverIpData->HostIpAssignmentType = RedfishHostIpAssignmentStatic;
216 RedfishOverIpData->RedfishServiceIpDiscoveryType = RedfishHostIpAssignmentStatic;
217 } else if (ThisInstance->IpAssignedType == IpmiDynamicAddressBmcDhcp) {
218 RedfishOverIpData->HostIpAssignmentType = RedfishHostIpAssignmentDhcp;
219 RedfishOverIpData->RedfishServiceIpDiscoveryType = RedfishHostIpAssignmentDhcp;
220 }
221
222 // HostIpAddressFormat and RedfishServiceIpAddressFormat, only support IPv4 for now.
223 RedfishOverIpData->HostIpAddressFormat = REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP4;
224 RedfishOverIpData->RedfishServiceIpAddressFormat = REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP4;
225
226 // HostIpAddress
227 CopyMem (
228 (VOID *)RedfishOverIpData->HostIpAddress,
229 (VOID *)ThisInstance->HostIpAddressIpv4,
230 sizeof (ThisInstance->HostIpAddressIpv4)
231 );
232
233 // HostIpMask and RedfishServiceIpMask
234 CopyMem (
235 (VOID *)RedfishOverIpData->HostIpMask,
236 (VOID *)ThisInstance->SubnetMaskIpv4,
237 sizeof (ThisInstance->SubnetMaskIpv4)
238 );
239 CopyMem (
240 (VOID *)RedfishOverIpData->RedfishServiceIpMask,
241 (VOID *)ThisInstance->SubnetMaskIpv4,
242 sizeof (ThisInstance->SubnetMaskIpv4)
243 );
244
245 // RedfishServiceIpAddress
246 CopyMem (
247 (VOID *)RedfishOverIpData->RedfishServiceIpAddress,
248 (VOID *)ThisInstance->RedfishIpAddressIpv4,
249 sizeof (ThisInstance->RedfishIpAddressIpv4)
250 );
251
252 // RedfishServiceIpPort
253 RedfishOverIpData->RedfishServiceIpPort = PcdGet16 (PcdRedfishServicePort);
254
255 // RedfishServiceVlanId
256 RedfishOverIpData->RedfishServiceVlanId = ThisInstance->VLanId;
257
258 // RedfishServiceHostnameLength
259 RedfishOverIpData->RedfishServiceHostnameLength = HostNameLength;
260
261 // Redfish host name.
262 CopyMem (
263 (VOID *)&RedfishOverIpData->RedfishServiceHostname,
264 (VOID *)HostNameString,
265 HostNameLength
266 );
267
268 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " MC_HOST_INTERFACE_PROTOCOL_RECORD is returned successfully.\n"));
269 *ProtocolRecord = ThisProtocolRecord;
270 return EFI_SUCCESS;
271 }
272
273 if (IsNodeAtEnd (&mBmcUsbNic, &ThisInstance->NextInstance)) {
274 break;
275 }
276
277 ThisInstance = (HOST_INTERFACE_BMC_USB_NIC_INFO *)
278 GetNextNode (&mBmcUsbNic, &ThisInstance->NextInstance);
279 }
280
281 return EFI_NOT_FOUND;
282}
283
294 VOID
295 )
296{
297 EFI_STATUS Status;
298 UINT32 ResponseDataSize;
302 IPMI_LAN_IP_ADDRESS_SRC *IpAddressSrc;
303 IPMI_LAN_IP_ADDRESS *DestIpAddress;
304 IPMI_LAN_SUBNET_MASK *SubnetMask;
305 IPMI_LAN_DEFAULT_GATEWAY *DefaultGateway;
306 IPMI_LAN_VLAN_ID *LanVlanId;
307 EFI_USB_DEVICE_DESCRIPTOR UsbDeviceDescriptor;
308
309 DEBUG ((DEBUG_MANAGEABILITY, "%a: Entry\n", __func__));
310
311 if (IsListEmpty (&mBmcUsbNic)) {
312 return EFI_NOT_FOUND;
313 }
314
315 ThisInstance = (HOST_INTERFACE_BMC_USB_NIC_INFO *)GetFirstNode (&mBmcUsbNic);
316 while (TRUE) {
317 if (ThisInstance->IsExposedByBmc) {
318 ThisInstance->IsSuppportedHostInterface = FALSE;
319
320 // Probe if Redfish Host Interface Credential Bootstrapping is supported.
322
323 // Get IP address source
324 GetLanConfigReq.SetSelector = 0;
325 GetLanConfigReq.BlockSelector = 0;
326 GetLanConfigReq.ChannelNumber.Bits.ChannelNo = ThisInstance->IpmiLanChannelNumber;
327 GetLanConfigReq.ChannelNumber.Bits.GetParameter = 0;
328 GetLanConfigReq.ChannelNumber.Bits.Reserved = 0;
329 GetLanConfigReq.ParameterSelector = IpmiLanIpAddressSource;
330 ResponseDataSize = sizeof (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE) + sizeof (IPMI_LAN_IP_ADDRESS_SRC);
331 GetLanConfigReps = (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE *)AllocateZeroPool (ResponseDataSize);
332 GetLanConfigReps->CompletionCode = IPMI_COMP_CODE_UNSPECIFIED;
334 &GetLanConfigReq,
335 GetLanConfigReps,
336 &ResponseDataSize
337 );
338 if (EFI_ERROR (Status) || (GetLanConfigReps->CompletionCode != IPMI_COMP_CODE_NORMAL)) {
339 DEBUG ((DEBUG_ERROR, " Failed to get IP address source at channel %d: %r, 0x%02x.\n", ThisInstance->IpmiLanChannelNumber, Status, GetLanConfigReps->CompletionCode));
340 FreePool (GetLanConfigReps);
341 return Status;
342 }
343
344 IpAddressSrc = (IPMI_LAN_IP_ADDRESS_SRC *)(GetLanConfigReps + 1);
345 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " IP address source at channel %d: %x\n", ThisInstance->IpmiLanChannelNumber, IpAddressSrc->Bits.AddressSrc));
346 ThisInstance->IpAssignedType = IpAddressSrc->Bits.AddressSrc;
347 FreePool (GetLanConfigReps);
348
349 // Get LAN IPv4 IP address
350 GetLanConfigReq.ParameterSelector = IpmiLanIpAddress;
351 ResponseDataSize = sizeof (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE) + sizeof (IPMI_LAN_IP_ADDRESS);
352 GetLanConfigReps = (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE *)AllocateZeroPool (ResponseDataSize);
353 GetLanConfigReps->CompletionCode = IPMI_COMP_CODE_UNSPECIFIED;
355 &GetLanConfigReq,
356 GetLanConfigReps,
357 &ResponseDataSize
358 );
359 if (EFI_ERROR (Status) || (GetLanConfigReps->CompletionCode != IPMI_COMP_CODE_NORMAL)) {
360 DEBUG ((DEBUG_ERROR, " Failed to get Dest IP address at channel %d: %r, 0x%02x.\n", ThisInstance->IpmiLanChannelNumber, Status, GetLanConfigReps->CompletionCode));
361 FreePool (GetLanConfigReps);
362 return Status;
363 }
364
365 DestIpAddress = (IPMI_LAN_IP_ADDRESS *)(GetLanConfigReps + 1);
366 DEBUG ((
368 " Dest IP address at channel %d: %d.%d.%d.%d\n",
369 ThisInstance->IpmiLanChannelNumber,
370 DestIpAddress->IpAddress[0],
371 DestIpAddress->IpAddress[1],
372 DestIpAddress->IpAddress[2],
373 DestIpAddress->IpAddress[3]
374 ));
375 CopyMem ((VOID *)&ThisInstance->RedfishIpAddressIpv4, (VOID *)&DestIpAddress->IpAddress, sizeof (DestIpAddress->IpAddress));
376 //
377 // According to the design spec:
378 // https://github.com/tianocore/edk2/tree/master/RedfishPkg#platform-with-bmc-and-the-bmc-exposed-usb-network-device
379 // The IP address at BMC USB NIC host end is the IP address at BMC end minus 1.
380 //
381 CopyMem ((VOID *)&ThisInstance->HostIpAddressIpv4, (VOID *)&DestIpAddress->IpAddress, sizeof (DestIpAddress->IpAddress));
382 ThisInstance->HostIpAddressIpv4[sizeof (ThisInstance->HostIpAddressIpv4) - 1] -= 1;
383 FreePool (GetLanConfigReps);
384 DEBUG ((
386 " Host IP address at channel %d: %d.%d.%d.%d\n",
387 ThisInstance->IpmiLanChannelNumber,
388 ThisInstance->HostIpAddressIpv4[0],
389 ThisInstance->HostIpAddressIpv4[1],
390 ThisInstance->HostIpAddressIpv4[2],
391 ThisInstance->HostIpAddressIpv4[3]
392 ));
393
394 // Get IPv4 subnet mask
395 GetLanConfigReq.ParameterSelector = IpmiLanSubnetMask;
396 ResponseDataSize = sizeof (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE) + sizeof (IPMI_LAN_SUBNET_MASK);
397 GetLanConfigReps = (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE *)AllocateZeroPool (ResponseDataSize);
398 GetLanConfigReps->CompletionCode = IPMI_COMP_CODE_UNSPECIFIED;
400 &GetLanConfigReq,
401 GetLanConfigReps,
402 &ResponseDataSize
403 );
404 if ((EFI_ERROR (Status)) || (GetLanConfigReps->CompletionCode != IPMI_COMP_CODE_NORMAL)) {
405 DEBUG ((DEBUG_ERROR, " Failed to get subnet mask at channel %d: %r, 0x%02x.\n", ThisInstance->IpmiLanChannelNumber, Status, GetLanConfigReps->CompletionCode));
406 FreePool (GetLanConfigReps);
407 return Status;
408 }
409
410 SubnetMask = (IPMI_LAN_SUBNET_MASK *)(GetLanConfigReps + 1);
411 DEBUG ((
413 " Subnet mask at channel %d: %d.%d.%d.%d\n",
414 ThisInstance->IpmiLanChannelNumber,
415 SubnetMask->IpAddress[0],
416 SubnetMask->IpAddress[1],
417 SubnetMask->IpAddress[2],
418 SubnetMask->IpAddress[3]
419 ));
420 CopyMem ((VOID *)&ThisInstance->SubnetMaskIpv4, (VOID *)&SubnetMask->IpAddress, sizeof (SubnetMask->IpAddress));
421 FreePool (GetLanConfigReps);
422
423 // Get Gateway IP address.
424 GetLanConfigReq.ParameterSelector = IpmiLanDefaultGateway;
426 GetLanConfigReps = (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE *)AllocateZeroPool (ResponseDataSize);
427 GetLanConfigReps->CompletionCode = IPMI_COMP_CODE_UNSPECIFIED;
429 &GetLanConfigReq,
430 GetLanConfigReps,
431 &ResponseDataSize
432 );
433 if ((EFI_ERROR (Status)) || (GetLanConfigReps->CompletionCode != IPMI_COMP_CODE_NORMAL)) {
434 DEBUG ((DEBUG_ERROR, " Failed to get default gateway at channel %d: %r, 0x%02x.\n", ThisInstance->IpmiLanChannelNumber, Status, GetLanConfigReps->CompletionCode));
435 FreePool (GetLanConfigReps);
436 return Status;
437 }
438
439 DefaultGateway = (IPMI_LAN_DEFAULT_GATEWAY *)(GetLanConfigReps + 1);
440 DEBUG ((
442 " Gateway at channel %d: %d.%d.%d.%d\n",
443 ThisInstance->IpmiLanChannelNumber,
444 DefaultGateway->IpAddress[0],
445 DefaultGateway->IpAddress[1],
446 DefaultGateway->IpAddress[2],
447 DefaultGateway->IpAddress[3]
448 ));
449 CopyMem ((VOID *)&ThisInstance->GatewayIpv4, (VOID *)&DefaultGateway->IpAddress, sizeof (DefaultGateway->IpAddress));
450 FreePool (GetLanConfigReps);
451
452 // Get VLAN ID
453 GetLanConfigReq.ParameterSelector = IpmiLanVlanId;
454 ResponseDataSize = sizeof (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE) + sizeof (IPMI_LAN_VLAN_ID);
455 GetLanConfigReps = (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE *)AllocateZeroPool (ResponseDataSize);
456 GetLanConfigReps->CompletionCode = IPMI_COMP_CODE_UNSPECIFIED;
458 &GetLanConfigReq,
459 GetLanConfigReps,
460 &ResponseDataSize
461 );
462 if ((EFI_ERROR (Status)) || (GetLanConfigReps->CompletionCode != IPMI_COMP_CODE_NORMAL)) {
463 DEBUG ((DEBUG_ERROR, " Failed to get VLAN ID at channel %d: %r, 0x%02x.\n", ThisInstance->IpmiLanChannelNumber, Status, GetLanConfigReps->CompletionCode));
464 FreePool (GetLanConfigReps);
465 return Status;
466 }
467
468 LanVlanId = (IPMI_LAN_VLAN_ID *)(GetLanConfigReps + 1);
469 ThisInstance->VLanId = 0;
470 if (LanVlanId->Data2.Bits.Enabled == 1) {
471 ThisInstance->VLanId = LanVlanId->Data1.VanIdLowByte | (LanVlanId->Data2.Bits.VanIdHighByte << 8);
472 }
473
474 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " VLAN ID %x\n", ThisInstance->VLanId));
475
476 FreePool (GetLanConfigReps);
477
478 //
479 // Read USB device information.
480 //
481 if (ThisInstance->ThisUsbIo != NULL) {
482 Status = ThisInstance->ThisUsbIo->UsbGetDeviceDescriptor (ThisInstance->ThisUsbIo, &UsbDeviceDescriptor);
483 if (!EFI_ERROR (Status)) {
484 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " USB NIC Vendor ID: 0x%04x, Device ID: 0x%04x\n", UsbDeviceDescriptor.IdVendor, UsbDeviceDescriptor.IdProduct));
485 ThisInstance->UsbVendorId = UsbDeviceDescriptor.IdVendor;
486 ThisInstance->UsbProductId = UsbDeviceDescriptor.IdProduct;
487 } else {
488 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Fail to get USB device descriptor.\n"));
489 }
490 }
491
492 // All information is retrieved.
493 ThisInstance->IsSuppportedHostInterface = TRUE;
494 return EFI_SUCCESS;
495 }
496
497 if (IsNodeAtEnd (&mBmcUsbNic, &ThisInstance->NextInstance)) {
498 break;
499 }
500
501 ThisInstance = (HOST_INTERFACE_BMC_USB_NIC_INFO *)
502 GetNextNode (&mBmcUsbNic, &ThisInstance->NextInstance);
503 }
504
505 return EFI_NOT_FOUND;
506}
507
524 IN UINT8 ChannelNum,
525 IN EFI_MAC_ADDRESS *IpmiLanChannelMacAddress,
526 IN UINT8 IpmiLanMacAddressSize
527 )
528{
529 BMC_IPMI_LAN_CHANNEL_INFO *ChannelInfo;
530
532 if (ChannelInfo == NULL) {
533 return EFI_OUT_OF_RESOURCES;
534 }
535
536 ChannelInfo->Channel = ChannelNum;
537 CopyMem ((VOID *)&ChannelInfo->MacAddress.Addr, (VOID *)IpmiLanChannelMacAddress->Addr, IpmiLanMacAddressSize);
538 ChannelInfo->MacAddressSize = IpmiLanMacAddressSize;
539 InitializeListHead (&ChannelInfo->NextInstance);
540 InsertTailList (&mBmcIpmiLan, &ChannelInfo->NextInstance);
541 return EFI_SUCCESS;
542}
543
558 IN UINT8 ChannelNum,
559 OUT BMC_IPMI_LAN_CHANNEL_INFO **CachedIpmiLanChannel
560 )
561{
562 BMC_IPMI_LAN_CHANNEL_INFO *ThisInstance;
563
564 if (IsListEmpty (&mBmcIpmiLan)) {
565 return EFI_NOT_FOUND;
566 }
567
568 ThisInstance = (BMC_IPMI_LAN_CHANNEL_INFO *)GetFirstNode (&mBmcIpmiLan);
569 while (TRUE) {
570 if (ThisInstance->Channel == ChannelNum) {
571 *CachedIpmiLanChannel = ThisInstance;
572 return EFI_SUCCESS;
573 }
574
575 if (IsNodeAtEnd (&mBmcIpmiLan, &ThisInstance->NextInstance)) {
576 break;
577 }
578
579 ThisInstance = (BMC_IPMI_LAN_CHANNEL_INFO *)
580 GetNextNode (&mBmcIpmiLan, &ThisInstance->NextInstance);
581 }
582
583 return EFI_NOT_FOUND;
584}
585
601 )
602{
603 EFI_STATUS Status;
604 EFI_STATUS ExitStatus;
605 UINTN ChannelNum;
606 UINT32 ResponseDataSize;
607 IPMI_GET_CHANNEL_INFO_REQUEST GetChanelInfoRequest;
608 IPMI_GET_CHANNEL_INFO_RESPONSE GetChanelInfoResponse;
611 BMC_IPMI_LAN_CHANNEL_INFO *CachedIpmiLanChannel;
612 UINT8 IpmiLanMacAddressSize;
613 EFI_MAC_ADDRESS IpmiLanChannelMacAddress;
614 BOOLEAN AlreadyCached;
615
616 DEBUG ((DEBUG_MANAGEABILITY, "%a: Entry.\n", __func__));
617
618 GetLanConfigReps = NULL;
619 AlreadyCached = FALSE;
620 if (!IsListEmpty (&mBmcIpmiLan)) {
621 AlreadyCached = TRUE;
622 }
623
624 // Initial the get MAC address request.
625 GetLanConfigReq.ChannelNumber.Uint8 = 0;
626 GetLanConfigReq.SetSelector = 0;
627 GetLanConfigReq.BlockSelector = 0;
628 GetLanConfigReq.ParameterSelector = IpmiLanMacAddress;
629
630 ExitStatus = EFI_NOT_FOUND;
631 for (ChannelNum = IPMI_CHANNEL_NUMBER_IMPLEMENTATION_SPECIFIC_1;
632 ChannelNum <= IPMI_CHANNEL_NUMBER_IMPLEMENTATION_SPECIFIC_11;
633 ChannelNum++)
634 {
635 IpmiLanMacAddressSize = 0;
636
637 // Check if the IPMI channel information is already cached.
638 Status = EFI_NOT_FOUND;
639 if (AlreadyCached) {
640 Status = CheckCachedIpmiLanMac ((UINT8)ChannelNum, &CachedIpmiLanChannel);
641 }
642
643 if (Status == EFI_SUCCESS) {
644 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Got cached IPMI LAN info.\n"));
645 IpmiLanMacAddressSize = sizeof (IPMI_LAN_MAC_ADDRESS);
646 CopyMem ((VOID *)&IpmiLanChannelMacAddress.Addr, (VOID *)&CachedIpmiLanChannel->MacAddress.Addr, IpmiLanMacAddressSize);
647 } else {
648 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " No cached IPMI LAN info\n"));
649 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Send NetFn = App, Command = 0x42 to channel %d\n", ChannelNum));
650 GetChanelInfoRequest.ChannelNumber.Uint8 = 0;
651 GetChanelInfoRequest.ChannelNumber.Bits.ChannelNo = (UINT8)ChannelNum;
652 Status = IpmiGetChannelInfo (
653 &GetChanelInfoRequest,
654 &GetChanelInfoResponse,
655 &ResponseDataSize
656 );
657 if (EFI_ERROR (Status)) {
658 DEBUG ((DEBUG_ERROR, " - Channel %d fails to send command.\n", ChannelNum));
659 continue;
660 }
661
662 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " - Response data size = 0x%x\n", ResponseDataSize));
663 if ((GetChanelInfoResponse.CompletionCode != IPMI_COMP_CODE_NORMAL) || (ResponseDataSize == 0)) {
664 DEBUG ((DEBUG_ERROR, " - Command returned fail: 0x%x.\n", GetChanelInfoResponse.CompletionCode));
665 continue;
666 }
667
668 DEBUG ((
670 " - Channel protocol = 0x%x, Media = 0x%x\n",
671 GetChanelInfoResponse.ProtocolType.Bits.ChannelProtocolType,
672 GetChanelInfoResponse.MediumType.Bits.ChannelMediumType
673 ));
674
675 if (GetChanelInfoResponse.ChannelNumber.Bits.ChannelNo != ChannelNum) {
676 DEBUG ((
677 DEBUG_ERROR,
678 " - ChannelNumber = %d in the response which is not macthed to the request.\n",
679 GetChanelInfoResponse.ChannelNumber.Bits.ChannelNo
680 ));
681 continue;
682 }
683
684 if ((GetChanelInfoResponse.MediumType.Bits.ChannelMediumType == IPMI_CHANNEL_MEDIA_TYPE_802_3_LAN) &&
685 (GetChanelInfoResponse.ProtocolType.Bits.ChannelProtocolType == IPMI_CHANNEL_PROTOCOL_TYPE_IPMB_1_0))
686 {
687 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " - Channel %d is a LAN device!\n", ChannelNum));
688
689 ResponseDataSize = sizeof (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE) +
690 sizeof (IPMI_LAN_MAC_ADDRESS);
691 if (GetLanConfigReps == NULL) {
692 GetLanConfigReps =
694 if (GetLanConfigReps == NULL) {
695 DEBUG ((DEBUG_ERROR, " Allocate memory failed for getting MAC address.\n"));
696 continue;
697 }
698 }
699
700 GetLanConfigReq.ChannelNumber.Bits.ChannelNo = (UINT8)ChannelNum;
701 GetLanConfigReps->CompletionCode = IPMI_COMP_CODE_UNSPECIFIED;
703 &GetLanConfigReq,
704 GetLanConfigReps,
705 &ResponseDataSize
706 );
707 if (EFI_ERROR (Status) || (GetLanConfigReps->CompletionCode != IPMI_COMP_CODE_NORMAL)) {
708 DEBUG ((
709 DEBUG_ERROR,
710 " Fails to get MAC address of channel %d, CompletionCode = %02x.\n",
711 ChannelNum,
712 GetLanConfigReps->CompletionCode
713 ));
714 continue;
715 } else {
716 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " The MAC address of channel %d.\n", ChannelNum));
717 DEBUG ((
719 " %02x:%02x:%02x:%02x:%02x:%02x\n",
720 *((UINT8 *)(GetLanConfigReps + 1) + 0),
721 *((UINT8 *)(GetLanConfigReps + 1) + 1),
722 *((UINT8 *)(GetLanConfigReps + 1) + 2),
723 *((UINT8 *)(GetLanConfigReps + 1) + 3),
724 *((UINT8 *)(GetLanConfigReps + 1) + 4),
725 *((UINT8 *)(GetLanConfigReps + 1) + 5)
726 ));
727 IpmiLanMacAddressSize = sizeof (IPMI_LAN_MAC_ADDRESS);
728 CopyMem ((VOID *)&IpmiLanChannelMacAddress.Addr, (VOID *)(GetLanConfigReps + 1), IpmiLanMacAddressSize);
729 }
730 }
731 }
732
733 if (IpmiLanMacAddressSize != 0) {
734 if (!AlreadyCached) {
735 // Cache this IPMI LAN channel.
736 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Cache this IPMI LAN channel.\n"));
737 CacheIpmiLanMac ((UINT8)ChannelNum, &IpmiLanChannelMacAddress, IpmiLanMacAddressSize);
738 }
739
740 //
741 // According to design spec in Readme file under RedfishPkg.
742 // https://github.com/tianocore/edk2/tree/master/RedfishPkg#platform-with-bmc-and-the-bmc-exposed-usb-network-device
743 // Compare the first five elements of MAC address and the 6th element of MAC address.
744 // The 6th element of MAC address must be the 6th element of
745 // IPMI channel MAC address minus 1.
746 //
747 if ((IpmiLanMacAddressSize != UsbNicInfo->MacAddressSize) ||
748 (CompareMem (
749 (VOID *)UsbNicInfo->MacAddress,
750 (VOID *)&IpmiLanChannelMacAddress.Addr,
751 IpmiLanMacAddressSize - 1
752 ) != 0) ||
753 ((IpmiLanChannelMacAddress.Addr[IpmiLanMacAddressSize - 1] - 1) !=
754 *(UsbNicInfo->MacAddress + IpmiLanMacAddressSize - 1))
755 )
756 {
757 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " MAC address is not matched.\n"));
758 continue;
759 }
760
761 // This is the NIC exposed by BMC.
762 UsbNicInfo->IpmiLanChannelNumber = (UINT8)ChannelNum;
763 UsbNicInfo->IsExposedByBmc = TRUE;
764 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " MAC address is matched.\n"));
765 ExitStatus = EFI_SUCCESS;
766 break;
767 }
768 }
769
770 if (GetLanConfigReps != NULL) {
771 FreePool (GetLanConfigReps);
772 }
773
774 return ExitStatus;
775}
776
788 IN EFI_DEVICE_PATH_PROTOCOL *ThisDevicePath
789 )
790{
791 if (ThisDevicePath == NULL) {
792 return NULL;
793 }
794
795 while (TRUE) {
796 ThisDevicePath = NextDevicePathNode (ThisDevicePath);
797 if (IsDevicePathEnd (ThisDevicePath)) {
798 return NULL;
799 }
800
801 if ((ThisDevicePath->Type == MESSAGING_DEVICE_PATH) && (ThisDevicePath->SubType == MSG_USB_DP)) {
802 return ThisDevicePath;
803 }
804 }
805
806 return NULL;
807}
808
822 IN EFI_DEVICE_PATH_PROTOCOL *UsbDevicePath,
824 )
825{
826 EFI_STATUS Status;
827 UINTN BufferSize;
828 EFI_HANDLE *HandleBuffer;
829 UINT16 Length;
830 UINTN Index;
831 CHAR16 *DevicePathStr;
832 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
833 EFI_DEVICE_PATH_PROTOCOL *ThisDevicePath;
834 EFI_DEVICE_PATH_PROTOCOL *ThisDevicePathEnd;
835 EFI_DEVICE_PATH_PROTOCOL *ThisUsbDevicePath;
836 EFI_DEVICE_PATH_PROTOCOL *ThisUsbDevicePathEnd;
837
838 DEBUG ((DEBUG_MANAGEABILITY, "%a: Entry.\n", __func__));
839 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "Device path on the EFI handle which has UsbIo and SNP instaleld on it.\n"));
840 DevicePathStr = ConvertDevicePathToText (UsbDevicePath, FALSE, FALSE);
841 if (DevicePathStr != NULL) {
842 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "%s\n", DevicePathStr));
843 FreePool (DevicePathStr);
844 } else {
845 DEBUG ((DEBUG_ERROR, "Failed to convert device path.\n"));
846 return EFI_INVALID_PARAMETER;
847 }
848
849 BufferSize = 0;
850 HandleBuffer = NULL;
851 *UsbIo = NULL;
852 Status = gBS->LocateHandle (
854 &gEfiUsbIoProtocolGuid,
855 NULL,
856 &BufferSize,
857 NULL
858 );
859 if (Status == EFI_BUFFER_TOO_SMALL) {
860 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " %d UsbIo protocol instances.\n", BufferSize/sizeof (EFI_HANDLE)));
861 HandleBuffer = AllocateZeroPool (BufferSize);
862 if (HandleBuffer == NULL) {
863 DEBUG ((DEBUG_ERROR, " Falied to allocate buffer for the handles.\n"));
864 return EFI_OUT_OF_RESOURCES;
865 }
866
867 Status = gBS->LocateHandle (
869 &gEfiUsbIoProtocolGuid,
870 NULL,
871 &BufferSize,
872 HandleBuffer
873 );
874 if (EFI_ERROR (Status)) {
875 DEBUG ((DEBUG_ERROR, " Falied to locate UsbIo protocol handles.\n"));
876 FreePool (HandleBuffer);
877 return Status;
878 }
879 } else {
880 return Status;
881 }
882
883 for (Index = 0; Index < (BufferSize/sizeof (EFI_HANDLE)); Index++) {
884 Status = gBS->HandleProtocol (
885 *(HandleBuffer + Index),
886 &gEfiDevicePathProtocolGuid,
887 (VOID **)&ThisDevicePath
888 );
889 if (EFI_ERROR (Status)) {
890 continue;
891 }
892
893 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "Device path on #%d instance of UsbIo.\n", Index));
894 DevicePathStr = ConvertDevicePathToText (ThisDevicePath, FALSE, FALSE);
895 if (DevicePathStr != NULL) {
896 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "%s\n", DevicePathStr));
897 FreePool (DevicePathStr);
898 } else {
899 DEBUG ((DEBUG_ERROR, "Failed to convert device path on #%d instance of UsbIo.\n", Index));
900 continue;
901 }
902
903 Status = EFI_NOT_FOUND;
904
905 // Search for the starting MSG_USB_DP node.
906 ThisUsbDevicePath = UsbDevicePath;
907 if ((DevicePathType (ThisUsbDevicePath) != MESSAGING_DEVICE_PATH) ||
908 (DevicePathSubType (ThisUsbDevicePath) != MSG_USB_DP))
909 {
910 ThisUsbDevicePath = UsbNicGetNextMsgUsbDp (ThisUsbDevicePath);
911 if (ThisUsbDevicePath == NULL) {
912 continue;
913 }
914 }
915
916 if ((DevicePathType (ThisDevicePath) != MESSAGING_DEVICE_PATH) ||
917 (DevicePathSubType (ThisDevicePath) != MSG_USB_DP))
918 {
919 ThisDevicePath = UsbNicGetNextMsgUsbDp (ThisDevicePath);
920 if (ThisDevicePath == NULL) {
921 continue;
922 }
923 }
924
925 // Search for the ending MSG_USB_DP node.
926 ThisDevicePathEnd = ThisDevicePath;
927 ThisUsbDevicePathEnd = ThisUsbDevicePath;
928 while (TRUE) {
929 TempDevicePath = UsbNicGetNextMsgUsbDp (ThisDevicePathEnd);
930 if (TempDevicePath == NULL) {
931 break;
932 }
933
934 ThisDevicePathEnd = TempDevicePath;
935 }
936
937 while (TRUE) {
938 TempDevicePath = UsbNicGetNextMsgUsbDp (ThisUsbDevicePathEnd);
939 if (TempDevicePath == NULL) {
940 break;
941 }
942
943 ThisUsbDevicePathEnd = TempDevicePath;
944 }
945
946 // Compare these two device paths
947 Length = (UINT16)((UINTN)(UINT8 *)ThisDevicePathEnd + DevicePathNodeLength (ThisDevicePathEnd) - (UINTN)(UINT8 *)ThisDevicePath);
948 if (Length != ((UINTN)(UINT8 *)ThisUsbDevicePathEnd + DevicePathNodeLength (ThisUsbDevicePathEnd) - (UINTN)(UINT8 *)ThisUsbDevicePath)) {
949 continue;
950 }
951
952 if (CompareMem (
953 (VOID *)ThisDevicePath,
954 (VOID *)ThisUsbDevicePath,
955 Length
956 ) == 0)
957 {
958 Status = EFI_SUCCESS;
959 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "EFI handle with the correct UsbIo is found at #%d instance of UsbIo.\n", Index));
960 break;
961 }
962 }
963
964 if (Status == EFI_SUCCESS) {
965 // Locate UsbIo from this handle.
966 Status = gBS->HandleProtocol (
967 *(HandleBuffer + Index),
968 &gEfiUsbIoProtocolGuid,
969 (VOID **)UsbIo
970 );
971 return Status;
972 }
973
974 return EFI_NOT_FOUND;
975}
976
989 IN EFI_DEVICE_PATH_PROTOCOL *UsbDevicePath
990 )
991{
992 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
993
994 DevicePath = UsbDevicePath;
995 while (TRUE) {
996 DevicePath = NextDevicePathNode (DevicePath);
997 if (IsDevicePathEnd (DevicePath)) {
998 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "MAC address device path is not found on this handle.\n"));
999 break;
1000 }
1001
1002 if ((DevicePath->Type == MESSAGING_DEVICE_PATH) && (DevicePath->SubType == MSG_MAC_ADDR_DP)) {
1003 DevicePath = NextDevicePathNode (DevicePath); // Advance to next device path protocol.
1004 if (IsDevicePathEnd (DevicePath)) {
1005 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "IPv4 device path is not found on this handle.\n"));
1006 break;
1007 }
1008
1009 if ((DevicePath->Type == MESSAGING_DEVICE_PATH) && (DevicePath->SubType == MSG_IPv4_DP)) {
1010 return EFI_SUCCESS;
1011 }
1012
1013 break;
1014 }
1015 }
1016
1017 return EFI_NOT_FOUND;
1018}
1019
1035 IN EFI_HANDLE Handle,
1036 IN EFI_DEVICE_PATH_PROTOCOL *UsbDevicePath
1037 )
1038{
1039 UINTN Index;
1040 EFI_STATUS Status;
1042 EFI_USB_IO_PROTOCOL *UsbIo;
1044
1045 DEBUG ((DEBUG_MANAGEABILITY, "%a: Entry.\n", __func__));
1046 Status = gBS->HandleProtocol (
1047 Handle,
1048 &gEfiSimpleNetworkProtocolGuid,
1049 (VOID **)&Snp
1050 );
1051 if (EFI_ERROR (Status)) {
1052 DEBUG ((DEBUG_ERROR, " Failed to locate SNP.\n"));
1053 return Status;
1054 }
1055
1056 Status = UsbNicSearchUsbIo (UsbDevicePath, &UsbIo);
1057 if (EFI_ERROR (Status)) {
1058 DEBUG ((DEBUG_ERROR, " Failed to find USBIO.\n"));
1059 return Status;
1060 }
1061
1062 // Get the MAC address of this SNP instance.
1064 if (BmcUsbNic == NULL) {
1065 DEBUG ((DEBUG_ERROR, " Failed to allocate memory for HOST_INTERFACE_BMC_USB_NIC_INFO.\n"));
1066 return EFI_OUT_OF_RESOURCES;
1067 }
1068
1069 InitializeListHead (&BmcUsbNic->NextInstance);
1070 BmcUsbNic->MacAddressSize = Snp->Mode->HwAddressSize;
1071 BmcUsbNic->MacAddress = AllocatePool (BmcUsbNic->MacAddressSize);
1072 if (BmcUsbNic->MacAddress == NULL) {
1073 DEBUG ((DEBUG_ERROR, " Failed to allocate memory for HW MAC addresss.\n"));
1074 FreePool (BmcUsbNic);
1075 return EFI_OUT_OF_RESOURCES;
1076 }
1077
1078 CopyMem (
1079 (VOID *)BmcUsbNic->MacAddress,
1080 (VOID *)&Snp->Mode->CurrentAddress,
1081 BmcUsbNic->MacAddressSize
1082 );
1083 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " MAC address (in size %d) for this SNP instance:\n", BmcUsbNic->MacAddressSize));
1084 for (Index = 0; Index < BmcUsbNic->MacAddressSize; Index++) {
1085 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "%02x ", *(BmcUsbNic->MacAddress + Index)));
1086 }
1087
1089 BmcUsbNic->ThisSnp = Snp;
1090 BmcUsbNic->ThisUsbIo = UsbIo;
1091
1092 Status = HostInterfaceIpmiCheckMacAddress (BmcUsbNic);
1093 if (Status == EFI_SUCCESS) {
1094 BmcUsbNic->IsExposedByBmc = TRUE;
1095 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " BMC exposed USB NIC is found.\n"));
1096 } else {
1097 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " BMC exposed USB NIC is not found.\n"));
1098 }
1099
1100 InsertTailList (&mBmcUsbNic, &BmcUsbNic->NextInstance);
1101 return Status;
1102}
1103
1119 IN UINTN HandleNumer,
1120 IN EFI_HANDLE *HandleBuffer
1121 )
1122{
1123 UINTN Index;
1124 EFI_STATUS Status;
1125 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
1126 BOOLEAN GotBmcUsbNic;
1127 CHAR16 *DevicePathStr;
1128
1129 if ((HandleNumer == 0) || (HandleBuffer == NULL)) {
1130 return EFI_INVALID_PARAMETER;
1131 }
1132
1133 DEBUG ((DEBUG_MANAGEABILITY, "%a: Entry, #%d SNP handle\n", __func__, HandleNumer));
1134
1135 GotBmcUsbNic = FALSE;
1136 for (Index = 0; Index < HandleNumer; Index++) {
1137 DEBUG ((DEBUG_MANAGEABILITY, " Locate device path on handle 0x%08x\n", *(HandleBuffer + Index)));
1138 Status = gBS->HandleProtocol (
1139 *(HandleBuffer + Index),
1140 &gEfiDevicePathProtocolGuid,
1141 (VOID **)&DevicePath
1142 );
1143 if (EFI_ERROR (Status)) {
1144 DEBUG ((DEBUG_ERROR, " Failed to locate device path on %d handle.\n", Index));
1145 continue;
1146 }
1147
1148 DevicePathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
1149 if (DevicePathStr != NULL) {
1150 DEBUG ((DEBUG_MANAGEABILITY, " Device path: %s\n", DevicePathStr));
1151 FreePool (DevicePathStr);
1152 }
1153
1154 // Check if this is an BMC exposed USB NIC device.
1155 while (TRUE) {
1156 if ((DevicePath->Type == MESSAGING_DEVICE_PATH) && (DevicePath->SubType == MSG_USB_DP)) {
1157 Status = IdentifyNetworkMessageDevicePath (DevicePath);
1158 if (!EFI_ERROR (Status)) {
1159 Status = IdentifyUsbNicBmcChannel (*(HandleBuffer + Index), DevicePath);
1160 if (!EFI_ERROR (Status)) {
1161 GotBmcUsbNic = TRUE;
1162 }
1163 }
1164
1165 break; // Advance to next SNP handle.
1166 }
1167
1168 DevicePath = NextDevicePathNode (DevicePath);
1169 if (IsDevicePathEnd (DevicePath)) {
1170 break;
1171 }
1172 }
1173 }
1174
1175 if (GotBmcUsbNic) {
1176 return EFI_SUCCESS;
1177 }
1178
1179 DEBUG ((DEBUG_MANAGEABILITY, "No BMC USB NIC found on SNP handles\n"));
1180 return EFI_NOT_FOUND;
1181}
1182
1200 VOID *Registration
1201 )
1202{
1203 EFI_STATUS Status;
1204 EFI_HANDLE Handle;
1205 UINTN BufferSize;
1206 EFI_HANDLE *HandleBuffer;
1207
1208 DEBUG ((DEBUG_MANAGEABILITY, "%a: Entry, the registration key - 0x%08x.\n", __func__, Registration));
1209
1210 Handle = NULL;
1211 HandleBuffer = NULL;
1212 Status = EFI_SUCCESS;
1213
1214 do {
1215 BufferSize = 0;
1216 Status = gBS->LocateHandle (
1217 Registration == NULL ? ByProtocol : ByRegisterNotify,
1218 &gEfiSimpleNetworkProtocolGuid,
1219 Registration,
1220 &BufferSize,
1221 NULL
1222 );
1223 if (Status == EFI_BUFFER_TOO_SMALL) {
1224 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " %d SNP protocol instance(s).\n", BufferSize/sizeof (EFI_HANDLE)));
1225 HandleBuffer = AllocateZeroPool (BufferSize);
1226 if (HandleBuffer == NULL) {
1227 DEBUG ((DEBUG_ERROR, " Falied to allocate buffer for the handles.\n"));
1228 return EFI_OUT_OF_RESOURCES;
1229 }
1230
1231 Status = gBS->LocateHandle (
1232 Registration == NULL ? ByProtocol : ByRegisterNotify,
1233 &gEfiSimpleNetworkProtocolGuid,
1234 Registration,
1235 &BufferSize,
1236 HandleBuffer
1237 );
1238 if (EFI_ERROR (Status)) {
1239 DEBUG ((DEBUG_ERROR, " Falied to locate SNP protocol handles.\n"));
1240 FreePool (HandleBuffer);
1241 return Status;
1242 }
1243 } else if (EFI_ERROR (Status)) {
1244 if (Registration != NULL) {
1245 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " No more newly installed SNP protocol for this registration - %r.\n", Status));
1246 return EFI_SUCCESS;
1247 }
1248
1249 return Status;
1250 }
1251
1252 // Check USB NIC on handles.
1253 Status = CheckBmcUsbNicOnHandles (BufferSize/sizeof (EFI_HANDLE), HandleBuffer);
1254 if (!EFI_ERROR (Status)) {
1255 // Retrieve the rest of BMC USB NIC information for Redfish over IP information
1256 // and USB Network Interface V2.
1257 Status = RetrievedBmcUsbNicInfo ();
1258 if (!EFI_ERROR (Status)) {
1259 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Install protocol to notify the platform Redfish Host Interface information is ready.\n"));
1260 Status = gBS->InstallProtocolInterface (
1261 &Handle,
1262 &mPlatformHostInterfaceBmcUsbNicReadinessGuid,
1264 NULL
1265 );
1266 if (EFI_ERROR (Status)) {
1267 DEBUG ((DEBUG_ERROR, " Install protocol fail %r.\n", Status));
1268 }
1269 }
1270 }
1271
1272 FreePool (HandleBuffer);
1273 } while (Registration != NULL);
1274
1275 return Status;
1276}
1277
1286VOID
1287EFIAPI
1289 IN EFI_EVENT Event,
1290 IN VOID *Context
1291 )
1292{
1293 DEBUG ((DEBUG_MANAGEABILITY, "%a: Entry.\n", __func__));
1294
1295 CheckBmcUsbNic (mPlatformHostInterfaceSnpRegistration);
1296 return;
1297}
1298
1316 OUT EFI_GUID **InformationReadinessGuid
1317 )
1318{
1319 EFI_STATUS Status;
1320
1321 DEBUG ((DEBUG_MANAGEABILITY, "%a: Entry\n", __func__));
1322
1323 *InformationReadinessGuid = NULL;
1324 InitializeListHead (&mBmcUsbNic);
1325 InitializeListHead (&mBmcIpmiLan);
1326
1327 //
1328 // Check if USB NIC exposed by BMC is already
1329 // connected.
1330 //
1331 Status = CheckBmcUsbNic (NULL);
1332 if (!EFI_ERROR (Status)) {
1333 return EFI_ALREADY_STARTED;
1334 }
1335
1336 if (Status == EFI_NOT_FOUND) {
1337 DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "%a: BMC USB NIC is not found. Register the notification.\n", __func__));
1338
1339 // Register the notification of SNP installation.
1340 Status = gBS->CreateEvent (
1341 EVT_NOTIFY_SIGNAL,
1342 TPL_CALLBACK,
1344 NULL,
1345 &mPlatformHostInterfaceSnpEvent
1346 );
1347 if (EFI_ERROR (Status)) {
1348 DEBUG ((DEBUG_ERROR, "%a: Fail to create event for the installation of SNP protocol.", __func__));
1349 return Status;
1350 }
1351
1352 Status = gBS->RegisterProtocolNotify (
1353 &gEfiSimpleNetworkProtocolGuid,
1354 mPlatformHostInterfaceSnpEvent,
1355 &mPlatformHostInterfaceSnpRegistration
1356 );
1357 if (EFI_ERROR (Status)) {
1358 DEBUG ((DEBUG_ERROR, "%a: Fail to register event for the installation of SNP protocol.", __func__));
1359 return Status;
1360 }
1361
1362 *InformationReadinessGuid = &mPlatformHostInterfaceBmcUsbNicReadinessGuid;
1363 return EFI_SUCCESS;
1364 }
1365
1366 DEBUG ((DEBUG_ERROR, "%a: Something wrong when look for BMC USB NIC.\n", __func__));
1367 return Status;
1368}
UINT64 UINTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
BOOLEAN EFIAPI IsNodeAtEnd(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:481
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
RETURN_STATUS EFIAPI StrToGuid(IN CONST CHAR16 *String, OUT GUID *Guid)
Definition: SafeString.c:1500
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
UINTN EFIAPI AsciiStrSize(IN CONST CHAR8 *String)
Definition: String.c:681
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define MSG_IPv4_DP
Definition: DevicePath.h:566
#define MSG_USB_DP
Definition: DevicePath.h:418
#define MSG_MAC_ADDR_DP
Definition: DevicePath.h:550
#define MESSAGING_DEVICE_PATH
Definition: DevicePath.h:321
UINT8 EFIAPI DevicePathType(IN CONST VOID *Node)
UINTN EFIAPI DevicePathNodeLength(IN CONST VOID *Node)
UINT8 EFIAPI DevicePathSubType(IN CONST VOID *Node)
BOOLEAN EFIAPI IsDevicePathEnd(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI NextDevicePathNode(IN CONST VOID *Node)
CHAR16 *EFIAPI ConvertDevicePathToText(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN BOOLEAN DisplayOnly, IN BOOLEAN AllowShortcuts)
EDKII_REDFISH_AUTH_METHOD
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STATUS EFIAPI IpmiGetLanConfigurationParameters(IN IPMI_GET_LAN_CONFIGURATION_PARAMETERS_REQUEST *GetLanConfigurationParametersRequest, OUT IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE *GetLanConfigurationParametersResponse, IN OUT UINT32 *GetLanConfigurationParametersSize)
EFI_STATUS EFIAPI IpmiGetChannelInfo(IN IPMI_GET_CHANNEL_INFO_REQUEST *GetChannelInfoRequest, OUT IPMI_GET_CHANNEL_INFO_RESPONSE *GetChannelInfoResponse, OUT UINT32 *GetChannelInfoResponseSize)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet16(TokenName)
Definition: PcdLib.h:349
#define PcdGetPtr(TokenName)
Definition: PcdLib.h:388
EFI_STATUS HostInterfaceIpmiCheckMacAddress(IN HOST_INTERFACE_BMC_USB_NIC_INFO *UsbNicInfo)
BOOLEAN ProbeRedfishCredentialBootstrap(VOID)
EFI_STATUS IdentifyUsbNicBmcChannel(IN EFI_HANDLE Handle, IN EFI_DEVICE_PATH_PROTOCOL *UsbDevicePath)
EFI_STATUS RedfishPlatformHostInterfaceNotification(OUT EFI_GUID **InformationReadinessGuid)
EFI_STATUS RedfishPlatformHostInterfaceDeviceDescriptor(IN UINT8 *DeviceType, OUT REDFISH_INTERFACE_DATA **DeviceDescriptor)
EFI_STATUS RedfishPlatformHostInterfaceProtocolData(IN OUT MC_HOST_INTERFACE_PROTOCOL_RECORD **ProtocolRecord, IN UINT8 IndexOfProtocolData)
EFI_STATUS RetrievedBmcUsbNicInfo(VOID)
EFI_STATUS CheckCachedIpmiLanMac(IN UINT8 ChannelNum, OUT BMC_IPMI_LAN_CHANNEL_INFO **CachedIpmiLanChannel)
EFI_STATUS CheckBmcUsbNicOnHandles(IN UINTN HandleNumer, IN EFI_HANDLE *HandleBuffer)
VOID EFIAPI PlatformHostInterfaceSnpCallback(IN EFI_EVENT Event, IN VOID *Context)
EFI_DEVICE_PATH_PROTOCOL * UsbNicGetNextMsgUsbDp(IN EFI_DEVICE_PATH_PROTOCOL *ThisDevicePath)
EFI_STATUS IdentifyNetworkMessageDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *UsbDevicePath)
EFI_STATUS CheckBmcUsbNic(VOID *Registration)
EFI_STATUS UsbNicSearchUsbIo(IN EFI_DEVICE_PATH_PROTOCOL *UsbDevicePath, OUT EFI_USB_IO_PROTOCOL **UsbIo)
EFI_STATUS CacheIpmiLanMac(IN UINT8 ChannelNum, IN EFI_MAC_ADDRESS *IpmiLanChannelMacAddress, IN UINT8 IpmiLanMacAddressSize)
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
#define DEBUG_REDFISH_HOST_INTERFACE
Debug error level for Redfish Host INterface.
#define USB_INTERFACE_DEVICE_DESCRIPTOR_V2_SIZE_1_3
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
GUID EFI_GUID
Definition: UefiBaseType.h:25
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
@ EFI_NATIVE_INTERFACE
Definition: UefiSpec.h:1193
@ ByProtocol
Definition: UefiSpec.h:1518
@ ByRegisterNotify
Definition: UefiSpec.h:1513
EFI_SIMPLE_NETWORK_MODE * Mode
LIST_ENTRY NextInstance
Link to the next IPMI LAN Channel.
EFI_MAC_ADDRESS MacAddress
IPMI LAN Channel MAC address.
EFI_MAC_ADDRESS CurrentAddress
Definition: Base.h:213
UINT16 UsbProductId
USB Product ID of this BMC exposed USB NIC.
LIST_ENTRY NextInstance
Link to the next instance.
UINT8 IpAssignedType
Redfish service IP assign type.
UINT8 IpmiLanChannelNumber
BMC IPMI Lan Channel number.
UINT8 RedfishIpAddressIpv4[4]
Redfish service IP address.
UINT16 UsbVendorId
USB Vendor ID of this BMC exposed USB NIC.
Device descriptor data formated based on Device Type.
DEVICE_DESCRITOR DeviceDescriptor
The Device descriptor.
UINT8 DeviceType
The Device Type of the interface.
UINT8 MacAddress[6]
The MAC address of the PCI/PCIe network device.
UINT16 CredentialBootstrappingHandle
Credential bootstrapping handle.
UINT16 Characteristics
Additional device characteristics.
USB_INTERFACE_DEVICE_DESCRIPTOR_V2 UsbDeviceV2
Device type USB V2 device discriptor.