]> git.proxmox.com Git - mirror_edk2.git/blame - RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.c
RedfishPkg: fix multiple SMBIOS type 42 version issue
[mirror_edk2.git] / RedfishPkg / RedfishHostInterfaceDxe / RedfishHostInterfaceDxe.c
CommitLineData
d4fae44d
AC
1/** @file\r
2 RedfishHostInterfaceDxe builds up SMBIOS Type 42h host interface\r
3 record for Redfish service host interface using EFI MBIOS Protocol.\r
4 RedfishHostInterfacePlatformLib is the platform-level library which\r
5 provides the content of Redfish host interface type 42h record.\r
6\r
7 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
8 (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>\r
2846c19d 9 Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved.<BR>\r
aea8a9c9 10 Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
d4fae44d
AC
11\r
12 SPDX-License-Identifier: BSD-2-Clause-Patent\r
13\r
14**/\r
15#include <Uefi.h>\r
16#include <Library/BaseLib.h>\r
17#include <Library/BaseMemoryLib.h>\r
18#include <Library/DebugLib.h>\r
19#include <Library/MemoryAllocationLib.h>\r
20#include <Library/PrintLib.h>\r
21#include <Library/RedfishHostInterfaceLib.h>\r
22#include <Library/UefiLib.h>\r
23#include <Library/UefiBootServicesTableLib.h>\r
24#include <Library/UefiRuntimeServicesTableLib.h>\r
25\r
2846c19d
AC
26static EFI_EVENT mPlatformHostInterfaceReadylEvent = NULL;\r
27static VOID *mPlatformHostInterfaceReadyRegistration = NULL;\r
28\r
d4fae44d
AC
29/**\r
30 Create SMBIOS type 42 record for Redfish host interface.\r
31\r
a7cf2c56 32 @retval EFI_SUCCESS SMBIOS type 42 record is created.\r
d4fae44d
AC
33 @retval Others Fail to create SMBIOS 42 record.\r
34\r
35**/\r
36EFI_STATUS\r
37RedfishCreateSmbiosTable42 (\r
38 VOID\r
39 )\r
40{\r
39de741e
MK
41 REDFISH_INTERFACE_DATA *DeviceDescriptor;\r
42 UINT8 DeviceDataLength;\r
43 UINT8 DeviceType;\r
44 EFI_STATUS Status;\r
45 MC_HOST_INTERFACE_PROTOCOL_RECORD *ProtocolRecord;\r
46 VOID *ProtocolRecords;\r
47 VOID *NewProtocolRecords;\r
48 UINT8 ProtocolCount;\r
49 UINT8 CurrentProtocolsDataLength;\r
50 UINT8 NewProtocolsDataLength;\r
51 UINT8 ProtocolDataSize;\r
52 SMBIOS_TABLE_TYPE42 *Type42Record;\r
53 EFI_SMBIOS_PROTOCOL *Smbios;\r
54 EFI_SMBIOS_HANDLE MemArrayMappedAddrSmbiosHandle;\r
d4fae44d
AC
55\r
56 //\r
57 // Get platform Redfish host interface device type descriptor data.\r
58 //\r
59 Status = RedfishPlatformHostInterfaceDeviceDescriptor (&DeviceType, &DeviceDescriptor);\r
60 if (EFI_ERROR (Status)) {\r
61 if (Status == EFI_NOT_FOUND) {\r
62 DEBUG ((DEBUG_ERROR, "%a: No Redfish host interface descriptor is provided on this platform.", __FUNCTION__));\r
63 return EFI_NOT_FOUND;\r
64 }\r
39de741e
MK
65\r
66 DEBUG ((DEBUG_ERROR, "%a: Fail to get device descriptor, %r.", __FUNCTION__, Status));\r
d4fae44d
AC
67 return Status;\r
68 }\r
39de741e
MK
69\r
70 if ((DeviceType != REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2) &&\r
71 (DeviceType != REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2)\r
72 )\r
73 {\r
d4fae44d
AC
74 DEBUG ((DEBUG_ERROR, "%a: Only support either protocol type 04h or 05h as Redfish host interface.", __FUNCTION__));\r
75 return EFI_UNSUPPORTED;\r
76 }\r
39de741e 77\r
d4fae44d
AC
78 if (DeviceType == REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) {\r
79 DeviceDataLength = DeviceDescriptor->DeviceDescriptor.PciPcieDeviceV2.Length;\r
80 } else {\r
81 DeviceDataLength = DeviceDescriptor->DeviceDescriptor.UsbDeviceV2.Length;\r
82 }\r
39de741e 83\r
d4fae44d
AC
84 //\r
85 // Loop to get platform Redfish host interface protocol type data.\r
86 //\r
39de741e
MK
87 ProtocolRecord = NULL;\r
88 ProtocolRecords = NULL;\r
89 NewProtocolRecords = NULL;\r
90 Type42Record = NULL;\r
91 ProtocolCount = 0;\r
d4fae44d 92 CurrentProtocolsDataLength = 0;\r
39de741e 93 NewProtocolsDataLength = 0;\r
d4fae44d
AC
94 while (TRUE) {\r
95 Status = RedfishPlatformHostInterfaceProtocolData (&ProtocolRecord, ProtocolCount);\r
96 if (Status == EFI_NOT_FOUND) {\r
97 break;\r
98 }\r
39de741e
MK
99\r
100 if (EFI_ERROR (Status)) {\r
d4fae44d
AC
101 DEBUG ((DEBUG_ERROR, "%a: Fail to get Redfish host interafce protocol type data.", __FUNCTION__));\r
102 if (ProtocolRecords != NULL) {\r
103 FreePool (ProtocolRecords);\r
104 }\r
39de741e 105\r
d4fae44d
AC
106 if (ProtocolRecord != NULL) {\r
107 FreePool (ProtocolRecord);\r
108 }\r
39de741e 109\r
d4fae44d
AC
110 return Status;\r
111 }\r
39de741e
MK
112\r
113 ProtocolDataSize = sizeof (MC_HOST_INTERFACE_PROTOCOL_RECORD) - sizeof (ProtocolRecord->ProtocolTypeData) + ProtocolRecord->ProtocolTypeDataLen;\r
d4fae44d
AC
114 NewProtocolsDataLength += ProtocolDataSize;\r
115 if (ProtocolRecords == NULL) {\r
116 ProtocolRecords = AllocateZeroPool (NewProtocolsDataLength);\r
117 if (ProtocolRecords == NULL) {\r
118 FreePool (ProtocolRecord);\r
119 return EFI_OUT_OF_RESOURCES;\r
120 }\r
39de741e 121\r
d4fae44d
AC
122 CopyMem ((VOID *)ProtocolRecords, (VOID *)ProtocolRecord, ProtocolDataSize);\r
123 NewProtocolRecords = ProtocolRecords;\r
124 } else {\r
39de741e 125 NewProtocolRecords = ReallocatePool (CurrentProtocolsDataLength, NewProtocolsDataLength, (VOID *)ProtocolRecords);\r
d4fae44d 126 if (NewProtocolRecords == NULL) {\r
c403de7b 127 DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for Redfish host interface protocol data.", __FUNCTION__));\r
d4fae44d
AC
128 FreePool (ProtocolRecords);\r
129 FreePool (ProtocolRecord);\r
130 return EFI_OUT_OF_RESOURCES;\r
131 }\r
39de741e 132\r
d4fae44d
AC
133 CopyMem (\r
134 (VOID *)((UINT8 *)NewProtocolRecords + CurrentProtocolsDataLength),\r
135 (VOID *)ProtocolRecord,\r
136 ProtocolDataSize\r
137 );\r
138 }\r
39de741e 139\r
d4fae44d
AC
140 FreePool (ProtocolRecord);\r
141 CurrentProtocolsDataLength = NewProtocolsDataLength;\r
39de741e
MK
142 ProtocolCount++;\r
143 }\r
144\r
d4fae44d
AC
145 if (ProtocolCount == 0) {\r
146 goto ON_EXIT;\r
147 }\r
39de741e 148\r
d4fae44d
AC
149 //\r
150 // Construct SMBIOS Type 42h for Redfish host inteface.\r
151 //\r
152 // SMBIOS type 42 Record for Redfish Interface\r
153 // 00h Type BYTE 42 Management Controller Host Interface structure indicator\r
154 // 01h Length BYTE Varies Length of the structure, a minimum of 09h\r
155 // 02h Handle WORD Varies\r
156 // 04h Interface Type BYTE Varies Management Controller Interface Type.\r
157 // 05h Interface Specific Data Length (n)\r
158 // 06h Interface Specific data\r
159 // 06h+n number of protocols defined for the host interface (typically 1)\r
160 // 07h+n Include a Protocol Record for each protocol supported.\r
161 //\r
39de741e
MK
162 Type42Record = (SMBIOS_TABLE_TYPE42 *)AllocateZeroPool (\r
163 sizeof (SMBIOS_TABLE_TYPE42) - 4\r
164 + DeviceDataLength\r
165 + 1 /// For Protocol Record Count\r
166 + CurrentProtocolsDataLength\r
167 + 2 /// Double NULL terminator/\r
168 );\r
d4fae44d
AC
169 if (Type42Record == NULL) {\r
170 Status = EFI_OUT_OF_RESOURCES;\r
171 goto ON_EXIT;\r
172 }\r
173\r
174 Type42Record->Hdr.Type = EFI_SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE;\r
175 Type42Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE42) - 4\r
39de741e
MK
176 + DeviceDataLength\r
177 + 1\r
178 + CurrentProtocolsDataLength;\r
179 Type42Record->Hdr.Handle = 0;\r
d4fae44d
AC
180 Type42Record->InterfaceType = MCHostInterfaceTypeNetworkHostInterface; // Network Host Interface\r
181\r
182 //\r
183 // Fill in InterfaceTypeSpecificDataLength field\r
184 //\r
185 Type42Record->InterfaceTypeSpecificDataLength = DeviceDataLength;\r
186\r
187 //\r
188 // Fill in InterfaceTypeSpecificData field\r
189 //\r
190 CopyMem (Type42Record->InterfaceTypeSpecificData, DeviceDescriptor, DeviceDataLength);\r
191 FreePool (DeviceDescriptor);\r
192 DeviceDescriptor = NULL;\r
193\r
194 //\r
195 // Fill in InterfaceTypeSpecificData Protocol Count field\r
196 //\r
197 *(Type42Record->InterfaceTypeSpecificData + DeviceDataLength) = ProtocolCount;\r
198\r
199 //\r
200 // Fill in Redfish Protocol Data\r
201 //\r
202 CopyMem (\r
203 Type42Record->InterfaceTypeSpecificData + DeviceDataLength + 1,\r
204 NewProtocolRecords,\r
205 CurrentProtocolsDataLength\r
206 );\r
207\r
208 //\r
209 // 5. Add Redfish interface data record to SMBIOS table 42\r
210 //\r
39de741e 211 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios);\r
d4fae44d
AC
212 if (EFI_ERROR (Status)) {\r
213 goto ON_EXIT;\r
214 }\r
215\r
216 MemArrayMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
39de741e
MK
217 Status = Smbios->Add (\r
218 Smbios,\r
219 NULL,\r
220 &MemArrayMappedAddrSmbiosHandle,\r
221 (EFI_SMBIOS_TABLE_HEADER *)Type42Record\r
222 );\r
d4fae44d
AC
223 DEBUG ((DEBUG_INFO, "RedfishPlatformDxe: Smbios->Add() - %r\n", Status));\r
224 if (EFI_ERROR (Status)) {\r
225 goto ON_EXIT;\r
226 }\r
39de741e 227\r
d4fae44d
AC
228 Status = EFI_SUCCESS;\r
229\r
230ON_EXIT:\r
231 if (DeviceDescriptor != NULL) {\r
232 FreePool (DeviceDescriptor);\r
233 }\r
39de741e 234\r
d4fae44d
AC
235 if (NewProtocolRecords != NULL) {\r
236 FreePool (NewProtocolRecords);\r
237 }\r
39de741e 238\r
d4fae44d
AC
239 if (Type42Record != NULL) {\r
240 FreePool (Type42Record);\r
241 }\r
39de741e 242\r
d4fae44d
AC
243 return Status;\r
244}\r
245\r
2846c19d
AC
246/**\r
247 Notification event of platform Redfish Host Interface readiness.\r
248\r
249 @param[in] Event Event whose notification function is being invoked.\r
250 @param[in] Context The pointer to the notification function's context,\r
251 which is implementation-dependent.\r
252\r
253**/\r
254VOID\r
255EFIAPI\r
256PlatformHostInterfaceInformationReady (\r
257 IN EFI_EVENT Event,\r
258 IN VOID *Context\r
259 )\r
260{\r
261 DEBUG ((DEBUG_INFO, "%a: Platform Redfish Host Interface informtion is ready\n", __FUNCTION__));\r
262\r
263 RedfishCreateSmbiosTable42 ();\r
aea8a9c9
NW
264\r
265 //\r
266 // Close event so we don't create multiple type 42 records\r
267 //\r
268 gBS->CloseEvent (Event);\r
269 mPlatformHostInterfaceReadylEvent = NULL;\r
270\r
2846c19d
AC
271 return;\r
272}\r
273\r
d4fae44d
AC
274/**\r
275 Main entry for this driver.\r
276\r
277 @param ImageHandle Image handle this driver.\r
278 @param SystemTable Pointer to SystemTable.\r
279\r
a7cf2c56 280 @retval EFI_SUCCESS This function always complete successfully.\r
d4fae44d
AC
281\r
282**/\r
283EFI_STATUS\r
284EFIAPI\r
285RedfishHostInterfaceDxeEntryPoint (\r
39de741e
MK
286 IN EFI_HANDLE ImageHandle,\r
287 IN EFI_SYSTEM_TABLE *SystemTable\r
d4fae44d
AC
288 )\r
289{\r
2846c19d
AC
290 EFI_STATUS Status;\r
291 EFI_GUID *ReadyGuid;\r
292\r
293 DEBUG ((DEBUG_INFO, "%a: Entry\n.", __FUNCTION__));\r
294\r
d4fae44d 295 //\r
2846c19d
AC
296 // Check if the Redfish Host Interface depends on\r
297 // the specific protocol installation.\r
d4fae44d 298 //\r
2846c19d
AC
299 Status = RedfishPlatformHostInterfaceNotification (&ReadyGuid);\r
300 if (Status == EFI_SUCCESS) {\r
301 DEBUG ((DEBUG_INFO, " Create protocol install notification to know the installation of platform Redfish host interface readiness\n"));\r
302 DEBUG ((DEBUG_INFO, " Protocol GUID: %g\n", ReadyGuid));\r
303 //\r
304 // Register event for ReadyGuid protocol installed by\r
305 // platform Redfish host interface library.\r
306 //\r
307 Status = gBS->CreateEvent (\r
308 EVT_NOTIFY_SIGNAL,\r
309 TPL_CALLBACK,\r
310 PlatformHostInterfaceInformationReady,\r
311 NULL,\r
312 &mPlatformHostInterfaceReadylEvent\r
313 );\r
314 if (EFI_ERROR (Status)) {\r
315 DEBUG ((DEBUG_ERROR, " Fail to create event for the installation of platform Redfish host interface readiness.\n"));\r
316 return Status;\r
317 }\r
318\r
319 Status = gBS->RegisterProtocolNotify (\r
320 ReadyGuid,\r
321 mPlatformHostInterfaceReadylEvent,\r
322 &mPlatformHostInterfaceReadyRegistration\r
323 );\r
324 if (EFI_ERROR (Status)) {\r
325 DEBUG ((DEBUG_ERROR, " Fail to register event for the installation of platform Redfish host interface readiness.\n"));\r
326 return Status;\r
327 }\r
328\r
329 return EFI_SUCCESS;\r
330 }\r
331\r
332 if ((Status == EFI_UNSUPPORTED) || (Status == EFI_ALREADY_STARTED)) {\r
333 Status = RedfishCreateSmbiosTable42 ();\r
334 }\r
335\r
336 // Return other erros.\r
337 return Status;\r
d4fae44d 338}\r