ConsolePrefDxe.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /** @file
  2. *
  3. * Copyright (c) 2017, Linaro, Ltd. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause-Patent
  6. *
  7. **/
  8. #include <Uefi.h>
  9. #include <IndustryStandard/Acpi.h>
  10. #include <libfdt.h>
  11. #include <Library/BaseLib.h>
  12. #include <Library/DebugLib.h>
  13. #include <Library/DevicePathLib.h>
  14. #include <Library/HiiLib.h>
  15. #include <Library/UefiBootServicesTableLib.h>
  16. #include <Library/UefiBootServicesTableLib.h>
  17. #include <Library/UefiDriverEntryPoint.h>
  18. #include <Library/UefiLib.h>
  19. #include <Library/UefiRuntimeServicesTableLib.h>
  20. #include <Protocol/AcpiTable.h>
  21. #include <Protocol/AcpiSystemDescriptionTable.h>
  22. #include "ConsolePrefDxe.h"
  23. #define SPCR_SIG EFI_ACPI_2_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
  24. extern UINT8 ConsolePrefHiiBin[];
  25. extern UINT8 ConsolePrefDxeStrings[];
  26. typedef struct {
  27. VENDOR_DEVICE_PATH VendorDevicePath;
  28. EFI_DEVICE_PATH_PROTOCOL End;
  29. } HII_VENDOR_DEVICE_PATH;
  30. STATIC HII_VENDOR_DEVICE_PATH mConsolePrefDxeVendorDevicePath = {
  31. {
  32. {
  33. HARDWARE_DEVICE_PATH,
  34. HW_VENDOR_DP,
  35. {
  36. (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
  37. (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
  38. }
  39. },
  40. CONSOLE_PREF_FORMSET_GUID
  41. },
  42. {
  43. END_DEVICE_PATH_TYPE,
  44. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  45. {
  46. (UINT8)(END_DEVICE_PATH_LENGTH),
  47. (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
  48. }
  49. }
  50. };
  51. STATIC EFI_EVENT mReadyToBootEvent;
  52. STATIC
  53. EFI_STATUS
  54. InstallHiiPages (
  55. VOID
  56. )
  57. {
  58. EFI_STATUS Status;
  59. EFI_HII_HANDLE HiiHandle;
  60. EFI_HANDLE DriverHandle;
  61. DriverHandle = NULL;
  62. Status = gBS->InstallMultipleProtocolInterfaces (
  63. &DriverHandle,
  64. &gEfiDevicePathProtocolGuid,
  65. &mConsolePrefDxeVendorDevicePath,
  66. NULL
  67. );
  68. if (EFI_ERROR (Status)) {
  69. return Status;
  70. }
  71. HiiHandle = HiiAddPackages (
  72. &gConsolePrefFormSetGuid,
  73. DriverHandle,
  74. ConsolePrefDxeStrings,
  75. ConsolePrefHiiBin,
  76. NULL
  77. );
  78. if (HiiHandle == NULL) {
  79. gBS->UninstallMultipleProtocolInterfaces (
  80. DriverHandle,
  81. &gEfiDevicePathProtocolGuid,
  82. &mConsolePrefDxeVendorDevicePath,
  83. NULL
  84. );
  85. return EFI_OUT_OF_RESOURCES;
  86. }
  87. return EFI_SUCCESS;
  88. }
  89. STATIC
  90. VOID
  91. RemoveDtStdoutPath (
  92. VOID
  93. )
  94. {
  95. VOID *Dtb;
  96. INT32 Node;
  97. INT32 Error;
  98. EFI_STATUS Status;
  99. Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &Dtb);
  100. if (EFI_ERROR (Status)) {
  101. DEBUG ((
  102. DEBUG_INFO,
  103. "%a: could not retrieve DT blob - %r\n",
  104. __FUNCTION__,
  105. Status
  106. ));
  107. return;
  108. }
  109. Node = fdt_path_offset (Dtb, "/chosen");
  110. if (Node < 0) {
  111. return;
  112. }
  113. Error = fdt_delprop (Dtb, Node, "stdout-path");
  114. if (Error) {
  115. DEBUG ((
  116. DEBUG_INFO,
  117. "%a: Failed to delete 'stdout-path' property: %a\n",
  118. __FUNCTION__,
  119. fdt_strerror (Error)
  120. ));
  121. }
  122. }
  123. STATIC
  124. VOID
  125. RemoveSpcrTable (
  126. VOID
  127. )
  128. {
  129. EFI_ACPI_SDT_PROTOCOL *Sdt;
  130. EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
  131. EFI_STATUS Status;
  132. UINTN TableIndex;
  133. EFI_ACPI_SDT_HEADER *TableHeader;
  134. EFI_ACPI_TABLE_VERSION TableVersion;
  135. UINTN TableKey;
  136. Status = gBS->LocateProtocol (
  137. &gEfiAcpiTableProtocolGuid,
  138. NULL,
  139. (VOID **)&AcpiTable
  140. );
  141. if (EFI_ERROR (Status)) {
  142. return;
  143. }
  144. Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&Sdt);
  145. if (EFI_ERROR (Status)) {
  146. return;
  147. }
  148. TableIndex = 0;
  149. TableKey = 0;
  150. TableHeader = NULL;
  151. do {
  152. Status = Sdt->GetAcpiTable (
  153. TableIndex++,
  154. &TableHeader,
  155. &TableVersion,
  156. &TableKey
  157. );
  158. if (EFI_ERROR (Status)) {
  159. break;
  160. }
  161. if (TableHeader->Signature != SPCR_SIG) {
  162. continue;
  163. }
  164. Status = AcpiTable->UninstallAcpiTable (AcpiTable, TableKey);
  165. if (EFI_ERROR (Status)) {
  166. DEBUG ((
  167. DEBUG_WARN,
  168. "%a: failed to uninstall SPCR table - %r\n",
  169. __FUNCTION__,
  170. Status
  171. ));
  172. }
  173. break;
  174. } while (TRUE);
  175. }
  176. STATIC
  177. VOID
  178. EFIAPI
  179. OnReadyToBoot (
  180. IN EFI_EVENT Event,
  181. IN VOID *Context
  182. )
  183. {
  184. CONSOLE_PREF_VARSTORE_DATA ConsolePref;
  185. UINTN BufferSize;
  186. EFI_STATUS Status;
  187. VOID *Gop;
  188. BufferSize = sizeof (ConsolePref);
  189. Status = gRT->GetVariable (
  190. CONSOLE_PREF_VARIABLE_NAME,
  191. &gConsolePrefFormSetGuid,
  192. NULL,
  193. &BufferSize,
  194. &ConsolePref
  195. );
  196. if (EFI_ERROR (Status)) {
  197. DEBUG ((
  198. DEBUG_ERROR,
  199. "%a: variable '%s' could not be read - bailing!\n",
  200. __FUNCTION__,
  201. CONSOLE_PREF_VARIABLE_NAME
  202. ));
  203. return;
  204. }
  205. if (ConsolePref.Console == CONSOLE_PREF_SERIAL) {
  206. DEBUG ((
  207. DEBUG_INFO,
  208. "%a: serial console preferred - doing nothing\n",
  209. __FUNCTION__
  210. ));
  211. return;
  212. }
  213. //
  214. // Check if any GOP instances exist: if so, disable stdout-path and SPCR
  215. //
  216. Status = gBS->LocateProtocol (&gEfiGraphicsOutputProtocolGuid, NULL, &Gop);
  217. if (EFI_ERROR (Status)) {
  218. DEBUG ((
  219. DEBUG_INFO,
  220. "%a: no GOP instances found - doing nothing (%r)\n",
  221. __FUNCTION__,
  222. Status
  223. ));
  224. return;
  225. }
  226. RemoveDtStdoutPath ();
  227. RemoveSpcrTable ();
  228. }
  229. /**
  230. The entry point for ConsolePrefDxe driver.
  231. @param[in] ImageHandle The image handle of the driver.
  232. @param[in] SystemTable The system table.
  233. @retval EFI_ALREADY_STARTED The driver already exists in system.
  234. @retval EFI_OUT_OF_RESOURCES Fail to execute entry point due to lack of
  235. resources.
  236. @retval EFI_SUCCESS All the related protocols are installed on
  237. the driver.
  238. **/
  239. EFI_STATUS
  240. EFIAPI
  241. ConsolePrefDxeEntryPoint (
  242. IN EFI_HANDLE ImageHandle,
  243. IN EFI_SYSTEM_TABLE *SystemTable
  244. )
  245. {
  246. EFI_STATUS Status;
  247. CONSOLE_PREF_VARSTORE_DATA ConsolePref;
  248. UINTN BufferSize;
  249. //
  250. // Get the current console preference from the ConsolePref variable.
  251. //
  252. BufferSize = sizeof (ConsolePref);
  253. Status = gRT->GetVariable (
  254. CONSOLE_PREF_VARIABLE_NAME,
  255. &gConsolePrefFormSetGuid,
  256. NULL,
  257. &BufferSize,
  258. &ConsolePref
  259. );
  260. if (EFI_ERROR (Status)) {
  261. DEBUG ((
  262. DEBUG_INFO,
  263. "%a: no console preference found, defaulting to graphical\n",
  264. __FUNCTION__
  265. ));
  266. ConsolePref.Console = CONSOLE_PREF_GRAPHICAL;
  267. }
  268. if (!EFI_ERROR (Status) &&
  269. (ConsolePref.Console != CONSOLE_PREF_GRAPHICAL) &&
  270. (ConsolePref.Console != CONSOLE_PREF_SERIAL))
  271. {
  272. DEBUG ((
  273. DEBUG_WARN,
  274. "%a: invalid value for %s, defaulting to graphical\n",
  275. __FUNCTION__,
  276. CONSOLE_PREF_VARIABLE_NAME
  277. ));
  278. ConsolePref.Console = CONSOLE_PREF_GRAPHICAL;
  279. Status = EFI_INVALID_PARAMETER; // trigger setvar below
  280. }
  281. //
  282. // Write the newly selected value back to the variable store.
  283. //
  284. if (EFI_ERROR (Status)) {
  285. ZeroMem (&ConsolePref.Reserved, sizeof (ConsolePref.Reserved));
  286. Status = gRT->SetVariable (
  287. CONSOLE_PREF_VARIABLE_NAME,
  288. &gConsolePrefFormSetGuid,
  289. EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
  290. sizeof (ConsolePref),
  291. &ConsolePref
  292. );
  293. if (EFI_ERROR (Status)) {
  294. DEBUG ((
  295. DEBUG_ERROR,
  296. "%a: gRT->SetVariable () failed - %r\n",
  297. __FUNCTION__,
  298. Status
  299. ));
  300. return Status;
  301. }
  302. }
  303. Status = gBS->CreateEventEx (
  304. EVT_NOTIFY_SIGNAL,
  305. TPL_CALLBACK,
  306. OnReadyToBoot,
  307. NULL,
  308. &gEfiEventReadyToBootGuid,
  309. &mReadyToBootEvent
  310. );
  311. ASSERT_EFI_ERROR (Status);
  312. return InstallHiiPages ();
  313. }