BoardBdsHookLib.c 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630
  1. /** @file
  2. Board BDS hook Library. Implements board specific BDS hook library
  3. Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "BoardBdsHook.h"
  7. #include <Guid/RootBridgesConnectedEventGroup.h>
  8. #include <Protocol/FirmwareVolume2.h>
  9. #define LEGACY_8259_MASK_REGISTER_MASTER 0x21
  10. #define LEGACY_8259_MASK_REGISTER_SLAVE 0xA1
  11. #define LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER 0x4D0
  12. #define LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE 0x4D1
  13. //
  14. // Predefined platform connect sequence
  15. //
  16. EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[] = { NULL };
  17. ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard;
  18. ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode = gPnp16550ComPort;
  19. UART_DEVICE_PATH gUartDeviceNode = gUart;
  20. VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gPcAnsiTerminal;
  21. //
  22. // Global data
  23. //
  24. VOID *mEfiDevPathNotifyReg;
  25. EFI_EVENT mEfiDevPathEvent;
  26. VOID *mEmuVariableEventReg;
  27. EFI_EVENT mEmuVariableEvent;
  28. BOOLEAN mDetectVgaOnly;
  29. UINT16 mHostBridgeDevId;
  30. //
  31. // Table of host IRQs matching PCI IRQs A-D
  32. // (for configuring PCI Interrupt Line register)
  33. //
  34. CONST UINT8 PciHostIrqs[] = {
  35. 0x0a, 0x0a, 0x0b, 0x0b
  36. };
  37. //
  38. // Type definitions
  39. //
  40. typedef
  41. EFI_STATUS
  42. (EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
  43. IN EFI_HANDLE Handle,
  44. IN VOID *Instance,
  45. IN VOID *Context
  46. );
  47. /**
  48. @param[in] Handle - Handle of PCI device instance
  49. @param[in] PciIo - PCI IO protocol instance
  50. @param[in] Pci - PCI Header register block
  51. **/
  52. typedef
  53. EFI_STATUS
  54. (EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
  55. IN EFI_HANDLE Handle,
  56. IN EFI_PCI_IO_PROTOCOL *PciIo,
  57. IN PCI_TYPE00 *Pci
  58. );
  59. //
  60. // Function prototypes
  61. //
  62. EFI_STATUS
  63. VisitAllInstancesOfProtocol (
  64. IN EFI_GUID *Id,
  65. IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
  66. IN VOID *Context
  67. );
  68. EFI_STATUS
  69. VisitAllPciInstancesOfProtocol (
  70. IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
  71. );
  72. VOID
  73. InstallDevicePathCallback (
  74. VOID
  75. );
  76. EFI_STATUS
  77. EFIAPI
  78. ConnectRootBridge (
  79. IN EFI_HANDLE RootBridgeHandle,
  80. IN VOID *Instance,
  81. IN VOID *Context
  82. );
  83. VOID
  84. PlatformRegisterFvBootOption (
  85. EFI_GUID *FileGuid,
  86. CHAR16 *Description,
  87. UINT32 Attributes
  88. )
  89. {
  90. EFI_STATUS Status;
  91. INTN OptionIndex;
  92. EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
  93. EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
  94. UINTN BootOptionCount;
  95. MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
  96. EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
  97. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  98. Status = gBS->HandleProtocol (
  99. gImageHandle,
  100. &gEfiLoadedImageProtocolGuid,
  101. (VOID **) &LoadedImage
  102. );
  103. ASSERT_EFI_ERROR (Status);
  104. EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
  105. DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
  106. ASSERT (DevicePath != NULL);
  107. DevicePath = AppendDevicePathNode (
  108. DevicePath,
  109. (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
  110. );
  111. ASSERT (DevicePath != NULL);
  112. Status = EfiBootManagerInitializeLoadOption (
  113. &NewOption,
  114. LoadOptionNumberUnassigned,
  115. LoadOptionTypeBoot,
  116. Attributes,
  117. Description,
  118. DevicePath,
  119. NULL,
  120. 0
  121. );
  122. ASSERT_EFI_ERROR (Status);
  123. FreePool (DevicePath);
  124. BootOptions = EfiBootManagerGetLoadOptions (
  125. &BootOptionCount, LoadOptionTypeBoot
  126. );
  127. OptionIndex = EfiBootManagerFindLoadOption (
  128. &NewOption, BootOptions, BootOptionCount
  129. );
  130. if (OptionIndex == -1) {
  131. Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
  132. ASSERT_EFI_ERROR (Status);
  133. }
  134. EfiBootManagerFreeLoadOption (&NewOption);
  135. EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
  136. }
  137. /**
  138. Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
  139. whose device paths do not resolve exactly to an FvFile in the system.
  140. This removes any boot options that point to binaries built into the firmware
  141. and have become stale due to any of the following:
  142. - DXEFV's base address or size changed (historical),
  143. - DXEFV's FvNameGuid changed,
  144. - the FILE_GUID of the pointed-to binary changed,
  145. - the referenced binary is no longer built into the firmware.
  146. EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
  147. avoids exact duplicates.
  148. **/
  149. VOID
  150. RemoveStaleFvFileOptions (
  151. VOID
  152. )
  153. {
  154. EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
  155. UINTN BootOptionCount;
  156. UINTN Index;
  157. BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount,
  158. LoadOptionTypeBoot);
  159. for (Index = 0; Index < BootOptionCount; ++Index) {
  160. EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;
  161. EFI_STATUS Status;
  162. EFI_HANDLE FvHandle;
  163. //
  164. // If the device path starts with neither MemoryMapped(...) nor Fv(...),
  165. // then keep the boot option.
  166. //
  167. Node1 = BootOptions[Index].FilePath;
  168. if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH &&
  169. DevicePathSubType (Node1) == HW_MEMMAP_DP) &&
  170. !(DevicePathType (Node1) == MEDIA_DEVICE_PATH &&
  171. DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) {
  172. continue;
  173. }
  174. //
  175. // If the second device path node is not FvFile(...), then keep the boot
  176. // option.
  177. //
  178. Node2 = NextDevicePathNode (Node1);
  179. if (DevicePathType (Node2) != MEDIA_DEVICE_PATH ||
  180. DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) {
  181. continue;
  182. }
  183. //
  184. // Locate the Firmware Volume2 protocol instance that is denoted by the
  185. // boot option. If this lookup fails (i.e., the boot option references a
  186. // firmware volume that doesn't exist), then we'll proceed to delete the
  187. // boot option.
  188. //
  189. SearchNode = Node1;
  190. Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,
  191. &SearchNode, &FvHandle);
  192. if (!EFI_ERROR (Status)) {
  193. //
  194. // The firmware volume was found; now let's see if it contains the FvFile
  195. // identified by GUID.
  196. //
  197. EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
  198. MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;
  199. UINTN BufferSize;
  200. EFI_FV_FILETYPE FoundType;
  201. EFI_FV_FILE_ATTRIBUTES FileAttributes;
  202. UINT32 AuthenticationStatus;
  203. Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid,
  204. (VOID **)&FvProtocol);
  205. ASSERT_EFI_ERROR (Status);
  206. FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;
  207. //
  208. // Buffer==NULL means we request metadata only: BufferSize, FoundType,
  209. // FileAttributes.
  210. //
  211. Status = FvProtocol->ReadFile (
  212. FvProtocol,
  213. &FvFileNode->FvFileName, // NameGuid
  214. NULL, // Buffer
  215. &BufferSize,
  216. &FoundType,
  217. &FileAttributes,
  218. &AuthenticationStatus
  219. );
  220. if (!EFI_ERROR (Status)) {
  221. //
  222. // The FvFile was found. Keep the boot option.
  223. //
  224. continue;
  225. }
  226. }
  227. //
  228. // Delete the boot option.
  229. //
  230. Status = EfiBootManagerDeleteLoadOptionVariable (
  231. BootOptions[Index].OptionNumber, LoadOptionTypeBoot);
  232. DEBUG_CODE (
  233. CHAR16 *DevicePathString;
  234. DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath,
  235. FALSE, FALSE);
  236. DEBUG ((
  237. EFI_ERROR (Status) ? EFI_D_WARN : DEBUG_VERBOSE,
  238. "%a: removing stale Boot#%04x %s: %r\n",
  239. __FUNCTION__,
  240. (UINT32)BootOptions[Index].OptionNumber,
  241. DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
  242. Status
  243. ));
  244. if (DevicePathString != NULL) {
  245. FreePool (DevicePathString);
  246. }
  247. );
  248. }
  249. EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
  250. }
  251. VOID
  252. PlatformRegisterOptionsAndKeys (
  253. VOID
  254. )
  255. {
  256. EFI_STATUS Status;
  257. EFI_INPUT_KEY Enter;
  258. EFI_INPUT_KEY F2;
  259. EFI_INPUT_KEY Esc;
  260. EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
  261. //
  262. // Register ENTER as CONTINUE key
  263. //
  264. Enter.ScanCode = SCAN_NULL;
  265. Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
  266. Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
  267. ASSERT_EFI_ERROR (Status);
  268. DEBUG ((DEBUG_INFO, "PlatformRegisterOptionsAndKeys\n"));
  269. if (EFI_ERROR(Status)){
  270. return;
  271. }
  272. //
  273. // Map F2 to Boot Manager Menu
  274. //
  275. F2.ScanCode = SCAN_F2;
  276. F2.UnicodeChar = CHAR_NULL;
  277. Esc.ScanCode = SCAN_ESC;
  278. Esc.UnicodeChar = CHAR_NULL;
  279. Status = EfiBootManagerGetBootManagerMenu (&BootOption);
  280. ASSERT_EFI_ERROR (Status);
  281. Status = EfiBootManagerAddKeyOptionVariable (
  282. NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL
  283. );
  284. ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
  285. Status = EfiBootManagerAddKeyOptionVariable (
  286. NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL
  287. );
  288. ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
  289. }
  290. /**
  291. Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
  292. @param[in] DeviceHandle Handle of the LPC Bridge device.
  293. @retval EFI_SUCCESS Console devices on the LPC bridge have been added to
  294. ConOut, ConIn, and ErrOut.
  295. @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
  296. from DeviceHandle.
  297. **/
  298. EFI_STATUS
  299. EFIAPI
  300. ConnectRootBridge (
  301. IN EFI_HANDLE RootBridgeHandle,
  302. IN VOID *Instance,
  303. IN VOID *Context
  304. )
  305. {
  306. EFI_STATUS Status;
  307. //
  308. // Make the PCI bus driver connect the root bridge, non-recursively. This
  309. // will produce a number of child handles with PciIo on them.
  310. //
  311. Status = gBS->ConnectController (
  312. RootBridgeHandle, // ControllerHandle
  313. NULL, // DriverImageHandle
  314. NULL, // RemainingDevicePath -- produce all
  315. // children
  316. FALSE // Recursive
  317. );
  318. return Status;
  319. }
  320. /**
  321. Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
  322. @param[in] DeviceHandle Handle of the LPC Bridge device.
  323. @retval EFI_SUCCESS Console devices on the LPC bridge have been added to
  324. ConOut, ConIn, and ErrOut.
  325. @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
  326. from DeviceHandle.
  327. **/
  328. EFI_STATUS
  329. PrepareLpcBridgeDevicePath (
  330. IN EFI_HANDLE DeviceHandle
  331. )
  332. {
  333. EFI_STATUS Status;
  334. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  335. EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
  336. CHAR16 *DevPathStr;
  337. DevicePath = NULL;
  338. Status = gBS->HandleProtocol (
  339. DeviceHandle,
  340. &gEfiDevicePathProtocolGuid,
  341. (VOID*)&DevicePath
  342. );
  343. if (EFI_ERROR (Status)) {
  344. return Status;
  345. }
  346. TempDevicePath = DevicePath;
  347. //
  348. // Register Keyboard
  349. //
  350. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
  351. EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
  352. //
  353. // Register COM1
  354. //
  355. DevicePath = TempDevicePath;
  356. gPnp16550ComPortDeviceNode.UID = 0;
  357. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
  358. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
  359. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
  360. //
  361. // Print Device Path
  362. //
  363. DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
  364. if (DevPathStr != NULL) {
  365. DEBUG((
  366. DEBUG_INFO,
  367. "BdsPlatform.c+%d: COM%d DevPath: %s\n",
  368. __LINE__,
  369. gPnp16550ComPortDeviceNode.UID + 1,
  370. DevPathStr
  371. ));
  372. FreePool(DevPathStr);
  373. }
  374. EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
  375. EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
  376. EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
  377. //
  378. // Register COM2
  379. //
  380. DevicePath = TempDevicePath;
  381. gPnp16550ComPortDeviceNode.UID = 1;
  382. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
  383. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
  384. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
  385. //
  386. // Print Device Path
  387. //
  388. DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
  389. if (DevPathStr != NULL) {
  390. DEBUG((
  391. DEBUG_INFO,
  392. "BdsPlatform.c+%d: COM%d DevPath: %s\n",
  393. __LINE__,
  394. gPnp16550ComPortDeviceNode.UID + 1,
  395. DevPathStr
  396. ));
  397. FreePool(DevPathStr);
  398. }
  399. EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
  400. EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
  401. EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
  402. return EFI_SUCCESS;
  403. }
  404. EFI_STATUS
  405. GetGopDevicePath (
  406. IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
  407. OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
  408. )
  409. {
  410. UINTN Index;
  411. EFI_STATUS Status;
  412. EFI_HANDLE PciDeviceHandle;
  413. EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
  414. EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
  415. UINTN GopHandleCount;
  416. EFI_HANDLE *GopHandleBuffer;
  417. if (PciDevicePath == NULL || GopDevicePath == NULL) {
  418. return EFI_INVALID_PARAMETER;
  419. }
  420. //
  421. // Initialize the GopDevicePath to be PciDevicePath
  422. //
  423. *GopDevicePath = PciDevicePath;
  424. TempPciDevicePath = PciDevicePath;
  425. Status = gBS->LocateDevicePath (
  426. &gEfiDevicePathProtocolGuid,
  427. &TempPciDevicePath,
  428. &PciDeviceHandle
  429. );
  430. if (EFI_ERROR (Status)) {
  431. return Status;
  432. }
  433. //
  434. // Try to connect this handle, so that GOP driver could start on this
  435. // device and create child handles with GraphicsOutput Protocol installed
  436. // on them, then we get device paths of these child handles and select
  437. // them as possible console device.
  438. //
  439. gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
  440. Status = gBS->LocateHandleBuffer (
  441. ByProtocol,
  442. &gEfiGraphicsOutputProtocolGuid,
  443. NULL,
  444. &GopHandleCount,
  445. &GopHandleBuffer
  446. );
  447. if (!EFI_ERROR (Status)) {
  448. //
  449. // Add all the child handles as possible Console Device
  450. //
  451. for (Index = 0; Index < GopHandleCount; Index++) {
  452. Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
  453. if (EFI_ERROR (Status)) {
  454. continue;
  455. }
  456. if (CompareMem (
  457. PciDevicePath,
  458. TempDevicePath,
  459. GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
  460. ) == 0) {
  461. //
  462. // In current implementation, we only enable one of the child handles
  463. // as console device, i.e. sotre one of the child handle's device
  464. // path to variable "ConOut"
  465. // In future, we could select all child handles to be console device
  466. //
  467. *GopDevicePath = TempDevicePath;
  468. //
  469. // Delete the PCI device's path that added by
  470. // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
  471. //
  472. EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);
  473. EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);
  474. }
  475. }
  476. gBS->FreePool (GopHandleBuffer);
  477. }
  478. return EFI_SUCCESS;
  479. }
  480. /**
  481. Add PCI display to ConOut.
  482. @param[in] DeviceHandle Handle of the PCI display device.
  483. @retval EFI_SUCCESS The PCI display device has been added to ConOut.
  484. @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
  485. from DeviceHandle.
  486. **/
  487. EFI_STATUS
  488. PreparePciDisplayDevicePath (
  489. IN EFI_HANDLE DeviceHandle
  490. )
  491. {
  492. EFI_STATUS Status;
  493. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  494. EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
  495. DevicePath = NULL;
  496. GopDevicePath = NULL;
  497. Status = gBS->HandleProtocol (
  498. DeviceHandle,
  499. &gEfiDevicePathProtocolGuid,
  500. (VOID*)&DevicePath
  501. );
  502. if (EFI_ERROR (Status)) {
  503. return Status;
  504. }
  505. GetGopDevicePath (DevicePath, &GopDevicePath);
  506. DevicePath = GopDevicePath;
  507. EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
  508. return EFI_SUCCESS;
  509. }
  510. /**
  511. Add PCI Serial to ConOut, ConIn, ErrOut.
  512. @param[in] DeviceHandle Handle of the PCI serial device.
  513. @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,
  514. ErrOut.
  515. @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
  516. from DeviceHandle.
  517. **/
  518. EFI_STATUS
  519. PreparePciSerialDevicePath (
  520. IN EFI_HANDLE DeviceHandle
  521. )
  522. {
  523. EFI_STATUS Status;
  524. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  525. DevicePath = NULL;
  526. Status = gBS->HandleProtocol (
  527. DeviceHandle,
  528. &gEfiDevicePathProtocolGuid,
  529. (VOID*)&DevicePath
  530. );
  531. if (EFI_ERROR (Status)) {
  532. return Status;
  533. }
  534. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
  535. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
  536. EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
  537. EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
  538. EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
  539. return EFI_SUCCESS;
  540. }
  541. EFI_STATUS
  542. VisitAllInstancesOfProtocol (
  543. IN EFI_GUID *Id,
  544. IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
  545. IN VOID *Context
  546. )
  547. {
  548. EFI_STATUS Status;
  549. UINTN HandleCount;
  550. EFI_HANDLE *HandleBuffer;
  551. UINTN Index;
  552. VOID *Instance;
  553. //
  554. // Start to check all the PciIo to find all possible device
  555. //
  556. HandleCount = 0;
  557. HandleBuffer = NULL;
  558. Status = gBS->LocateHandleBuffer (
  559. ByProtocol,
  560. Id,
  561. NULL,
  562. &HandleCount,
  563. &HandleBuffer
  564. );
  565. if (EFI_ERROR (Status)) {
  566. return Status;
  567. }
  568. for (Index = 0; Index < HandleCount; Index++) {
  569. Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
  570. if (EFI_ERROR (Status)) {
  571. continue;
  572. }
  573. Status = (*CallBackFunction) (
  574. HandleBuffer[Index],
  575. Instance,
  576. Context
  577. );
  578. }
  579. gBS->FreePool (HandleBuffer);
  580. return EFI_SUCCESS;
  581. }
  582. EFI_STATUS
  583. EFIAPI
  584. VisitingAPciInstance (
  585. IN EFI_HANDLE Handle,
  586. IN VOID *Instance,
  587. IN VOID *Context
  588. )
  589. {
  590. EFI_STATUS Status;
  591. EFI_PCI_IO_PROTOCOL *PciIo;
  592. PCI_TYPE00 Pci;
  593. PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
  594. //
  595. // Check for all PCI device
  596. //
  597. Status = PciIo->Pci.Read (
  598. PciIo,
  599. EfiPciIoWidthUint32,
  600. 0,
  601. sizeof (Pci) / sizeof (UINT32),
  602. &Pci
  603. );
  604. if (EFI_ERROR (Status)) {
  605. return Status;
  606. }
  607. return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
  608. Handle,
  609. PciIo,
  610. &Pci
  611. );
  612. }
  613. EFI_STATUS
  614. VisitAllPciInstances (
  615. IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
  616. )
  617. {
  618. return VisitAllInstancesOfProtocol (
  619. &gEfiPciIoProtocolGuid,
  620. VisitingAPciInstance,
  621. (VOID*)(UINTN) CallBackFunction
  622. );
  623. }
  624. /**
  625. Do platform specific PCI Device check and add them to
  626. ConOut, ConIn, ErrOut.
  627. @param[in] Handle - Handle of PCI device instance
  628. @param[in] PciIo - PCI IO protocol instance
  629. @param[in] Pci - PCI Header register block
  630. @retval EFI_SUCCESS - PCI Device check and Console variable update
  631. successfully.
  632. @retval EFI_STATUS - PCI Device check or Console variable update fail.
  633. **/
  634. EFI_STATUS
  635. EFIAPI
  636. DetectAndPreparePlatformPciDevicePath (
  637. IN EFI_HANDLE Handle,
  638. IN EFI_PCI_IO_PROTOCOL *PciIo,
  639. IN PCI_TYPE00 *Pci
  640. )
  641. {
  642. EFI_STATUS Status;
  643. Status = PciIo->Attributes (
  644. PciIo,
  645. EfiPciIoAttributeOperationEnable,
  646. EFI_PCI_DEVICE_ENABLE,
  647. NULL
  648. );
  649. ASSERT_EFI_ERROR (Status);
  650. if (!mDetectVgaOnly) {
  651. //
  652. // Here we decide whether it is LPC Bridge
  653. //
  654. if ((IS_PCI_LPC (Pci)) ||
  655. ((IS_PCI_ISA_PDECODE (Pci)) &&
  656. (Pci->Hdr.VendorId == 0x8086) &&
  657. (Pci->Hdr.DeviceId == 0x7000)
  658. )
  659. ) {
  660. //
  661. // Add IsaKeyboard to ConIn,
  662. // add IsaSerial to ConOut, ConIn, ErrOut
  663. //
  664. DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));
  665. PrepareLpcBridgeDevicePath (Handle);
  666. return EFI_SUCCESS;
  667. }
  668. //
  669. // Here we decide which Serial device to enable in PCI bus
  670. //
  671. if (IS_PCI_16550SERIAL (Pci)) {
  672. //
  673. // Add them to ConOut, ConIn, ErrOut.
  674. //
  675. DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n"));
  676. PreparePciSerialDevicePath (Handle);
  677. return EFI_SUCCESS;
  678. }
  679. }
  680. //
  681. // Here we decide which display device to enable in PCI bus
  682. //
  683. if (IS_PCI_DISPLAY (Pci)) {
  684. //
  685. // Add them to ConOut.
  686. //
  687. DEBUG ((DEBUG_INFO, "Found PCI display device\n"));
  688. PreparePciDisplayDevicePath (Handle);
  689. return EFI_SUCCESS;
  690. }
  691. return Status;
  692. }
  693. /**
  694. Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
  695. @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
  696. @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
  697. @retval EFI_STATUS - PCI Device check or Console variable update fail.
  698. **/
  699. EFI_STATUS
  700. DetectAndPreparePlatformPciDevicePaths (
  701. BOOLEAN DetectVgaOnly
  702. )
  703. {
  704. mDetectVgaOnly = DetectVgaOnly;
  705. return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
  706. }
  707. /**
  708. Connect the predefined platform default console device.
  709. Always try to find and enable PCI display devices.
  710. @param[in] PlatformConsole Predefined platform default console device array.
  711. **/
  712. VOID
  713. PlatformInitializeConsole (
  714. IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole
  715. )
  716. {
  717. UINTN Index;
  718. EFI_DEVICE_PATH_PROTOCOL *VarConout;
  719. EFI_DEVICE_PATH_PROTOCOL *VarConin;
  720. //
  721. // Connect RootBridge
  722. //
  723. GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME, (VOID **) &VarConout, NULL);
  724. GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME, (VOID **) &VarConin, NULL);
  725. if (VarConout == NULL || VarConin == NULL) {
  726. //
  727. // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
  728. //
  729. DetectAndPreparePlatformPciDevicePaths (FALSE);
  730. DetectAndPreparePlatformPciDevicePaths(TRUE);
  731. //
  732. // Have chance to connect the platform default console,
  733. // the platform default console is the minimue device group
  734. // the platform should support
  735. //
  736. for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
  737. //
  738. // Update the console variable with the connect type
  739. //
  740. if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
  741. EfiBootManagerUpdateConsoleVariable (ConIn, PlatformConsole[Index].DevicePath, NULL);
  742. }
  743. if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
  744. EfiBootManagerUpdateConsoleVariable (ConOut, PlatformConsole[Index].DevicePath, NULL);
  745. }
  746. if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
  747. EfiBootManagerUpdateConsoleVariable (ErrOut, PlatformConsole[Index].DevicePath, NULL);
  748. }
  749. }
  750. } else {
  751. //
  752. // Only detect VGA device and add them to ConOut
  753. //
  754. DetectAndPreparePlatformPciDevicePaths (TRUE);
  755. }
  756. }
  757. /**
  758. Configure PCI Interrupt Line register for applicable devices
  759. Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
  760. @param[in] Handle - Handle of PCI device instance
  761. @param[in] PciIo - PCI IO protocol instance
  762. @param[in] PciHdr - PCI Header register block
  763. @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
  764. **/
  765. EFI_STATUS
  766. EFIAPI
  767. SetPciIntLine (
  768. IN EFI_HANDLE Handle,
  769. IN EFI_PCI_IO_PROTOCOL *PciIo,
  770. IN PCI_TYPE00 *PciHdr
  771. )
  772. {
  773. EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
  774. EFI_DEVICE_PATH_PROTOCOL *DevPath;
  775. UINTN RootSlot;
  776. UINTN Idx;
  777. UINT8 IrqLine;
  778. EFI_STATUS Status;
  779. UINT32 RootBusNumber;
  780. Status = EFI_SUCCESS;
  781. if (PciHdr->Device.InterruptPin != 0) {
  782. DevPathNode = DevicePathFromHandle (Handle);
  783. ASSERT (DevPathNode != NULL);
  784. DevPath = DevPathNode;
  785. RootBusNumber = 0;
  786. if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&
  787. DevicePathSubType (DevPathNode) == ACPI_DP &&
  788. ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {
  789. RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;
  790. }
  791. //
  792. // Compute index into PciHostIrqs[] table by walking
  793. // the device path and adding up all device numbers
  794. //
  795. Status = EFI_NOT_FOUND;
  796. RootSlot = 0;
  797. Idx = PciHdr->Device.InterruptPin - 1;
  798. while (!IsDevicePathEnd (DevPathNode)) {
  799. if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&
  800. DevicePathSubType (DevPathNode) == HW_PCI_DP) {
  801. Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;
  802. //
  803. // Unlike SeaBIOS, which starts climbing from the leaf device
  804. // up toward the root, we traverse the device path starting at
  805. // the root moving toward the leaf node.
  806. // The slot number of the top-level parent bridge is needed
  807. // with more than 24 slots on the root bus.
  808. //
  809. if (Status != EFI_SUCCESS) {
  810. Status = EFI_SUCCESS;
  811. RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;
  812. }
  813. }
  814. DevPathNode = NextDevicePathNode (DevPathNode);
  815. }
  816. if (EFI_ERROR (Status)) {
  817. return Status;
  818. }
  819. if (RootBusNumber == 0 && RootSlot == 0) {
  820. return Status; //bugbug: workaround; need SIMICS change B0/D0/F0 PCI_IntPin reg(0x3D) = 0X0
  821. // DEBUG((
  822. // DEBUG_ERROR,
  823. // "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
  824. // __FUNCTION__
  825. // ));
  826. // ASSERT (FALSE);
  827. }
  828. //
  829. // Final PciHostIrqs[] index calculation depends on the platform
  830. // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
  831. //
  832. switch (mHostBridgeDevId) {
  833. case INTEL_82441_DEVICE_ID:
  834. Idx -= 1;
  835. break;
  836. case INTEL_ICH10_DEVICE_ID:
  837. //
  838. // SeaBIOS contains the following comment:
  839. // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
  840. // with a different starting index.
  841. //
  842. // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
  843. //
  844. if (RootSlot > 24) {
  845. //
  846. // in this case, subtract back out RootSlot from Idx
  847. // (SeaBIOS never adds it to begin with, but that would make our
  848. // device path traversal loop above too awkward)
  849. //
  850. Idx -= RootSlot;
  851. }
  852. break;
  853. default:
  854. ASSERT (FALSE); // should never get here
  855. }
  856. Idx %= ARRAY_SIZE (PciHostIrqs);
  857. IrqLine = PciHostIrqs[Idx];
  858. DEBUG_CODE_BEGIN ();
  859. {
  860. CHAR16 *DevPathString;
  861. STATIC CHAR16 Fallback[] = L"<failed to convert>";
  862. UINTN Segment, Bus, Device, Function;
  863. DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);
  864. if (DevPathString == NULL) {
  865. DevPathString = Fallback;
  866. }
  867. Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
  868. ASSERT_EFI_ERROR (Status);
  869. DEBUG ((DEBUG_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,
  870. (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,
  871. IrqLine));
  872. if (DevPathString != Fallback) {
  873. FreePool (DevPathString);
  874. }
  875. }
  876. DEBUG_CODE_END ();
  877. //
  878. // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
  879. //
  880. Status = PciIo->Pci.Write (
  881. PciIo,
  882. EfiPciIoWidthUint8,
  883. PCI_INT_LINE_OFFSET,
  884. 1,
  885. &IrqLine
  886. );
  887. }
  888. return Status;
  889. }
  890. /**
  891. Write to mask and edge/level triggered registers of master and slave 8259 PICs.
  892. @param[in] Mask low byte for master PIC mask register,
  893. high byte for slave PIC mask register.
  894. @param[in] EdgeLevel low byte for master PIC edge/level triggered register,
  895. high byte for slave PIC edge/level triggered register.
  896. **/
  897. VOID
  898. Interrupt8259WriteMask(
  899. IN UINT16 Mask,
  900. IN UINT16 EdgeLevel
  901. )
  902. {
  903. IoWrite8(LEGACY_8259_MASK_REGISTER_MASTER, (UINT8)Mask);
  904. IoWrite8(LEGACY_8259_MASK_REGISTER_SLAVE, (UINT8)(Mask >> 8));
  905. IoWrite8(LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER, (UINT8)EdgeLevel);
  906. IoWrite8(LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE, (UINT8)(EdgeLevel >> 8));
  907. }
  908. VOID
  909. PciAcpiInitialization (
  910. VOID
  911. )
  912. {
  913. UINTN Pmba;
  914. //
  915. // Query Host Bridge DID to determine platform type
  916. //
  917. mHostBridgeDevId = PcdGet16 (PcdSimicsX58HostBridgePciDevId);
  918. switch (mHostBridgeDevId) {
  919. case INTEL_82441_DEVICE_ID:
  920. Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
  921. //
  922. // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
  923. //
  924. PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
  925. PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
  926. PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
  927. PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
  928. break;
  929. case INTEL_ICH10_DEVICE_ID:
  930. Pmba = POWER_MGMT_REGISTER_ICH10 (ICH10_PMBASE);
  931. //
  932. // 00:1f.0 LPC Bridge LNK routing targets
  933. //
  934. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
  935. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
  936. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
  937. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
  938. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
  939. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
  940. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
  941. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
  942. break;
  943. default:
  944. DEBUG ((DEBUG_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
  945. __FUNCTION__, mHostBridgeDevId));
  946. ASSERT (FALSE);
  947. return;
  948. }
  949. //
  950. // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
  951. //
  952. VisitAllPciInstances (SetPciIntLine);
  953. //
  954. // Set ACPI SCI_EN bit in PMCNTRL
  955. //
  956. IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
  957. //
  958. // Set all 8259 interrupts to edge triggered and disabled
  959. //
  960. Interrupt8259WriteMask(0xFFFF, 0x0000);
  961. }
  962. EFI_STATUS
  963. EFIAPI
  964. ConnectRecursivelyIfPciMassStorage (
  965. IN EFI_HANDLE Handle,
  966. IN EFI_PCI_IO_PROTOCOL *Instance,
  967. IN PCI_TYPE00 *PciHeader
  968. )
  969. {
  970. EFI_STATUS Status;
  971. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  972. CHAR16 *DevPathStr;
  973. //
  974. // Recognize PCI Mass Storage
  975. //
  976. if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
  977. DevicePath = NULL;
  978. Status = gBS->HandleProtocol (
  979. Handle,
  980. &gEfiDevicePathProtocolGuid,
  981. (VOID*)&DevicePath
  982. );
  983. if (EFI_ERROR (Status)) {
  984. return Status;
  985. }
  986. //
  987. // Print Device Path
  988. //
  989. DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
  990. if (DevPathStr != NULL) {
  991. DEBUG(( DEBUG_INFO, "Found Mass Storage device: %s\n", DevPathStr));
  992. FreePool(DevPathStr);
  993. }
  994. Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
  995. if (EFI_ERROR (Status)) {
  996. return Status;
  997. }
  998. }
  999. return EFI_SUCCESS;
  1000. }
  1001. /**
  1002. This notification function is invoked when the
  1003. EMU Variable FVB has been changed.
  1004. @param Event The event that occurred
  1005. @param Context For EFI compatibility. Not used.
  1006. **/
  1007. VOID
  1008. EFIAPI
  1009. EmuVariablesUpdatedCallback (
  1010. IN EFI_EVENT Event,
  1011. IN VOID *Context
  1012. )
  1013. {
  1014. DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
  1015. UpdateNvVarsOnFileSystem ();
  1016. }
  1017. EFI_STATUS
  1018. EFIAPI
  1019. VisitingFileSystemInstance (
  1020. IN EFI_HANDLE Handle,
  1021. IN VOID *Instance,
  1022. IN VOID *Context
  1023. )
  1024. {
  1025. EFI_STATUS Status;
  1026. STATIC BOOLEAN ConnectedToFileSystem = FALSE;
  1027. if (ConnectedToFileSystem) {
  1028. return EFI_ALREADY_STARTED;
  1029. }
  1030. Status = ConnectNvVarsToFileSystem (Handle);
  1031. if (EFI_ERROR (Status)) {
  1032. return Status;
  1033. }
  1034. ConnectedToFileSystem = TRUE;
  1035. mEmuVariableEvent =
  1036. EfiCreateProtocolNotifyEvent (
  1037. &gEfiDevicePathProtocolGuid,
  1038. TPL_CALLBACK,
  1039. EmuVariablesUpdatedCallback,
  1040. NULL,
  1041. &mEmuVariableEventReg
  1042. );
  1043. PcdSet64S (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);
  1044. return EFI_SUCCESS;
  1045. }
  1046. VOID
  1047. PlatformBdsRestoreNvVarsFromHardDisk (
  1048. )
  1049. {
  1050. VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
  1051. VisitAllInstancesOfProtocol (
  1052. &gEfiSimpleFileSystemProtocolGuid,
  1053. VisitingFileSystemInstance,
  1054. NULL
  1055. );
  1056. }
  1057. /**
  1058. Connect with predefined platform connect sequence.
  1059. The OEM/IBV can customize with their own connect sequence.
  1060. **/
  1061. VOID
  1062. PlatformBdsConnectSequence (
  1063. VOID
  1064. )
  1065. {
  1066. UINTN Index;
  1067. DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
  1068. Index = 0;
  1069. //
  1070. // Here we can get the customized platform connect sequence
  1071. // Notes: we can connect with new variable which record the
  1072. // last time boots connect device path sequence
  1073. //
  1074. while (gPlatformConnectSequence[Index] != NULL) {
  1075. //
  1076. // Build the platform boot option
  1077. //
  1078. EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL);
  1079. Index++;
  1080. }
  1081. //
  1082. // Just use the simple policy to connect all devices
  1083. //
  1084. DEBUG ((DEBUG_INFO, "EfiBootManagerConnectAll\n"));
  1085. EfiBootManagerConnectAll ();
  1086. PciAcpiInitialization ();
  1087. }
  1088. /**
  1089. Do the platform specific action after the console is ready
  1090. Possible things that can be done in PlatformBootManagerAfterConsole:
  1091. > Console post action:
  1092. > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
  1093. > Signal console ready platform customized event
  1094. > Run diagnostics like memory testing
  1095. > Connect certain devices
  1096. > Dispatch aditional option roms
  1097. > Special boot: e.g.: USB boot, enter UI
  1098. **/
  1099. // VOID
  1100. // EFIAPI
  1101. // PlatformBootManagerAfterConsole (
  1102. // VOID
  1103. // )
  1104. // {
  1105. // }
  1106. /**
  1107. This notification function is invoked when an instance of the
  1108. EFI_DEVICE_PATH_PROTOCOL is produced.
  1109. @param Event The event that occurred
  1110. @param Context For EFI compatibility. Not used.
  1111. **/
  1112. VOID
  1113. EFIAPI
  1114. NotifyDevPath (
  1115. IN EFI_EVENT Event,
  1116. IN VOID *Context
  1117. )
  1118. {
  1119. EFI_HANDLE Handle;
  1120. EFI_STATUS Status;
  1121. UINTN BufferSize;
  1122. EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
  1123. ATAPI_DEVICE_PATH *Atapi;
  1124. //
  1125. // Examine all new handles
  1126. //
  1127. for (;;) {
  1128. //
  1129. // Get the next handle
  1130. //
  1131. BufferSize = sizeof (Handle);
  1132. Status = gBS->LocateHandle (
  1133. ByRegisterNotify,
  1134. NULL,
  1135. mEfiDevPathNotifyReg,
  1136. &BufferSize,
  1137. &Handle
  1138. );
  1139. //
  1140. // If not found, we're done
  1141. //
  1142. if (EFI_NOT_FOUND == Status) {
  1143. break;
  1144. }
  1145. if (EFI_ERROR (Status)) {
  1146. continue;
  1147. }
  1148. //
  1149. // Get the DevicePath protocol on that handle
  1150. //
  1151. Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
  1152. ASSERT_EFI_ERROR (Status);
  1153. while (!IsDevicePathEnd (DevPathNode)) {
  1154. //
  1155. // Find the handler to dump this device path node
  1156. //
  1157. if (
  1158. (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
  1159. (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
  1160. ) {
  1161. Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
  1162. PciOr16 (
  1163. PCI_LIB_ADDRESS (
  1164. 0,
  1165. 1,
  1166. 1,
  1167. (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
  1168. ),
  1169. BIT15
  1170. );
  1171. }
  1172. //
  1173. // Next device path node
  1174. //
  1175. DevPathNode = NextDevicePathNode (DevPathNode);
  1176. }
  1177. }
  1178. return;
  1179. }
  1180. VOID
  1181. InstallDevicePathCallback (
  1182. VOID
  1183. )
  1184. {
  1185. DEBUG ((DEBUG_INFO, "Registered NotifyDevPath Event\n"));
  1186. mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
  1187. &gEfiDevicePathProtocolGuid,
  1188. TPL_CALLBACK,
  1189. NotifyDevPath,
  1190. NULL,
  1191. &mEfiDevPathNotifyReg
  1192. );
  1193. }
  1194. /**
  1195. ReadyToBoot callback to set video and text mode for internal shell boot.
  1196. That will not connect USB controller while CSM and FastBoot are disabled, we need to connect them
  1197. before booting to Shell for showing USB devices in Shell.
  1198. When FastBoot is enabled and Windows Console is the chosen Console behavior, input devices will not be connected
  1199. by default. Hence, when booting to EFI shell, connecting input consoles are required.
  1200. @param Event Pointer to this event
  1201. @param Context Event hanlder private data
  1202. @retval None.
  1203. **/
  1204. VOID
  1205. EFIAPI
  1206. BdsReadyToBootCallback (
  1207. IN EFI_EVENT Event,
  1208. IN VOID *Context
  1209. )
  1210. {
  1211. DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
  1212. }
  1213. /**
  1214. This is the callback function for PCI ENUMERATION COMPLETE.
  1215. @param[in] Event The Event this notify function registered to.
  1216. @param[in] Context Pointer to the context data registered to the Event.
  1217. **/
  1218. VOID
  1219. EFIAPI
  1220. BdsSmmReadyToLockCallback (
  1221. IN EFI_EVENT Event,
  1222. IN VOID *Context
  1223. )
  1224. {
  1225. VOID *ProtocolPointer;
  1226. EFI_STATUS Status;
  1227. //
  1228. // Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
  1229. // if it is, we will skip it until real event is triggered
  1230. //
  1231. Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL, (VOID **) &ProtocolPointer);
  1232. if (EFI_SUCCESS != Status) {
  1233. return;
  1234. }
  1235. DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
  1236. //
  1237. // Dispatch the deferred 3rd party images.
  1238. //
  1239. EfiBootManagerDispatchDeferredImages ();
  1240. //
  1241. // For non-trusted console it must be handled here.
  1242. //
  1243. //UpdateGraphicConOut (FALSE);
  1244. }
  1245. /**
  1246. This is the callback function for PCI ENUMERATION COMPLETE.
  1247. @param[in] Event The Event this notify function registered to.
  1248. @param[in] Context Pointer to the context data registered to the Event.
  1249. **/
  1250. VOID
  1251. EFIAPI
  1252. BdsPciEnumCompleteCallback (
  1253. IN EFI_EVENT Event,
  1254. IN VOID *Context
  1255. )
  1256. {
  1257. VOID *ProtocolPointer;
  1258. EFI_STATUS Status;
  1259. PLATFORM_CONSOLE_CONNECT_ENTRY PlatformConsole[3];
  1260. UINTN PlatformConsoleCount;
  1261. UINTN MaxCount;
  1262. //
  1263. // Check if this is first time called by EfiCreateProtocolNotifyEvent() or not,
  1264. // if it is, we will skip it until real event is triggered
  1265. //
  1266. Status = gBS->LocateProtocol (&gEfiPciEnumerationCompleteProtocolGuid, NULL, (VOID **) &ProtocolPointer);
  1267. if (EFI_SUCCESS != Status) {
  1268. return;
  1269. }
  1270. PlatformConsoleCount = 0;
  1271. MaxCount = ARRAY_SIZE(PlatformConsole);
  1272. if (PcdGetSize (PcdTrustedConsoleOutputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
  1273. PlatformConsole[PlatformConsoleCount].ConnectType = ConOut;
  1274. PlatformConsole[PlatformConsoleCount].DevicePath = PcdGetPtr (PcdTrustedConsoleOutputDevicePath);
  1275. PlatformConsoleCount++;
  1276. }
  1277. if (PcdGetSize (PcdTrustedConsoleInputDevicePath) >= sizeof(EFI_DEVICE_PATH_PROTOCOL) &&
  1278. PlatformConsoleCount < MaxCount) {
  1279. PlatformConsole[PlatformConsoleCount].ConnectType = ConIn;
  1280. PlatformConsole[PlatformConsoleCount].DevicePath = PcdGetPtr (PcdTrustedConsoleInputDevicePath);
  1281. PlatformConsoleCount++;
  1282. }
  1283. if (PlatformConsoleCount < MaxCount){
  1284. PlatformConsole[PlatformConsoleCount].ConnectType = 0;
  1285. PlatformConsole[PlatformConsoleCount].DevicePath = NULL;
  1286. }else{
  1287. PlatformConsole[MaxCount - 1].ConnectType = 0;
  1288. PlatformConsole[MaxCount - 1].DevicePath = NULL;
  1289. }
  1290. DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
  1291. PlatformInitializeConsole (PlatformConsole);
  1292. }
  1293. /**
  1294. Before console after trusted console event callback
  1295. @param[in] Event The Event this notify function registered to.
  1296. @param[in] Context Pointer to the context data registered to the Event.
  1297. **/
  1298. VOID
  1299. EFIAPI
  1300. BdsBeforeConsoleAfterTrustedConsoleCallback (
  1301. IN EFI_EVENT Event,
  1302. IN VOID *Context
  1303. )
  1304. {
  1305. EFI_BOOT_MANAGER_LOAD_OPTION *NvBootOptions;
  1306. UINTN NvBootOptionCount;
  1307. UINTN Index;
  1308. EFI_STATUS Status;
  1309. DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
  1310. NvBootOptions = EfiBootManagerGetLoadOptions (&NvBootOptionCount, LoadOptionTypeBoot);
  1311. for (Index = 0; Index < NvBootOptionCount; Index++) {
  1312. Status = EfiBootManagerDeleteLoadOptionVariable (NvBootOptions[Index].OptionNumber, LoadOptionTypeBoot);
  1313. if (EFI_ERROR (Status)) {
  1314. DEBUG ((
  1315. DEBUG_ERROR,
  1316. "%a: removing Boot#%04x %r\n",
  1317. __FUNCTION__,
  1318. (UINT32) NvBootOptions[Index].OptionNumber,
  1319. Status
  1320. ));
  1321. }
  1322. }
  1323. InstallDevicePathCallback ();
  1324. VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid, ConnectRootBridge, NULL);
  1325. //
  1326. // Enable LPC
  1327. //
  1328. PciOr16 (POWER_MGMT_REGISTER_ICH10(0x04), BIT0 | BIT1 | BIT2);
  1329. PlatformRegisterOptionsAndKeys ();
  1330. }
  1331. /**
  1332. Before console before end of DXE event callback
  1333. @param[in] Event The Event this notify function registered to.
  1334. @param[in] Context Pointer to the context data registered to the Event.
  1335. **/
  1336. VOID
  1337. EFIAPI
  1338. BdsBeforeConsoleBeforeEndOfDxeGuidCallback (
  1339. IN EFI_EVENT Event,
  1340. IN VOID *Context
  1341. ){
  1342. DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
  1343. }
  1344. /**
  1345. After console ready before boot option event callback
  1346. @param[in] Event The Event this notify function registered to.
  1347. @param[in] Context Pointer to the context data registered to the Event.
  1348. **/
  1349. VOID
  1350. EFIAPI
  1351. BdsAfterConsoleReadyBeforeBootOptionCallback (
  1352. IN EFI_EVENT Event,
  1353. IN VOID *Context
  1354. )
  1355. {
  1356. EFI_BOOT_MODE BootMode;
  1357. DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
  1358. if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
  1359. DEBUG ((DEBUG_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "
  1360. "from disk since flash variables appear to be supported.\n"));
  1361. } else {
  1362. //
  1363. // Try to restore variables from the hard disk early so
  1364. // they can be used for the other BDS connect operations.
  1365. //
  1366. PlatformBdsRestoreNvVarsFromHardDisk ();
  1367. }
  1368. //
  1369. // Get current Boot Mode
  1370. //
  1371. BootMode = GetBootModeHob ();
  1372. DEBUG ((DEBUG_ERROR, "Boot Mode:%x\n", BootMode));
  1373. //
  1374. // Go the different platform policy with different boot mode
  1375. // Notes: this part code can be change with the table policy
  1376. //
  1377. ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
  1378. //
  1379. // Perform some platform specific connect sequence
  1380. //
  1381. PlatformBdsConnectSequence ();
  1382. //
  1383. // Logo show
  1384. //
  1385. EnableBootLogo(PcdGetPtr(PcdLogoFile));
  1386. EfiBootManagerRefreshAllBootOption ();
  1387. //
  1388. // Register UEFI Shell
  1389. //
  1390. PlatformRegisterFvBootOption (
  1391. PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE
  1392. );
  1393. RemoveStaleFvFileOptions ();
  1394. }