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>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Library/BaseLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/DevicePathLib.h>
16 #include <Library/MemoryAllocationLib.h>
17 #include <Library/PrintLib.h>
18 #include <Library/RedfishHostInterfaceLib.h>
19 #include <Library/UefiLib.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/UefiRuntimeServicesTableLib.h>
23 #include <Pcd/RestExServiceDevicePath.h>
24 #include <Guid/GlobalVariable.h>
26 #define VERBOSE_COLUME_SIZE (16)
28 REDFISH_OVER_IP_PROTOCOL_DATA
*mRedfishOverIpProtocolData
;
29 UINT8 mRedfishProtocolDataSize
;
32 Get the MAC address of NIC.
34 @param[out] MacAddress Pointer to retrieve MAC address
36 @retval EFI_SUCCESS MAC address is returned in MacAddress
40 GetMacAddressInformation (
41 OUT EFI_MAC_ADDRESS
*MacAddress
44 MAC_ADDR_DEVICE_PATH
*Mac
;
45 REST_EX_SERVICE_DEVICE_PATH_DATA
*RestExServiceDevicePathData
;
46 EFI_DEVICE_PATH_PROTOCOL
*RestExServiceDevicePath
;
47 MAC_ADDR_DEVICE_PATH
*MacAddressDevicePath
;
50 RestExServiceDevicePathData
= NULL
;
51 RestExServiceDevicePath
= NULL
;
53 RestExServiceDevicePathData
= (REST_EX_SERVICE_DEVICE_PATH_DATA
*)PcdGetPtr(PcdRedfishRestExServiceDevicePath
);
54 if (RestExServiceDevicePathData
== NULL
||
55 RestExServiceDevicePathData
->DevicePathNum
== 0 ||
56 !IsDevicePathValid (RestExServiceDevicePathData
->DevicePath
, 0)) {
60 RestExServiceDevicePath
= RestExServiceDevicePathData
->DevicePath
;
61 if (RestExServiceDevicePathData
->DevicePathMatchMode
!= DEVICE_PATH_MATCH_MAC_NODE
) {
66 // Find Mac DevicePath Node.
68 while (!IsDevicePathEnd (RestExServiceDevicePath
) &&
69 ((DevicePathType (RestExServiceDevicePath
) != MESSAGING_DEVICE_PATH
) ||
70 (DevicePathSubType (RestExServiceDevicePath
) != MSG_MAC_ADDR_DP
))) {
71 RestExServiceDevicePath
= NextDevicePathNode (RestExServiceDevicePath
);
74 if (!IsDevicePathEnd (RestExServiceDevicePath
)) {
75 MacAddressDevicePath
= (MAC_ADDR_DEVICE_PATH
*)RestExServiceDevicePath
;
76 CopyMem ((VOID
*)MacAddress
, (VOID
*)&MacAddressDevicePath
->MacAddress
, sizeof (EFI_MAC_ADDRESS
));
83 Get platform Redfish host interface device descriptor.
85 @param[out] DeviceType Pointer to retrieve device type.
86 @param[out] DeviceDescriptor Pointer to retrieve REDFISH_INTERFACE_DATA, caller has to free
87 this memory using FreePool().
88 @retval EFI_SUCCESS Device descriptor is returned successfully in DeviceDescriptor.
89 @retval EFI_NOT_FOUND No Redfish host interface descriptor provided on this platform.
90 @retval Others Fail to get device descriptor.
93 RedfishPlatformHostInterfaceDeviceDescriptor (
94 OUT UINT8
*DeviceType
,
95 OUT REDFISH_INTERFACE_DATA
**DeviceDescriptor
99 EFI_MAC_ADDRESS MacAddress
;
100 REDFISH_INTERFACE_DATA
*RedfishInterfaceData
;
101 PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2
*ThisDeviceDescriptor
;
103 RedfishInterfaceData
= AllocateZeroPool (sizeof (PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2
) + 1);
104 if (RedfishInterfaceData
== NULL
) {
105 return EFI_OUT_OF_RESOURCES
;
107 RedfishInterfaceData
->DeviceType
= REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2
;
109 // Fill up device type information.
111 ThisDeviceDescriptor
= (PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2
*)((UINT8
*)RedfishInterfaceData
+ 1);
112 ThisDeviceDescriptor
->Length
= sizeof (PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2
) + 1;
113 Status
= GetMacAddressInformation (&MacAddress
);
114 if (EFI_ERROR (Status
)) {
115 FreePool (RedfishInterfaceData
);
116 return EFI_NOT_FOUND
;
118 CopyMem ((VOID
*)&ThisDeviceDescriptor
->MacAddress
, (VOID
*)&MacAddress
, sizeof (ThisDeviceDescriptor
->MacAddress
));
119 *DeviceType
= REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2
;
120 *DeviceDescriptor
= RedfishInterfaceData
;
124 Get platform Redfish host interface protocol data.
125 Caller should pass NULL in ProtocolRecord to retrive the first protocol record.
126 Then continuously pass previous ProtocolRecord for retrieving the next ProtocolRecord.
128 @param[out] ProtocolRecord Pointer to retrieve the protocol record.
129 caller has to free the new protocol record returned from
130 this function using FreePool().
131 @param[in] IndexOfProtocolData The index of protocol data.
133 @retval EFI_SUCCESS Protocol records are all returned.
134 @retval EFI_NOT_FOUND No more protocol records.
135 @retval Others Fail to get protocol records.
138 RedfishPlatformHostInterfaceProtocolData (
139 OUT MC_HOST_INTERFACE_PROTOCOL_RECORD
**ProtocolRecord
,
140 IN UINT8 IndexOfProtocolData
143 MC_HOST_INTERFACE_PROTOCOL_RECORD
*ThisProtocolRecord
;
145 if (mRedfishOverIpProtocolData
== 0) {
146 return EFI_NOT_FOUND
;
148 if (IndexOfProtocolData
== 0) {
150 // Return the first Redfish protocol data to caller. We only have
151 // one protocol data in this case.
153 ThisProtocolRecord
= (MC_HOST_INTERFACE_PROTOCOL_RECORD
*) AllocatePool (mRedfishProtocolDataSize
+ sizeof (MC_HOST_INTERFACE_PROTOCOL_RECORD
) - 1);
154 ThisProtocolRecord
->ProtocolType
= MCHostInterfaceProtocolTypeRedfishOverIP
;
155 ThisProtocolRecord
->ProtocolTypeDataLen
= mRedfishProtocolDataSize
;
156 CopyMem ((VOID
*)&ThisProtocolRecord
->ProtocolTypeData
, (VOID
*)mRedfishOverIpProtocolData
, mRedfishProtocolDataSize
);
157 *ProtocolRecord
= ThisProtocolRecord
;
160 return EFI_NOT_FOUND
;
165 @param[in] Ip IPv4 address
168 InternalDumpIp4Addr (
169 IN EFI_IPv4_ADDRESS
*Ip
174 for (Index
= 0; Index
< 4; Index
++) {
175 DEBUG ((DEBUG_VERBOSE
, "%d", Ip
->Addr
[Index
]));
177 DEBUG ((DEBUG_VERBOSE
, "."));
181 DEBUG ((DEBUG_VERBOSE
, "\n"));
186 @param[in] Ip IPv6 address
189 InternalDumpIp6Addr (
190 IN EFI_IPv6_ADDRESS
*Ip
195 for (Index
= 0; Index
< 16; Index
++) {
196 if (Ip
->Addr
[Index
] != 0) {
197 DEBUG ((DEBUG_VERBOSE
, "%x", Ip
->Addr
[Index
]));
205 if (((Ip
->Addr
[Index
] & 0xf0) == 0) && (Ip
->Addr
[Index
- 1] != 0)) {
206 DEBUG ((DEBUG_VERBOSE
, "0"));
208 DEBUG ((DEBUG_VERBOSE
, "%x", Ip
->Addr
[Index
]));
211 DEBUG ((DEBUG_VERBOSE
, ":"));
214 DEBUG ((DEBUG_VERBOSE
, "\n"));
219 @param[in] Data Pointer to data.
220 @param[in] Size size of data to dump.
229 for (Index
= 0; Index
< Size
; Index
++) {
230 DEBUG ((DEBUG_VERBOSE
, "%02x ", (UINTN
)Data
[Index
]));
236 @param[in] Data Pointer to hex data.
237 @param[in] Size size of hex data to dump.
249 Count
= Size
/ VERBOSE_COLUME_SIZE
;
250 Left
= Size
% VERBOSE_COLUME_SIZE
;
251 for (Index
= 0; Index
< Count
; Index
++) {
252 InternalDumpData (Data
+ Index
* VERBOSE_COLUME_SIZE
, VERBOSE_COLUME_SIZE
);
253 DEBUG ((DEBUG_VERBOSE
, "\n"));
257 InternalDumpData (Data
+ Index
* VERBOSE_COLUME_SIZE
, Left
);
258 DEBUG ((DEBUG_VERBOSE
, "\n"));
261 DEBUG ((DEBUG_VERBOSE
, "\n"));
264 Dump Redfish over IP protocol data
266 @param[in] RedfishProtocolData Pointer to REDFISH_OVER_IP_PROTOCOL_DATA
267 @param[in] RedfishProtocolDataSize size of data to dump.
270 DumpRedfishIpProtocolData (
271 IN REDFISH_OVER_IP_PROTOCOL_DATA
*RedfishProtocolData
,
272 IN UINT8 RedfishProtocolDataSize
277 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData: \n"));
278 InternalDumpHex ((UINT8
*) RedfishProtocolData
, RedfishProtocolDataSize
);
280 DEBUG ((DEBUG_VERBOSE
, "Parsing as below: \n"));
282 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->ServiceUuid - %g\n", &(RedfishProtocolData
->ServiceUuid
)));
284 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->HostIpAssignmentType - %d\n", RedfishProtocolData
->HostIpAssignmentType
));
286 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->HostIpAddressFormat - %d\n", RedfishProtocolData
->HostIpAddressFormat
));
288 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->HostIpAddress: \n"));
289 if (RedfishProtocolData
->HostIpAddressFormat
== 0x01) {
290 InternalDumpIp4Addr ((EFI_IPv4_ADDRESS
*) (RedfishProtocolData
->HostIpAddress
));
292 InternalDumpIp6Addr ((EFI_IPv6_ADDRESS
*) (RedfishProtocolData
->HostIpAddress
));
295 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->HostIpMask: \n"));
296 if (RedfishProtocolData
->HostIpAddressFormat
== 0x01) {
297 InternalDumpIp4Addr ((EFI_IPv4_ADDRESS
*) (RedfishProtocolData
->HostIpMask
));
299 InternalDumpIp6Addr ((EFI_IPv6_ADDRESS
*) (RedfishProtocolData
->HostIpMask
));
302 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceIpDiscoveryType - %d\n", RedfishProtocolData
->RedfishServiceIpDiscoveryType
));
304 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceIpAddressFormat - %d\n", RedfishProtocolData
->RedfishServiceIpAddressFormat
));
306 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceIpAddress: \n"));
307 if (RedfishProtocolData
->RedfishServiceIpAddressFormat
== 0x01) {
308 InternalDumpIp4Addr ((EFI_IPv4_ADDRESS
*) (RedfishProtocolData
->RedfishServiceIpAddress
));
310 InternalDumpIp6Addr ((EFI_IPv6_ADDRESS
*) (RedfishProtocolData
->RedfishServiceIpAddress
));
313 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceIpMask: \n"));
314 if (RedfishProtocolData
->RedfishServiceIpAddressFormat
== 0x01) {
315 InternalDumpIp4Addr ((EFI_IPv4_ADDRESS
*) (RedfishProtocolData
->RedfishServiceIpMask
));
317 InternalDumpIp6Addr ((EFI_IPv6_ADDRESS
*) (RedfishProtocolData
->RedfishServiceIpMask
));
320 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceIpPort - %d\n", RedfishProtocolData
->RedfishServiceIpPort
));
322 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceVlanId - %d\n", RedfishProtocolData
->RedfishServiceVlanId
));
324 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceHostnameLength - %d\n", RedfishProtocolData
->RedfishServiceHostnameLength
));
326 AsciiStrToUnicodeStrS((CHAR8
*) RedfishProtocolData
->RedfishServiceHostname
, Hostname
, sizeof (Hostname
) / sizeof (Hostname
[0]));
327 DEBUG ((DEBUG_VERBOSE
, "RedfishProtocolData->RedfishServiceHostname - %s\n", Hostname
));
331 Get Redfish host interface protocol data from variale.
333 @param[out] RedfishProtocolData Pointer to retrieve REDFISH_OVER_IP_PROTOCOL_DATA.
334 @param[out] RedfishProtocolDataSize Size of REDFISH_OVER_IP_PROTOCOL_DATA.
336 @retval EFI_SUCESS REDFISH_OVER_IP_PROTOCOL_DATA is returned successfully.
339 GetRedfishRecordFromVariable (
340 OUT REDFISH_OVER_IP_PROTOCOL_DATA
**RedfishProtocolData
,
341 OUT UINT8
*RedfishProtocolDataSize
345 UINT8 HostIpAssignmentType
;
346 UINTN HostIpAssignmentTypeSize
;
347 EFI_IPv4_ADDRESS HostIpAddress
;
349 EFI_IPv4_ADDRESS HostIpMask
;
350 EFI_IPv4_ADDRESS RedfishServiceIpAddress
;
351 EFI_IPv4_ADDRESS RedfishServiceIpMask
;
352 UINT16 RedfishServiceIpPort
;
353 UINTN IpPortDataSize
;
355 CHAR8 RedfishHostName
[20];
357 if (RedfishProtocolData
== NULL
|| RedfishProtocolDataSize
== NULL
) {
358 return EFI_INVALID_PARAMETER
;
362 // 1. Retrieve Address Information from variable.
364 Status
= gRT
->GetVariable (
365 L
"HostIpAssignmentType",
366 &gEmuRedfishServiceGuid
,
368 &HostIpAssignmentTypeSize
,
369 &HostIpAssignmentType
371 if (EFI_ERROR (Status
)) {
372 DEBUG ((DEBUG_ERROR
, "RedfishPlatformDxe: GetVariable HostIpAssignmentType - %r\n", Status
));
376 IPv4DataSize
= sizeof (EFI_IPv4_ADDRESS
);
377 if (HostIpAssignmentType
== 1 ) {
378 Status
= gRT
->GetVariable (
380 &gEmuRedfishServiceGuid
,
385 if (EFI_ERROR (Status
)) {
386 DEBUG ((DEBUG_ERROR
, "RedfishPlatformDxe: GetVariable HostIpAddress - %r\n", Status
));
390 Status
= gRT
->GetVariable (
392 &gEmuRedfishServiceGuid
,
397 if (EFI_ERROR (Status
)) {
398 DEBUG ((DEBUG_ERROR
, "RedfishPlatformDxe: GetVariable HostIpMask - %r\n", Status
));
403 Status
= gRT
->GetVariable (
404 L
"RedfishServiceIpAddress",
405 &gEmuRedfishServiceGuid
,
408 &RedfishServiceIpAddress
410 if (EFI_ERROR (Status
)) {
411 DEBUG ((DEBUG_ERROR
, "RedfishPlatformDxe: GetVariable RedfishServiceIpAddress - %r\n", Status
));
415 Status
= gRT
->GetVariable (
416 L
"RedfishServiceIpMask",
417 &gEmuRedfishServiceGuid
,
420 &RedfishServiceIpMask
422 if (EFI_ERROR (Status
)) {
423 DEBUG ((DEBUG_ERROR
, "RedfishPlatformDxe: GetVariable RedfishServiceIpMask - %r\n", Status
));
427 Status
= gRT
->GetVariable (
428 L
"RedfishServiceIpPort",
429 &gEmuRedfishServiceGuid
,
432 &RedfishServiceIpPort
434 if (EFI_ERROR (Status
)) {
435 DEBUG ((DEBUG_ERROR
, "RedfishPlatformDxe: GetVariable RedfishServiceIpPort - %r\n", Status
));
441 sizeof (RedfishHostName
),
443 RedfishServiceIpAddress
.Addr
[0],
444 RedfishServiceIpAddress
.Addr
[1],
445 RedfishServiceIpAddress
.Addr
[2],
446 RedfishServiceIpAddress
.Addr
[3]
449 HostNameSize
= (UINT8
) AsciiStrLen (RedfishHostName
) + 1;
452 // 2. Protocol Data Size.
454 *RedfishProtocolDataSize
= sizeof (REDFISH_OVER_IP_PROTOCOL_DATA
) - 1 + HostNameSize
;
459 *RedfishProtocolData
= (REDFISH_OVER_IP_PROTOCOL_DATA
*) AllocateZeroPool (*RedfishProtocolDataSize
);
460 if (*RedfishProtocolData
== NULL
) {
461 return EFI_OUT_OF_RESOURCES
;
464 CopyGuid (&(*RedfishProtocolData
)->ServiceUuid
, &gEmuRedfishServiceGuid
);
466 (*RedfishProtocolData
)->HostIpAssignmentType
= HostIpAssignmentType
;
467 (*RedfishProtocolData
)->HostIpAddressFormat
= 1; // Only support IPv4
469 if (HostIpAssignmentType
== 1 ) {
470 (*RedfishProtocolData
)->HostIpAddress
[0] = HostIpAddress
.Addr
[0];
471 (*RedfishProtocolData
)->HostIpAddress
[1] = HostIpAddress
.Addr
[1];
472 (*RedfishProtocolData
)->HostIpAddress
[2] = HostIpAddress
.Addr
[2];
473 (*RedfishProtocolData
)->HostIpAddress
[3] = HostIpAddress
.Addr
[3];
475 (*RedfishProtocolData
)->HostIpMask
[0] = HostIpMask
.Addr
[0];
476 (*RedfishProtocolData
)->HostIpMask
[1] = HostIpMask
.Addr
[1];
477 (*RedfishProtocolData
)->HostIpMask
[2] = HostIpMask
.Addr
[2];
478 (*RedfishProtocolData
)->HostIpMask
[3] = HostIpMask
.Addr
[3];
481 (*RedfishProtocolData
)->RedfishServiceIpDiscoveryType
= 1; // Use static IP address
482 (*RedfishProtocolData
)->RedfishServiceIpAddressFormat
= 1; // Only support IPv4
484 (*RedfishProtocolData
)->RedfishServiceIpAddress
[0] = RedfishServiceIpAddress
.Addr
[0];
485 (*RedfishProtocolData
)->RedfishServiceIpAddress
[1] = RedfishServiceIpAddress
.Addr
[1];
486 (*RedfishProtocolData
)->RedfishServiceIpAddress
[2] = RedfishServiceIpAddress
.Addr
[2];
487 (*RedfishProtocolData
)->RedfishServiceIpAddress
[3] = RedfishServiceIpAddress
.Addr
[3];
489 (*RedfishProtocolData
)->RedfishServiceIpMask
[0] = RedfishServiceIpMask
.Addr
[0];
490 (*RedfishProtocolData
)->RedfishServiceIpMask
[1] = RedfishServiceIpMask
.Addr
[1];
491 (*RedfishProtocolData
)->RedfishServiceIpMask
[2] = RedfishServiceIpMask
.Addr
[2];
492 (*RedfishProtocolData
)->RedfishServiceIpMask
[3] = RedfishServiceIpMask
.Addr
[3];
494 (*RedfishProtocolData
)->RedfishServiceIpPort
= RedfishServiceIpPort
;
495 (*RedfishProtocolData
)->RedfishServiceVlanId
= 0xffffffff;
497 (*RedfishProtocolData
)->RedfishServiceHostnameLength
= HostNameSize
;
498 AsciiStrCpyS ((CHAR8
*) ((*RedfishProtocolData
)->RedfishServiceHostname
), HostNameSize
, RedfishHostName
);
504 Construct Redfish host interface protocol data.
506 @param ImageHandle The image handle.
507 @param SystemTable The system table.
509 @retval EFI_SUCEESS Install Boot manager menu success.
510 @retval Other Return error status.
515 RedfishPlatformHostInterfaceConstructor (
516 IN EFI_HANDLE ImageHandle
,
517 IN EFI_SYSTEM_TABLE
*SystemTable
522 Status
= GetRedfishRecordFromVariable (&mRedfishOverIpProtocolData
, &mRedfishProtocolDataSize
);
523 DEBUG ((DEBUG_INFO
, "%a: GetRedfishRecordFromVariable() - %r\n", __FUNCTION__
, Status
));
524 if (!EFI_ERROR (Status
)) {
525 DumpRedfishIpProtocolData (mRedfishOverIpProtocolData
, mRedfishProtocolDataSize
);