BdsPlatform.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553
  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. STATIC
  279. VOID
  280. SaveS3BootScript (
  281. VOID
  282. );
  283. //
  284. // BDS Platform Functions
  285. //
  286. /**
  287. Do the platform init, can be customized by OEM/IBV
  288. Possible things that can be done in PlatformBootManagerBeforeConsole:
  289. > Update console variable: 1. include hot-plug devices;
  290. > 2. Clear ConIn and add SOL for AMT
  291. > Register new Driver#### or Boot####
  292. > Register new Key####: e.g.: F12
  293. > Signal ReadyToLock event
  294. > Authentication action: 1. connect Auth devices;
  295. > 2. Identify auto logon user.
  296. **/
  297. VOID
  298. EFIAPI
  299. PlatformBootManagerBeforeConsole (
  300. VOID
  301. )
  302. {
  303. // EFI_HANDLE Handle;
  304. // EFI_STATUS Status;
  305. DEBUG ((EFI_D_INFO, "PlatformBootManagerBeforeConsole\n"));
  306. InstallDevicePathCallback ();
  307. VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,
  308. ConnectRootBridge, NULL);
  309. //
  310. // Enable LPC
  311. //
  312. PciOr16(POWER_MGMT_REGISTER_ICH10(0x04),
  313. BIT0 | BIT1 | BIT2);
  314. //
  315. // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
  316. // the preparation of S3 system information. That logic has a hard dependency
  317. // on the presence of the FACS ACPI table. Since our ACPI tables are only
  318. // installed after PCI enumeration completes, we must not trigger the S3 save
  319. // earlier, hence we can't signal End-of-Dxe earlier.
  320. //
  321. EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
  322. PlatformInitializeConsole (gPlatformConsole);
  323. PlatformRegisterOptionsAndKeys ();
  324. }
  325. EFI_STATUS
  326. EFIAPI
  327. ConnectRootBridge (
  328. IN EFI_HANDLE RootBridgeHandle,
  329. IN VOID *Instance,
  330. IN VOID *Context
  331. )
  332. {
  333. EFI_STATUS Status;
  334. //
  335. // Make the PCI bus driver connect the root bridge, non-recursively. This
  336. // will produce a number of child handles with PciIo on them.
  337. //
  338. Status = gBS->ConnectController (
  339. RootBridgeHandle, // ControllerHandle
  340. NULL, // DriverImageHandle
  341. NULL, // RemainingDevicePath -- produce all
  342. // children
  343. FALSE // Recursive
  344. );
  345. return Status;
  346. }
  347. /**
  348. Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
  349. @param[in] DeviceHandle Handle of the LPC Bridge device.
  350. @retval EFI_SUCCESS Console devices on the LPC bridge have been added to
  351. ConOut, ConIn, and ErrOut.
  352. @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
  353. from DeviceHandle.
  354. **/
  355. EFI_STATUS
  356. PrepareLpcBridgeDevicePath (
  357. IN EFI_HANDLE DeviceHandle
  358. )
  359. {
  360. EFI_STATUS Status;
  361. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  362. EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
  363. CHAR16 *DevPathStr;
  364. DevicePath = NULL;
  365. Status = gBS->HandleProtocol (
  366. DeviceHandle,
  367. &gEfiDevicePathProtocolGuid,
  368. (VOID*)&DevicePath
  369. );
  370. if (EFI_ERROR (Status)) {
  371. return Status;
  372. }
  373. TempDevicePath = DevicePath;
  374. //
  375. // Register Keyboard
  376. //
  377. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
  378. EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
  379. //
  380. // Register COM1
  381. //
  382. DevicePath = TempDevicePath;
  383. gPnp16550ComPortDeviceNode.UID = 0;
  384. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
  385. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
  386. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
  387. //
  388. // Print Device Path
  389. //
  390. DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
  391. if (DevPathStr != NULL) {
  392. DEBUG((
  393. EFI_D_INFO,
  394. "BdsPlatform.c+%d: COM%d DevPath: %s\n",
  395. __LINE__,
  396. gPnp16550ComPortDeviceNode.UID + 1,
  397. DevPathStr
  398. ));
  399. FreePool(DevPathStr);
  400. }
  401. EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
  402. EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
  403. EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
  404. //
  405. // Register COM2
  406. //
  407. DevicePath = TempDevicePath;
  408. gPnp16550ComPortDeviceNode.UID = 1;
  409. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
  410. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
  411. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
  412. //
  413. // Print Device Path
  414. //
  415. DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
  416. if (DevPathStr != NULL) {
  417. DEBUG((
  418. EFI_D_INFO,
  419. "BdsPlatform.c+%d: COM%d DevPath: %s\n",
  420. __LINE__,
  421. gPnp16550ComPortDeviceNode.UID + 1,
  422. DevPathStr
  423. ));
  424. FreePool(DevPathStr);
  425. }
  426. EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
  427. EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
  428. EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
  429. return EFI_SUCCESS;
  430. }
  431. EFI_STATUS
  432. GetGopDevicePath (
  433. IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
  434. OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
  435. )
  436. {
  437. UINTN Index;
  438. EFI_STATUS Status;
  439. EFI_HANDLE PciDeviceHandle;
  440. EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
  441. EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
  442. UINTN GopHandleCount;
  443. EFI_HANDLE *GopHandleBuffer;
  444. if (PciDevicePath == NULL || GopDevicePath == NULL) {
  445. return EFI_INVALID_PARAMETER;
  446. }
  447. //
  448. // Initialize the GopDevicePath to be PciDevicePath
  449. //
  450. *GopDevicePath = PciDevicePath;
  451. TempPciDevicePath = PciDevicePath;
  452. Status = gBS->LocateDevicePath (
  453. &gEfiDevicePathProtocolGuid,
  454. &TempPciDevicePath,
  455. &PciDeviceHandle
  456. );
  457. if (EFI_ERROR (Status)) {
  458. return Status;
  459. }
  460. //
  461. // Try to connect this handle, so that GOP driver could start on this
  462. // device and create child handles with GraphicsOutput Protocol installed
  463. // on them, then we get device paths of these child handles and select
  464. // them as possible console device.
  465. //
  466. gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
  467. Status = gBS->LocateHandleBuffer (
  468. ByProtocol,
  469. &gEfiGraphicsOutputProtocolGuid,
  470. NULL,
  471. &GopHandleCount,
  472. &GopHandleBuffer
  473. );
  474. if (!EFI_ERROR (Status)) {
  475. //
  476. // Add all the child handles as possible Console Device
  477. //
  478. for (Index = 0; Index < GopHandleCount; Index++) {
  479. Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
  480. if (EFI_ERROR (Status)) {
  481. continue;
  482. }
  483. if (CompareMem (
  484. PciDevicePath,
  485. TempDevicePath,
  486. GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
  487. ) == 0) {
  488. //
  489. // In current implementation, we only enable one of the child handles
  490. // as console device, i.e. sotre one of the child handle's device
  491. // path to variable "ConOut"
  492. // In future, we could select all child handles to be console device
  493. //
  494. *GopDevicePath = TempDevicePath;
  495. //
  496. // Delete the PCI device's path that added by
  497. // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
  498. //
  499. EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);
  500. EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);
  501. }
  502. }
  503. gBS->FreePool (GopHandleBuffer);
  504. }
  505. return EFI_SUCCESS;
  506. }
  507. /**
  508. Add PCI display to ConOut.
  509. @param[in] DeviceHandle Handle of the PCI display device.
  510. @retval EFI_SUCCESS The PCI display device has been added to ConOut.
  511. @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
  512. from DeviceHandle.
  513. **/
  514. EFI_STATUS
  515. PreparePciDisplayDevicePath (
  516. IN EFI_HANDLE DeviceHandle
  517. )
  518. {
  519. EFI_STATUS Status;
  520. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  521. EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
  522. DevicePath = NULL;
  523. GopDevicePath = NULL;
  524. Status = gBS->HandleProtocol (
  525. DeviceHandle,
  526. &gEfiDevicePathProtocolGuid,
  527. (VOID*)&DevicePath
  528. );
  529. if (EFI_ERROR (Status)) {
  530. return Status;
  531. }
  532. GetGopDevicePath (DevicePath, &GopDevicePath);
  533. DevicePath = GopDevicePath;
  534. EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
  535. return EFI_SUCCESS;
  536. }
  537. /**
  538. Add PCI Serial to ConOut, ConIn, ErrOut.
  539. @param[in] DeviceHandle Handle of the PCI serial device.
  540. @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,
  541. ErrOut.
  542. @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
  543. from DeviceHandle.
  544. **/
  545. EFI_STATUS
  546. PreparePciSerialDevicePath (
  547. IN EFI_HANDLE DeviceHandle
  548. )
  549. {
  550. EFI_STATUS Status;
  551. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  552. DevicePath = NULL;
  553. Status = gBS->HandleProtocol (
  554. DeviceHandle,
  555. &gEfiDevicePathProtocolGuid,
  556. (VOID*)&DevicePath
  557. );
  558. if (EFI_ERROR (Status)) {
  559. return Status;
  560. }
  561. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
  562. DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
  563. EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
  564. EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
  565. EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
  566. return EFI_SUCCESS;
  567. }
  568. EFI_STATUS
  569. VisitAllInstancesOfProtocol (
  570. IN EFI_GUID *Id,
  571. IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
  572. IN VOID *Context
  573. )
  574. {
  575. EFI_STATUS Status;
  576. UINTN HandleCount;
  577. EFI_HANDLE *HandleBuffer;
  578. UINTN Index;
  579. VOID *Instance;
  580. //
  581. // Start to check all the PciIo to find all possible device
  582. //
  583. HandleCount = 0;
  584. HandleBuffer = NULL;
  585. Status = gBS->LocateHandleBuffer (
  586. ByProtocol,
  587. Id,
  588. NULL,
  589. &HandleCount,
  590. &HandleBuffer
  591. );
  592. if (EFI_ERROR (Status)) {
  593. return Status;
  594. }
  595. for (Index = 0; Index < HandleCount; Index++) {
  596. Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
  597. if (EFI_ERROR (Status)) {
  598. continue;
  599. }
  600. Status = (*CallBackFunction) (
  601. HandleBuffer[Index],
  602. Instance,
  603. Context
  604. );
  605. }
  606. gBS->FreePool (HandleBuffer);
  607. return EFI_SUCCESS;
  608. }
  609. EFI_STATUS
  610. EFIAPI
  611. VisitingAPciInstance (
  612. IN EFI_HANDLE Handle,
  613. IN VOID *Instance,
  614. IN VOID *Context
  615. )
  616. {
  617. EFI_STATUS Status;
  618. EFI_PCI_IO_PROTOCOL *PciIo;
  619. PCI_TYPE00 Pci;
  620. PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
  621. //
  622. // Check for all PCI device
  623. //
  624. Status = PciIo->Pci.Read (
  625. PciIo,
  626. EfiPciIoWidthUint32,
  627. 0,
  628. sizeof (Pci) / sizeof (UINT32),
  629. &Pci
  630. );
  631. if (EFI_ERROR (Status)) {
  632. return Status;
  633. }
  634. return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
  635. Handle,
  636. PciIo,
  637. &Pci
  638. );
  639. }
  640. EFI_STATUS
  641. VisitAllPciInstances (
  642. IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
  643. )
  644. {
  645. return VisitAllInstancesOfProtocol (
  646. &gEfiPciIoProtocolGuid,
  647. VisitingAPciInstance,
  648. (VOID*)(UINTN) CallBackFunction
  649. );
  650. }
  651. /**
  652. Do platform specific PCI Device check and add them to
  653. ConOut, ConIn, ErrOut.
  654. @param[in] Handle - Handle of PCI device instance
  655. @param[in] PciIo - PCI IO protocol instance
  656. @param[in] Pci - PCI Header register block
  657. @retval EFI_SUCCESS - PCI Device check and Console variable update
  658. successfully.
  659. @retval EFI_STATUS - PCI Device check or Console variable update fail.
  660. **/
  661. EFI_STATUS
  662. EFIAPI
  663. DetectAndPreparePlatformPciDevicePath (
  664. IN EFI_HANDLE Handle,
  665. IN EFI_PCI_IO_PROTOCOL *PciIo,
  666. IN PCI_TYPE00 *Pci
  667. )
  668. {
  669. EFI_STATUS Status;
  670. Status = PciIo->Attributes (
  671. PciIo,
  672. EfiPciIoAttributeOperationEnable,
  673. EFI_PCI_DEVICE_ENABLE,
  674. NULL
  675. );
  676. ASSERT_EFI_ERROR (Status);
  677. if (!mDetectVgaOnly) {
  678. //
  679. // Here we decide whether it is LPC Bridge
  680. //
  681. if ((IS_PCI_LPC (Pci)) ||
  682. ((IS_PCI_ISA_PDECODE (Pci)) &&
  683. (Pci->Hdr.VendorId == 0x8086) &&
  684. (Pci->Hdr.DeviceId == 0x7000)
  685. )
  686. ) {
  687. //
  688. // Add IsaKeyboard to ConIn,
  689. // add IsaSerial to ConOut, ConIn, ErrOut
  690. //
  691. DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));
  692. PrepareLpcBridgeDevicePath (Handle);
  693. return EFI_SUCCESS;
  694. }
  695. //
  696. // Here we decide which Serial device to enable in PCI bus
  697. //
  698. if (IS_PCI_16550SERIAL (Pci)) {
  699. //
  700. // Add them to ConOut, ConIn, ErrOut.
  701. //
  702. DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));
  703. PreparePciSerialDevicePath (Handle);
  704. return EFI_SUCCESS;
  705. }
  706. }
  707. //
  708. // Here we decide which display device to enable in PCI bus
  709. //
  710. if (IS_PCI_DISPLAY (Pci)) {
  711. //
  712. // Add them to ConOut.
  713. //
  714. DEBUG ((EFI_D_INFO, "Found PCI display device\n"));
  715. PreparePciDisplayDevicePath (Handle);
  716. return EFI_SUCCESS;
  717. }
  718. return Status;
  719. }
  720. /**
  721. Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
  722. @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
  723. @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
  724. @retval EFI_STATUS - PCI Device check or Console variable update fail.
  725. **/
  726. EFI_STATUS
  727. DetectAndPreparePlatformPciDevicePaths (
  728. BOOLEAN DetectVgaOnly
  729. )
  730. {
  731. mDetectVgaOnly = DetectVgaOnly;
  732. return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
  733. }
  734. /**
  735. Connect the predefined platform default console device.
  736. Always try to find and enable PCI display devices.
  737. @param[in] PlatformConsole Predefined platform default console device array.
  738. **/
  739. VOID
  740. PlatformInitializeConsole (
  741. IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole
  742. )
  743. {
  744. UINTN Index;
  745. EFI_DEVICE_PATH_PROTOCOL *VarConout;
  746. EFI_DEVICE_PATH_PROTOCOL *VarConin;
  747. //
  748. // Connect RootBridge
  749. //
  750. GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME, (VOID **) &VarConout, NULL);
  751. GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME, (VOID **) &VarConin, NULL);
  752. if (VarConout == NULL || VarConin == NULL) {
  753. //
  754. // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
  755. //
  756. DetectAndPreparePlatformPciDevicePaths (FALSE);
  757. DetectAndPreparePlatformPciDevicePaths(TRUE);
  758. //
  759. // Have chance to connect the platform default console,
  760. // the platform default console is the minimue device group
  761. // the platform should support
  762. //
  763. for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
  764. //
  765. // Update the console variable with the connect type
  766. //
  767. if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
  768. EfiBootManagerUpdateConsoleVariable (ConIn, PlatformConsole[Index].DevicePath, NULL);
  769. }
  770. if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
  771. EfiBootManagerUpdateConsoleVariable (ConOut, PlatformConsole[Index].DevicePath, NULL);
  772. }
  773. if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
  774. EfiBootManagerUpdateConsoleVariable (ErrOut, PlatformConsole[Index].DevicePath, NULL);
  775. }
  776. }
  777. } else {
  778. //
  779. // Only detect VGA device and add them to ConOut
  780. //
  781. DetectAndPreparePlatformPciDevicePaths (TRUE);
  782. }
  783. }
  784. /**
  785. Configure PCI Interrupt Line register for applicable devices
  786. Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
  787. @param[in] Handle - Handle of PCI device instance
  788. @param[in] PciIo - PCI IO protocol instance
  789. @param[in] PciHdr - PCI Header register block
  790. @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
  791. **/
  792. EFI_STATUS
  793. EFIAPI
  794. SetPciIntLine (
  795. IN EFI_HANDLE Handle,
  796. IN EFI_PCI_IO_PROTOCOL *PciIo,
  797. IN PCI_TYPE00 *PciHdr
  798. )
  799. {
  800. EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
  801. EFI_DEVICE_PATH_PROTOCOL *DevPath;
  802. UINTN RootSlot;
  803. UINTN Idx;
  804. UINT8 IrqLine;
  805. EFI_STATUS Status;
  806. UINT32 RootBusNumber;
  807. Status = EFI_SUCCESS;
  808. if (PciHdr->Device.InterruptPin != 0) {
  809. DevPathNode = DevicePathFromHandle (Handle);
  810. ASSERT (DevPathNode != NULL);
  811. DevPath = DevPathNode;
  812. RootBusNumber = 0;
  813. if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&
  814. DevicePathSubType (DevPathNode) == ACPI_DP &&
  815. ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {
  816. RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;
  817. }
  818. //
  819. // Compute index into PciHostIrqs[] table by walking
  820. // the device path and adding up all device numbers
  821. //
  822. Status = EFI_NOT_FOUND;
  823. RootSlot = 0;
  824. Idx = PciHdr->Device.InterruptPin - 1;
  825. while (!IsDevicePathEnd (DevPathNode)) {
  826. if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&
  827. DevicePathSubType (DevPathNode) == HW_PCI_DP) {
  828. Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;
  829. //
  830. // Unlike SeaBIOS, which starts climbing from the leaf device
  831. // up toward the root, we traverse the device path starting at
  832. // the root moving toward the leaf node.
  833. // The slot number of the top-level parent bridge is needed
  834. // with more than 24 slots on the root bus.
  835. //
  836. if (Status != EFI_SUCCESS) {
  837. Status = EFI_SUCCESS;
  838. RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;
  839. }
  840. }
  841. DevPathNode = NextDevicePathNode (DevPathNode);
  842. }
  843. if (EFI_ERROR (Status)) {
  844. return Status;
  845. }
  846. if (RootBusNumber == 0 && RootSlot == 0) {
  847. return Status; //bugbug: workaround; need SIMICS change B0/D0/F0 PCI_IntPin reg(0x3D) = 0X0
  848. // DEBUG((
  849. // EFI_D_ERROR,
  850. // "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
  851. // __FUNCTION__
  852. // ));
  853. // ASSERT (FALSE);
  854. }
  855. //
  856. // Final PciHostIrqs[] index calculation depends on the platform
  857. // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
  858. //
  859. switch (mHostBridgeDevId) {
  860. case INTEL_82441_DEVICE_ID:
  861. Idx -= 1;
  862. break;
  863. case INTEL_ICH10_DEVICE_ID:
  864. //
  865. // SeaBIOS contains the following comment:
  866. // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
  867. // with a different starting index.
  868. //
  869. // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
  870. //
  871. if (RootSlot > 24) {
  872. //
  873. // in this case, subtract back out RootSlot from Idx
  874. // (SeaBIOS never adds it to begin with, but that would make our
  875. // device path traversal loop above too awkward)
  876. //
  877. Idx -= RootSlot;
  878. }
  879. break;
  880. default:
  881. ASSERT (FALSE); // should never get here
  882. }
  883. Idx %= ARRAY_SIZE (PciHostIrqs);
  884. IrqLine = PciHostIrqs[Idx];
  885. DEBUG_CODE_BEGIN ();
  886. {
  887. CHAR16 *DevPathString;
  888. STATIC CHAR16 Fallback[] = L"<failed to convert>";
  889. UINTN Segment, Bus, Device, Function;
  890. DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);
  891. if (DevPathString == NULL) {
  892. DevPathString = Fallback;
  893. }
  894. Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
  895. ASSERT_EFI_ERROR (Status);
  896. DEBUG ((EFI_D_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,
  897. (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,
  898. IrqLine));
  899. if (DevPathString != Fallback) {
  900. FreePool (DevPathString);
  901. }
  902. }
  903. DEBUG_CODE_END ();
  904. //
  905. // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
  906. //
  907. Status = PciIo->Pci.Write (
  908. PciIo,
  909. EfiPciIoWidthUint8,
  910. PCI_INT_LINE_OFFSET,
  911. 1,
  912. &IrqLine
  913. );
  914. }
  915. return Status;
  916. }
  917. /**
  918. Write to mask and edge/level triggered registers of master and slave 8259 PICs.
  919. @param[in] Mask low byte for master PIC mask register,
  920. high byte for slave PIC mask register.
  921. @param[in] EdgeLevel low byte for master PIC edge/level triggered register,
  922. high byte for slave PIC edge/level triggered register.
  923. **/
  924. VOID
  925. Interrupt8259WriteMask(
  926. IN UINT16 Mask,
  927. IN UINT16 EdgeLevel
  928. )
  929. {
  930. IoWrite8(LEGACY_8259_MASK_REGISTER_MASTER, (UINT8)Mask);
  931. IoWrite8(LEGACY_8259_MASK_REGISTER_SLAVE, (UINT8)(Mask >> 8));
  932. IoWrite8(LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_MASTER, (UINT8)EdgeLevel);
  933. IoWrite8(LEGACY_8259_EDGE_LEVEL_TRIGGERED_REGISTER_SLAVE, (UINT8)(EdgeLevel >> 8));
  934. }
  935. VOID
  936. PciAcpiInitialization (
  937. )
  938. {
  939. UINTN Pmba;
  940. //
  941. // Query Host Bridge DID to determine platform type
  942. //
  943. mHostBridgeDevId = PcdGet16 (PcdSimicsX58HostBridgePciDevId);
  944. switch (mHostBridgeDevId) {
  945. case INTEL_82441_DEVICE_ID:
  946. Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
  947. //
  948. // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
  949. //
  950. PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
  951. PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
  952. PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
  953. PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
  954. break;
  955. case INTEL_ICH10_DEVICE_ID:
  956. Pmba = POWER_MGMT_REGISTER_ICH10 (ICH10_PMBASE);
  957. //
  958. // 00:1f.0 LPC Bridge LNK routing targets
  959. //
  960. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
  961. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
  962. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
  963. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
  964. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
  965. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
  966. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
  967. PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
  968. break;
  969. default:
  970. DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
  971. __FUNCTION__, mHostBridgeDevId));
  972. ASSERT (FALSE);
  973. return;
  974. }
  975. //
  976. // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
  977. //
  978. VisitAllPciInstances (SetPciIntLine);
  979. //
  980. // Set ACPI SCI_EN bit in PMCNTRL
  981. //
  982. IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
  983. //
  984. // Set all 8259 interrupts to edge triggered and disabled
  985. //
  986. Interrupt8259WriteMask(0xFFFF, 0x0000);
  987. }
  988. EFI_STATUS
  989. EFIAPI
  990. ConnectRecursivelyIfPciMassStorage (
  991. IN EFI_HANDLE Handle,
  992. IN EFI_PCI_IO_PROTOCOL *Instance,
  993. IN PCI_TYPE00 *PciHeader
  994. )
  995. {
  996. EFI_STATUS Status;
  997. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  998. CHAR16 *DevPathStr;
  999. //
  1000. // Recognize PCI Mass Storage
  1001. //
  1002. if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
  1003. DevicePath = NULL;
  1004. Status = gBS->HandleProtocol (
  1005. Handle,
  1006. &gEfiDevicePathProtocolGuid,
  1007. (VOID*)&DevicePath
  1008. );
  1009. if (EFI_ERROR (Status)) {
  1010. return Status;
  1011. }
  1012. //
  1013. // Print Device Path
  1014. //
  1015. DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
  1016. if (DevPathStr != NULL) {
  1017. DEBUG((
  1018. EFI_D_INFO,
  1019. "Found Mass Storage device: %s\n",
  1020. DevPathStr
  1021. ));
  1022. FreePool(DevPathStr);
  1023. }
  1024. Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
  1025. if (EFI_ERROR (Status)) {
  1026. return Status;
  1027. }
  1028. }
  1029. return EFI_SUCCESS;
  1030. }
  1031. /**
  1032. This notification function is invoked when the
  1033. EMU Variable FVB has been changed.
  1034. @param Event The event that occurred
  1035. @param Context For EFI compatibility. Not used.
  1036. **/
  1037. VOID
  1038. EFIAPI
  1039. EmuVariablesUpdatedCallback (
  1040. IN EFI_EVENT Event,
  1041. IN VOID *Context
  1042. )
  1043. {
  1044. DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));
  1045. UpdateNvVarsOnFileSystem ();
  1046. }
  1047. EFI_STATUS
  1048. EFIAPI
  1049. VisitingFileSystemInstance (
  1050. IN EFI_HANDLE Handle,
  1051. IN VOID *Instance,
  1052. IN VOID *Context
  1053. )
  1054. {
  1055. EFI_STATUS Status;
  1056. STATIC BOOLEAN ConnectedToFileSystem = FALSE;
  1057. if (ConnectedToFileSystem) {
  1058. return EFI_ALREADY_STARTED;
  1059. }
  1060. Status = ConnectNvVarsToFileSystem (Handle);
  1061. if (EFI_ERROR (Status)) {
  1062. return Status;
  1063. }
  1064. ConnectedToFileSystem = TRUE;
  1065. mEmuVariableEvent =
  1066. EfiCreateProtocolNotifyEvent (
  1067. &gEfiDevicePathProtocolGuid,
  1068. TPL_CALLBACK,
  1069. EmuVariablesUpdatedCallback,
  1070. NULL,
  1071. &mEmuVariableEventReg
  1072. );
  1073. PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);
  1074. return EFI_SUCCESS;
  1075. }
  1076. VOID
  1077. PlatformBdsRestoreNvVarsFromHardDisk (
  1078. )
  1079. {
  1080. VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
  1081. VisitAllInstancesOfProtocol (
  1082. &gEfiSimpleFileSystemProtocolGuid,
  1083. VisitingFileSystemInstance,
  1084. NULL
  1085. );
  1086. }
  1087. /**
  1088. Connect with predefined platform connect sequence.
  1089. The OEM/IBV can customize with their own connect sequence.
  1090. **/
  1091. VOID
  1092. PlatformBdsConnectSequence (
  1093. VOID
  1094. )
  1095. {
  1096. UINTN Index;
  1097. DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
  1098. Index = 0;
  1099. //
  1100. // Here we can get the customized platform connect sequence
  1101. // Notes: we can connect with new variable which record the
  1102. // last time boots connect device path sequence
  1103. //
  1104. while (gPlatformConnectSequence[Index] != NULL) {
  1105. //
  1106. // Build the platform boot option
  1107. //
  1108. EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL);
  1109. Index++;
  1110. }
  1111. //
  1112. // Just use the simple policy to connect all devices
  1113. //
  1114. DEBUG ((EFI_D_INFO, "EfiBootManagerConnectAll\n"));
  1115. EfiBootManagerConnectAll ();
  1116. PciAcpiInitialization ();
  1117. }
  1118. /**
  1119. Save the S3 boot script.
  1120. Note that DxeSmmReadyToLock must be signaled after this function returns;
  1121. otherwise the script wouldn't be saved actually.
  1122. **/
  1123. STATIC
  1124. VOID
  1125. SaveS3BootScript (
  1126. VOID
  1127. )
  1128. {
  1129. EFI_STATUS Status;
  1130. EFI_S3_SAVE_STATE_PROTOCOL *BootScript;
  1131. STATIC CONST UINT8 Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };
  1132. Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL,
  1133. (VOID **) &BootScript);
  1134. ASSERT_EFI_ERROR (Status);
  1135. //
  1136. // Despite the opcode documentation in the PI spec, the protocol
  1137. // implementation embeds a deep copy of the info in the boot script, rather
  1138. // than storing just a pointer to runtime or NVS storage.
  1139. //
  1140. Status = BootScript->Write(BootScript, EFI_BOOT_SCRIPT_INFORMATION_OPCODE,
  1141. (UINT32) sizeof Info,
  1142. (EFI_PHYSICAL_ADDRESS)(UINTN) &Info);
  1143. ASSERT_EFI_ERROR (Status);
  1144. }
  1145. /**
  1146. Do the platform specific action after the console is ready
  1147. Possible things that can be done in PlatformBootManagerAfterConsole:
  1148. > Console post action:
  1149. > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
  1150. > Signal console ready platform customized event
  1151. > Run diagnostics like memory testing
  1152. > Connect certain devices
  1153. > Dispatch aditional option roms
  1154. > Special boot: e.g.: USB boot, enter UI
  1155. **/
  1156. VOID
  1157. EFIAPI
  1158. PlatformBootManagerAfterConsole (
  1159. VOID
  1160. )
  1161. {
  1162. EFI_BOOT_MODE BootMode;
  1163. EFI_HANDLE Handle;
  1164. EFI_STATUS Status;
  1165. DEBUG ((EFI_D_INFO, "PlatformBootManagerAfterConsole\n"));
  1166. //
  1167. // Prevent further changes to LockBoxes or SMRAM.
  1168. //
  1169. Handle = NULL;
  1170. Status = gBS->InstallProtocolInterface(&Handle,
  1171. &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,
  1172. NULL);
  1173. ASSERT_EFI_ERROR(Status);
  1174. if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
  1175. DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "
  1176. "from disk since flash variables appear to be supported.\n"));
  1177. } else {
  1178. //
  1179. // Try to restore variables from the hard disk early so
  1180. // they can be used for the other BDS connect operations.
  1181. //
  1182. PlatformBdsRestoreNvVarsFromHardDisk ();
  1183. }
  1184. //
  1185. // Get current Boot Mode
  1186. //
  1187. BootMode = GetBootModeHob ();
  1188. DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
  1189. //
  1190. // Go the different platform policy with different boot mode
  1191. // Notes: this part code can be change with the table policy
  1192. //
  1193. ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
  1194. // Perform some platform specific connect sequence
  1195. //
  1196. PlatformBdsConnectSequence ();
  1197. //
  1198. // Logo show
  1199. //
  1200. EnableBootLogo(PcdGetPtr(PcdLogoFile));
  1201. EfiBootManagerRefreshAllBootOption ();
  1202. //
  1203. // Register UEFI Shell
  1204. //
  1205. PlatformRegisterFvBootOption (
  1206. PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE
  1207. );
  1208. RemoveStaleFvFileOptions ();
  1209. }
  1210. /**
  1211. This notification function is invoked when an instance of the
  1212. EFI_DEVICE_PATH_PROTOCOL is produced.
  1213. @param Event The event that occurred
  1214. @param Context For EFI compatibility. Not used.
  1215. **/
  1216. VOID
  1217. EFIAPI
  1218. NotifyDevPath (
  1219. IN EFI_EVENT Event,
  1220. IN VOID *Context
  1221. )
  1222. {
  1223. EFI_HANDLE Handle;
  1224. EFI_STATUS Status;
  1225. UINTN BufferSize;
  1226. EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
  1227. ATAPI_DEVICE_PATH *Atapi;
  1228. //
  1229. // Examine all new handles
  1230. //
  1231. for (;;) {
  1232. //
  1233. // Get the next handle
  1234. //
  1235. BufferSize = sizeof (Handle);
  1236. Status = gBS->LocateHandle (
  1237. ByRegisterNotify,
  1238. NULL,
  1239. mEfiDevPathNotifyReg,
  1240. &BufferSize,
  1241. &Handle
  1242. );
  1243. //
  1244. // If not found, we're done
  1245. //
  1246. if (EFI_NOT_FOUND == Status) {
  1247. break;
  1248. }
  1249. if (EFI_ERROR (Status)) {
  1250. continue;
  1251. }
  1252. //
  1253. // Get the DevicePath protocol on that handle
  1254. //
  1255. Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
  1256. ASSERT_EFI_ERROR (Status);
  1257. while (!IsDevicePathEnd (DevPathNode)) {
  1258. //
  1259. // Find the handler to dump this device path node
  1260. //
  1261. if (
  1262. (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
  1263. (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
  1264. ) {
  1265. Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
  1266. PciOr16 (
  1267. PCI_LIB_ADDRESS (
  1268. 0,
  1269. 1,
  1270. 1,
  1271. (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
  1272. ),
  1273. BIT15
  1274. );
  1275. }
  1276. //
  1277. // Next device path node
  1278. //
  1279. DevPathNode = NextDevicePathNode (DevPathNode);
  1280. }
  1281. }
  1282. return;
  1283. }
  1284. VOID
  1285. InstallDevicePathCallback (
  1286. VOID
  1287. )
  1288. {
  1289. DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));
  1290. mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
  1291. &gEfiDevicePathProtocolGuid,
  1292. TPL_CALLBACK,
  1293. NotifyDevPath,
  1294. NULL,
  1295. &mEfiDevPathNotifyReg
  1296. );
  1297. }
  1298. /**
  1299. This function is called each second during the boot manager waits the
  1300. timeout.
  1301. @param TimeoutRemain The remaining timeout.
  1302. **/
  1303. VOID
  1304. EFIAPI
  1305. PlatformBootManagerWaitCallback (
  1306. UINT16 TimeoutRemain
  1307. )
  1308. {
  1309. EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;
  1310. EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;
  1311. UINT16 Timeout;
  1312. Timeout = PcdGet16 (PcdPlatformBootTimeOut);
  1313. Black.Raw = 0x00000000;
  1314. White.Raw = 0x00FFFFFF;
  1315. BootLogoUpdateProgress (
  1316. White.Pixel,
  1317. Black.Pixel,
  1318. L"Start boot option",
  1319. White.Pixel,
  1320. (Timeout - TimeoutRemain) * 100 / Timeout,
  1321. 0
  1322. );
  1323. }
  1324. /**
  1325. The function is called when no boot option could be launched,
  1326. including platform recovery options and options pointing to applications
  1327. built into firmware volumes.
  1328. If this function returns, BDS attempts to enter an infinite loop.
  1329. **/
  1330. VOID
  1331. EFIAPI
  1332. PlatformBootManagerUnableToBoot (
  1333. VOID
  1334. )
  1335. {
  1336. // BUGBUG- will do it if need
  1337. }