RedfishHostInterfaceDxe.c 11 KB

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