BdsPlatform.c 42 KB

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