2 PCI/PCIe network interface instace of RedfishPlatformHostInterfaceLib
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
6 Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <Library/BaseLib.h>
14 #include <Library/BaseMemoryLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/DevicePathLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/PrintLib.h>
19 #include <Library/RedfishHostInterfaceLib.h>
20 #include <Library/UefiLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 #include <Library/UefiRuntimeServicesTableLib.h>
24 #include <Pcd/RestExServiceDevicePath.h>
25 #include <Guid/GlobalVariable.h>
27 #define VERBOSE_COLUME_SIZE (16)
29 REDFISH_OVER_IP_PROTOCOL_DATA
*mRedfishOverIpProtocolData
;
30 UINT8 mRedfishProtocolDataSize
;
33 Get the MAC address of NIC.
35 @param[out] MacAddress Pointer to retrieve MAC address
37 @retval EFI_SUCCESS MAC address is returned in MacAddress
41 GetMacAddressInformation (
42 OUT EFI_MAC_ADDRESS
*MacAddress
45 MAC_ADDR_DEVICE_PATH
*Mac
;
46 REST_EX_SERVICE_DEVICE_PATH_DATA
*RestExServiceDevicePathData
;
47 EFI_DEVICE_PATH_PROTOCOL
*RestExServiceDevicePath
;
48 MAC_ADDR_DEVICE_PATH
*MacAddressDevicePath
;
51 RestExServiceDevicePathData
= NULL
;
52 RestExServiceDevicePath
= NULL
;
54 RestExServiceDevicePathData
= (REST_EX_SERVICE_DEVICE_PATH_DATA
*)PcdGetPtr (PcdRedfishRestExServiceDevicePath
);
55 if ((RestExServiceDevicePathData
== NULL
) ||
56 (RestExServiceDevicePathData
->DevicePathNum
== 0) ||
57 !IsDevicePathValid (RestExServiceDevicePathData
->DevicePath
, 0))
62 RestExServiceDevicePath
= RestExServiceDevicePathData
->DevicePath
;
63 if (RestExServiceDevicePathData
->DevicePathMatchMode
!= DEVICE_PATH_MATCH_MAC_NODE
) {
68 // Find Mac DevicePath Node.
70 while (!IsDevicePathEnd (RestExServiceDevicePath
) &&
71 ((DevicePathType (RestExServiceDevicePath
) != MESSAGING_DEVICE_PATH
) ||
72 (DevicePathSubType (RestExServiceDevicePath
) != MSG_MAC_ADDR_DP
)))
74 RestExServiceDevicePath
= NextDevicePathNode (RestExServiceDevicePath
);
77 if (!IsDevicePathEnd (RestExServiceDevicePath
)) {
78 MacAddressDevicePath
= (MAC_ADDR_DEVICE_PATH
*)RestExServiceDevicePath
;
79 CopyMem ((VOID
*)MacAddress
, (VOID
*)&MacAddressDevicePath
->MacAddress
, sizeof (EFI_MAC_ADDRESS
));
87 Get platform Redfish host interface device descriptor.
89 @param[out] DeviceType Pointer to retrieve device type.
90 @param[out] DeviceDescriptor Pointer to retrieve REDFISH_INTERFACE_DATA, caller has to free
91 this memory using FreePool().
92 @retval EFI_SUCCESS Device descriptor is returned successfully in DeviceDescriptor.
93 @retval EFI_NOT_FOUND No Redfish host interface descriptor provided on this platform.
94 @retval Others Fail to get device descriptor.
97 RedfishPlatformHostInterfaceDeviceDescriptor (
98 OUT UINT8
*DeviceType
,
99 OUT REDFISH_INTERFACE_DATA
**DeviceDescriptor
103 EFI_MAC_ADDRESS MacAddress
;
104 REDFISH_INTERFACE_DATA
*RedfishInterfaceData
;
105 PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2
*ThisDeviceDescriptor
;
107 RedfishInterfaceData
= AllocateZeroPool (sizeof (PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2
) + 1);
108 if (RedfishInterfaceData
== NULL
) {
109 return EFI_OUT_OF_RESOURCES
;
112 RedfishInterfaceData
->DeviceType
= REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2
;
114 // Fill up device type information.
116 ThisDeviceDescriptor
= (PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2
*)((UINT8
*)RedfishInterfaceData
+ 1);
117 ThisDeviceDescriptor
->Length
= sizeof (PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2
) + 1;
118 Status
= GetMacAddressInformation (&MacAddress
);
119 if (EFI_ERROR (Status
)) {
120 FreePool (RedfishInterfaceData
);
121 return EFI_NOT_FOUND
;
124 CopyMem ((VOID
*)&ThisDeviceDescriptor
->MacAddress
, (VOID
*)&MacAddress
, sizeof (ThisDeviceDescriptor
->MacAddress
));
125 *DeviceType
= REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2
;
126 *DeviceDescriptor
= RedfishInterfaceData
;
131 Get platform Redfish host interface protocol data.
132 Caller should pass NULL in ProtocolRecord to retrive the first protocol record.
133 Then continuously pass previous ProtocolRecord for retrieving the next ProtocolRecord.
135 @param[out] ProtocolRecord Pointer to retrieve the protocol record.
136 caller has to free the new protocol record returned from
137 this function using FreePool().
138 @param[in] IndexOfProtocolData The index of protocol data.
140 @retval EFI_SUCCESS Protocol records are all returned.
141 @retval EFI_NOT_FOUND No more protocol records.
142 @retval Others Fail to get protocol records.
145 RedfishPlatformHostInterfaceProtocolData (
146 OUT MC_HOST_INTERFACE_PROTOCOL_RECORD
**ProtocolRecord
,
147 IN UINT8 IndexOfProtocolData
150 MC_HOST_INTERFACE_PROTOCOL_RECORD
*ThisProtocolRecord
;
152 if (mRedfishOverIpProtocolData
== 0) {
153 return EFI_NOT_FOUND
;
156 if (IndexOfProtocolData
== 0) {
158 // Return the first Redfish protocol data to caller. We only have
159 // one protocol data in this case.
161 ThisProtocolRecord
= (MC_HOST_INTERFACE_PROTOCOL_RECORD
*)AllocatePool (mRedfishProtocolDataSize
+ sizeof (MC_HOST_INTERFACE_PROTOCOL_RECORD
) - 1);
162 ThisProtocolRecord
->ProtocolType
= MCHostInterfaceProtocolTypeRedfishOverIP
;
163 ThisProtocolRecord
->ProtocolTypeDataLen
= mRedfishProtocolDataSize
;
164 CopyMem ((VOID
*)&ThisProtocolRecord
->ProtocolTypeData
, (VOID
*)mRedfishOverIpProtocolData
, mRedfishProtocolDataSize
);
165 *ProtocolRecord
= ThisProtocolRecord
;
169 return EFI_NOT_FOUND
;
175 @param[in] Ip IPv4 address
178 InternalDumpIp4Addr (
179 IN EFI_IPv4_ADDRESS
*Ip
184 for (Index
= 0; Index
< 4; Index
++) {
185 DEBUG ((DEBUG_VERBOSE
, "%d", Ip
->Addr
[Index
]));
187 DEBUG ((DEBUG_VERBOSE
, "."));
191 DEBUG ((DEBUG_VERBOSE
, "\n"));
197 @param[in] Ip IPv6 address
200 InternalDumpIp6Addr (
201 IN EFI_IPv6_ADDRESS
*Ip
206 for (Index
= 0; Index
< 16; Index
++) {
207 if (Ip
->Addr
[Index
] != 0) {
208 DEBUG ((DEBUG_VERBOSE
, "%x", Ip
->Addr
[Index
]));
217 if (((Ip
->Addr
[Index
] & 0xf0) == 0) && (Ip
->Addr
[Index
- 1] != 0)) {
218 DEBUG ((DEBUG_VERBOSE
, "0"));
221 DEBUG ((DEBUG_VERBOSE
, "%x", Ip
->Addr
[Index
]));
224 DEBUG ((DEBUG_VERBOSE
, ":"));
228 DEBUG ((DEBUG_VERBOSE
, "\n"));
234 @param[in] Data Pointer to data.
235 @param[in] Size size of data to dump.
245 for (Index
= 0; Index
< Size
; Index
++) {
246 DEBUG ((DEBUG_VERBOSE
, "%02x ", (UINTN
)Data
[Index
]));
253 @param[in] Data Pointer to hex data.
254 @param[in] Size size of hex data to dump.
266 Count
= Size
/ VERBOSE_COLUME_SIZE
;
267 Left
= Size
% VERBOSE_COLUME_SIZE
;
268 for (Index
= 0; Index
< Count
; Index
++) {
269 InternalDumpData (Data
+ Index
* VERBOSE_COLUME_SIZE
, VERBOSE_COLUME_SIZE
);
270 DEBUG ((DEBUG_VERBOSE
, "\n"));
274 InternalDumpData (Data
+ Index
* VERBOSE_COLUME_SIZE
, Left
);
275 DEBUG ((DEBUG_VERBOSE
, "\n"));
278 DEBUG ((DEBUG_VERBOSE
, "\n"));
282 Dump Redfish over IP protocol data
284 @param[in] RedfishProtocolData Pointer to REDFISH_OVER_IP_PROTOCOL_DATA
285 @param[in] RedfishProtocolDataSize size of data to dump.
288 DumpRedfishIpProtocolData (
289 IN REDFISH_OVER_IP_PROTOCOL_DATA
*RedfishProtocolData
,
290 IN UINT8 RedfishProtocolDataSize
295 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData: \n"));
296 InternalDumpHex ((UINT8
*)RedfishProtocolData
, RedfishProtocolDataSize
);
298 DEBUG ((DEBUG_VERBOSE
, "Parsing as below: \n"));
300 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->ServiceUuid - %g\n", &(RedfishProtocolData
->ServiceUuid
)));
302 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->HostIpAssignmentType - %d\n", RedfishProtocolData
->HostIpAssignmentType
));
304 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->HostIpAddressFormat - %d\n", RedfishProtocolData
->HostIpAddressFormat
));
306 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->HostIpAddress: \n"));
307 if (RedfishProtocolData
->HostIpAddressFormat
== 0x01) {
308 InternalDumpIp4Addr ((EFI_IPv4_ADDRESS
*)(RedfishProtocolData
->HostIpAddress
));
310 InternalDumpIp6Addr ((EFI_IPv6_ADDRESS
*)(RedfishProtocolData
->HostIpAddress
));
313 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->HostIpMask: \n"));
314 if (RedfishProtocolData
->HostIpAddressFormat
== 0x01) {
315 InternalDumpIp4Addr ((EFI_IPv4_ADDRESS
*)(RedfishProtocolData
->HostIpMask
));
317 InternalDumpIp6Addr ((EFI_IPv6_ADDRESS
*)(RedfishProtocolData
->HostIpMask
));
320 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceIpDiscoveryType - %d\n", RedfishProtocolData
->RedfishServiceIpDiscoveryType
));
322 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceIpAddressFormat - %d\n", RedfishProtocolData
->RedfishServiceIpAddressFormat
));
324 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceIpAddress: \n"));
325 if (RedfishProtocolData
->RedfishServiceIpAddressFormat
== 0x01) {
326 InternalDumpIp4Addr ((EFI_IPv4_ADDRESS
*)(RedfishProtocolData
->RedfishServiceIpAddress
));
328 InternalDumpIp6Addr ((EFI_IPv6_ADDRESS
*)(RedfishProtocolData
->RedfishServiceIpAddress
));
331 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceIpMask: \n"));
332 if (RedfishProtocolData
->RedfishServiceIpAddressFormat
== 0x01) {
333 InternalDumpIp4Addr ((EFI_IPv4_ADDRESS
*)(RedfishProtocolData
->RedfishServiceIpMask
));
335 InternalDumpIp6Addr ((EFI_IPv6_ADDRESS
*)(RedfishProtocolData
->RedfishServiceIpMask
));
338 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceIpPort - %d\n", RedfishProtocolData
->RedfishServiceIpPort
));
340 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceVlanId - %d\n", RedfishProtocolData
->RedfishServiceVlanId
));
342 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceHostnameLength - %d\n", RedfishProtocolData
->RedfishServiceHostnameLength
));
344 AsciiStrToUnicodeStrS ((CHAR8
*)RedfishProtocolData
->RedfishServiceHostname
, Hostname
, sizeof (Hostname
) / sizeof (Hostname
[0]));
345 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceHostname - %s\n", Hostname
));
349 Get Redfish host interface protocol data from variale.
351 @param[out] RedfishProtocolData Pointer to retrieve REDFISH_OVER_IP_PROTOCOL_DATA.
352 @param[out] RedfishProtocolDataSize Size of REDFISH_OVER_IP_PROTOCOL_DATA.
354 @retval EFI_SUCESS REDFISH_OVER_IP_PROTOCOL_DATA is returned successfully.
357 GetRedfishRecordFromVariable (
358 OUT REDFISH_OVER_IP_PROTOCOL_DATA
**RedfishProtocolData
,
359 OUT UINT8
*RedfishProtocolDataSize
363 UINT8 HostIpAssignmentType
;
364 UINTN HostIpAssignmentTypeSize
;
365 EFI_IPv4_ADDRESS HostIpAddress
;
367 EFI_IPv4_ADDRESS HostIpMask
;
368 EFI_IPv4_ADDRESS RedfishServiceIpAddress
;
369 EFI_IPv4_ADDRESS RedfishServiceIpMask
;
370 UINT16 RedfishServiceIpPort
;
371 UINTN IpPortDataSize
;
373 CHAR8 RedfishHostName
[20];
375 if ((RedfishProtocolData
== NULL
) || (RedfishProtocolDataSize
== NULL
)) {
376 return EFI_INVALID_PARAMETER
;
380 // 1. Retrieve Address Information from variable.
382 Status
= gRT
->GetVariable (
383 L
"HostIpAssignmentType",
384 &gEmuRedfishServiceGuid
,
386 &HostIpAssignmentTypeSize
,
387 &HostIpAssignmentType
389 if (EFI_ERROR (Status
)) {
390 DEBUG ((DEBUG_ERROR
, "RedfishPlatformDxe: GetVariable HostIpAssignmentType - %r\n", Status
));
394 IPv4DataSize
= sizeof (EFI_IPv4_ADDRESS
);
395 if (HostIpAssignmentType
== 1 ) {
396 Status
= gRT
->GetVariable (
398 &gEmuRedfishServiceGuid
,
403 if (EFI_ERROR (Status
)) {
404 DEBUG ((DEBUG_ERROR
, "RedfishPlatformDxe: GetVariable HostIpAddress - %r\n", Status
));
408 Status
= gRT
->GetVariable (
410 &gEmuRedfishServiceGuid
,
415 if (EFI_ERROR (Status
)) {
416 DEBUG ((DEBUG_ERROR
, "RedfishPlatformDxe: GetVariable HostIpMask - %r\n", Status
));
421 Status
= gRT
->GetVariable (
422 L
"RedfishServiceIpAddress",
423 &gEmuRedfishServiceGuid
,
426 &RedfishServiceIpAddress
428 if (EFI_ERROR (Status
)) {
429 DEBUG ((DEBUG_ERROR
, "RedfishPlatformDxe: GetVariable RedfishServiceIpAddress - %r\n", Status
));
433 Status
= gRT
->GetVariable (
434 L
"RedfishServiceIpMask",
435 &gEmuRedfishServiceGuid
,
438 &RedfishServiceIpMask
440 if (EFI_ERROR (Status
)) {
441 DEBUG ((DEBUG_ERROR
, "RedfishPlatformDxe: GetVariable RedfishServiceIpMask - %r\n", Status
));
445 Status
= gRT
->GetVariable (
446 L
"RedfishServiceIpPort",
447 &gEmuRedfishServiceGuid
,
450 &RedfishServiceIpPort
452 if (EFI_ERROR (Status
)) {
453 DEBUG ((DEBUG_ERROR
, "RedfishPlatformDxe: GetVariable RedfishServiceIpPort - %r\n", Status
));
459 sizeof (RedfishHostName
),
461 RedfishServiceIpAddress
.Addr
[0],
462 RedfishServiceIpAddress
.Addr
[1],
463 RedfishServiceIpAddress
.Addr
[2],
464 RedfishServiceIpAddress
.Addr
[3]
467 HostNameSize
= (UINT8
)AsciiStrLen (RedfishHostName
) + 1;
470 // 2. Protocol Data Size.
472 *RedfishProtocolDataSize
= sizeof (REDFISH_OVER_IP_PROTOCOL_DATA
) - 1 + HostNameSize
;
477 *RedfishProtocolData
= (REDFISH_OVER_IP_PROTOCOL_DATA
*)AllocateZeroPool (*RedfishProtocolDataSize
);
478 if (*RedfishProtocolData
== NULL
) {
479 return EFI_OUT_OF_RESOURCES
;
482 CopyGuid (&(*RedfishProtocolData
)->ServiceUuid
, &gEmuRedfishServiceGuid
);
484 (*RedfishProtocolData
)->HostIpAssignmentType
= HostIpAssignmentType
;
485 (*RedfishProtocolData
)->HostIpAddressFormat
= 1; // Only support IPv4
487 if (HostIpAssignmentType
== 1 ) {
488 (*RedfishProtocolData
)->HostIpAddress
[0] = HostIpAddress
.Addr
[0];
489 (*RedfishProtocolData
)->HostIpAddress
[1] = HostIpAddress
.Addr
[1];
490 (*RedfishProtocolData
)->HostIpAddress
[2] = HostIpAddress
.Addr
[2];
491 (*RedfishProtocolData
)->HostIpAddress
[3] = HostIpAddress
.Addr
[3];
493 (*RedfishProtocolData
)->HostIpMask
[0] = HostIpMask
.Addr
[0];
494 (*RedfishProtocolData
)->HostIpMask
[1] = HostIpMask
.Addr
[1];
495 (*RedfishProtocolData
)->HostIpMask
[2] = HostIpMask
.Addr
[2];
496 (*RedfishProtocolData
)->HostIpMask
[3] = HostIpMask
.Addr
[3];
499 (*RedfishProtocolData
)->RedfishServiceIpDiscoveryType
= 1; // Use static IP address
500 (*RedfishProtocolData
)->RedfishServiceIpAddressFormat
= 1; // Only support IPv4
502 (*RedfishProtocolData
)->RedfishServiceIpAddress
[0] = RedfishServiceIpAddress
.Addr
[0];
503 (*RedfishProtocolData
)->RedfishServiceIpAddress
[1] = RedfishServiceIpAddress
.Addr
[1];
504 (*RedfishProtocolData
)->RedfishServiceIpAddress
[2] = RedfishServiceIpAddress
.Addr
[2];
505 (*RedfishProtocolData
)->RedfishServiceIpAddress
[3] = RedfishServiceIpAddress
.Addr
[3];
507 (*RedfishProtocolData
)->RedfishServiceIpMask
[0] = RedfishServiceIpMask
.Addr
[0];
508 (*RedfishProtocolData
)->RedfishServiceIpMask
[1] = RedfishServiceIpMask
.Addr
[1];
509 (*RedfishProtocolData
)->RedfishServiceIpMask
[2] = RedfishServiceIpMask
.Addr
[2];
510 (*RedfishProtocolData
)->RedfishServiceIpMask
[3] = RedfishServiceIpMask
.Addr
[3];
512 (*RedfishProtocolData
)->RedfishServiceIpPort
= RedfishServiceIpPort
;
513 (*RedfishProtocolData
)->RedfishServiceVlanId
= 0xffffffff;
515 (*RedfishProtocolData
)->RedfishServiceHostnameLength
= HostNameSize
;
516 AsciiStrCpyS ((CHAR8
*)((*RedfishProtocolData
)->RedfishServiceHostname
), HostNameSize
, RedfishHostName
);
522 Construct Redfish host interface protocol data.
524 @param ImageHandle The image handle.
525 @param SystemTable The system table.
527 @retval EFI_SUCEESS Install Boot manager menu success.
528 @retval Other Return error status.
533 RedfishPlatformHostInterfaceConstructor (
534 IN EFI_HANDLE ImageHandle
,
535 IN EFI_SYSTEM_TABLE
*SystemTable
540 Status
= GetRedfishRecordFromVariable (&mRedfishOverIpProtocolData
, &mRedfishProtocolDataSize
);
541 DEBUG ((DEBUG_INFO
, "%a: GetRedfishRecordFromVariable() - %r\n", __FUNCTION__
, Status
));
542 if (!EFI_ERROR (Status
)) {
543 DumpRedfishIpProtocolData (mRedfishOverIpProtocolData
, mRedfishProtocolDataSize
);
550 Get the EFI protocol GUID installed by platform library which
551 indicates the necessary information is ready for building
554 @param[out] InformationReadinessGuid Pointer to retrive the protocol
557 @retval EFI_SUCCESS Notification is required for building up
558 SMBIOS type 42h record.
559 @retval EFI_UNSUPPORTED Notification is not required for building up
560 SMBIOS type 42h record.
561 @retval EFI_ALREADY_STARTED Platform host information is already ready.
562 @retval Others Other errors.
565 RedfishPlatformHostInterfaceNotification (
566 OUT EFI_GUID
**InformationReadinessGuid
569 return EFI_UNSUPPORTED
;