X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=OvmfPkg%2FLibrary%2FPlatformBdsLib%2FBdsPlatform.c;h=f2ece66817d54c35041138c4e1714aeca7bcbb7b;hp=44fd0d7ed5dc874b623a7112507df4d783b9b65c;hb=5126ef789dd31312fa6722f9c9b77a9d7700371d;hpb=24cdd14e81bc867dfc0ed05fd6d22d4a49858adb diff --git a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c index 44fd0d7ed5..f2ece66817 100644 --- a/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c +++ b/OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c @@ -1,8 +1,8 @@ /** @file Platform BDS customizations. - Copyright (c) 2004 - 2008, Intel Corporation.
- All rights reserved. This program and the accompanying materials + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php @@ -13,6 +13,7 @@ **/ #include "BdsPlatform.h" +#include "QemuBootOrder.h" // @@ -21,18 +22,58 @@ VOID *mEfiDevPathNotifyReg; EFI_EVENT mEfiDevPathEvent; +VOID *mEmuVariableEventReg; +EFI_EVENT mEmuVariableEvent; +BOOLEAN mDetectVgaOnly; + + +// +// Type definitions +// + +typedef +EFI_STATUS +(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)( + IN EFI_HANDLE Handle, + IN VOID *Instance, + IN VOID *Context + ); + +/** + @param[in] Handle - Handle of PCI device instance + @param[in] PciIo - PCI IO protocol instance + @param[in] Pci - PCI Header register block +**/ +typedef +EFI_STATUS +(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)( + IN EFI_HANDLE Handle, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN PCI_TYPE00 *Pci + ); // // Function prototypes // +EFI_STATUS +VisitAllInstancesOfProtocol ( + IN EFI_GUID *Id, + IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction, + IN VOID *Context + ); + +EFI_STATUS +VisitAllPciInstancesOfProtocol ( + IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction + ); + VOID InstallDevicePathCallback ( VOID ); - // // BDS Platform Functions // @@ -168,14 +209,16 @@ Returns: // Print Device Path // DevPathStr = DevicePathToStr(DevicePath); - DEBUG(( - EFI_D_INFO, - "BdsPlatform.c+%d: COM%d DevPath: %s\n", - __LINE__, - gPnp16550ComPortDeviceNode.UID + 1, - DevPathStr - )); - FreePool(DevPathStr); + if (DevPathStr != NULL) { + DEBUG(( + EFI_D_INFO, + "BdsPlatform.c+%d: COM%d DevPath: %s\n", + __LINE__, + gPnp16550ComPortDeviceNode.UID + 1, + DevPathStr + )); + FreePool(DevPathStr); + } BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); @@ -195,14 +238,16 @@ Returns: // Print Device Path // DevPathStr = DevicePathToStr(DevicePath); - DEBUG(( - EFI_D_INFO, - "BdsPlatform.c+%d: COM%d DevPath: %s\n", - __LINE__, - gPnp16550ComPortDeviceNode.UID + 1, - DevPathStr - )); - FreePool(DevPathStr); + if (DevPathStr != NULL) { + DEBUG(( + EFI_D_INFO, + "BdsPlatform.c+%d: COM%d DevPath: %s\n", + __LINE__, + gPnp16550ComPortDeviceNode.UID + 1, + DevPathStr + )); + FreePool(DevPathStr); + } BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); @@ -322,7 +367,8 @@ Returns: EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *GopDevicePath; - DevicePath = NULL; + DevicePath = NULL; + GopDevicePath = NULL; Status = gBS->HandleProtocol ( DeviceHandle, &gEfiDevicePathProtocolGuid, @@ -386,32 +432,17 @@ Returns: } EFI_STATUS -DetectAndPreparePlatformPciDevicePath ( - BOOLEAN DetectVgaOnly +VisitAllInstancesOfProtocol ( + IN EFI_GUID *Id, + IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction, + IN VOID *Context ) -/*++ - -Routine Description: - - Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut - -Arguments: - - DetectVgaOnly - Only detect VGA device if it's TRUE. - -Returns: - - EFI_SUCCESS - PCI Device check and Console variable update successfully. - EFI_STATUS - PCI Device check or Console variable update fail. - ---*/ { EFI_STATUS Status; UINTN HandleCount; EFI_HANDLE *HandleBuffer; UINTN Index; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE00 Pci; + VOID *Instance; // // Start to check all the PciIo to find all possible device @@ -420,7 +451,7 @@ Returns: HandleBuffer = NULL; Status = gBS->LocateHandleBuffer ( ByProtocol, - &gEfiPciIoProtocolGuid, + Id, NULL, &HandleCount, &HandleBuffer @@ -430,89 +461,168 @@ Returns: } for (Index = 0; Index < HandleCount; Index++) { - Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID*)&PciIo); + Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance); if (EFI_ERROR (Status)) { continue; } + Status = (*CallBackFunction) ( + HandleBuffer[Index], + Instance, + Context + ); + } + + gBS->FreePool (HandleBuffer); + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +VisitingAPciInstance ( + IN EFI_HANDLE Handle, + IN VOID *Instance, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + PciIo = (EFI_PCI_IO_PROTOCOL*) Instance; + + // + // Check for all PCI device + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) ( + Handle, + PciIo, + &Pci + ); + +} + + + +EFI_STATUS +VisitAllPciInstances ( + IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction + ) +{ + return VisitAllInstancesOfProtocol ( + &gEfiPciIoProtocolGuid, + VisitingAPciInstance, + (VOID*)(UINTN) CallBackFunction + ); +} + + +/** + Do platform specific PCI Device check and add them to + ConOut, ConIn, ErrOut. + + @param[in] Handle - Handle of PCI device instance + @param[in] PciIo - PCI IO protocol instance + @param[in] Pci - PCI Header register block + + @retval EFI_SUCCESS - PCI Device check and Console variable update successfully. + @retval EFI_STATUS - PCI Device check or Console variable update fail. + +**/ +EFI_STATUS +EFIAPI +DetectAndPreparePlatformPciDevicePath ( + IN EFI_HANDLE Handle, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN PCI_TYPE00 *Pci + ) +{ + EFI_STATUS Status; + + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + ASSERT_EFI_ERROR (Status); + + if (!mDetectVgaOnly) { // - // Check for all PCI device + // Here we decide whether it is LPC Bridge // - Status = PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, - sizeof (Pci) / sizeof (UINT32), - &Pci - ); - if (EFI_ERROR (Status)) { - continue; - } - - if (!DetectVgaOnly) { - // - // Here we decide whether it is LPC Bridge - // - if ((IS_PCI_LPC (&Pci)) || - ((IS_PCI_ISA_PDECODE (&Pci)) && - (Pci.Hdr.VendorId == 0x8086) && - (Pci.Hdr.DeviceId == 0x7000) - ) - ) { - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationEnable, - EFI_PCI_DEVICE_ENABLE, - NULL - ); - // - // Add IsaKeyboard to ConIn, - // add IsaSerial to ConOut, ConIn, ErrOut - // - DEBUG ((EFI_D_INFO, "Find the LPC Bridge device\n")); - PrepareLpcBridgeDevicePath (HandleBuffer[Index]); - continue; - } + if ((IS_PCI_LPC (Pci)) || + ((IS_PCI_ISA_PDECODE (Pci)) && + (Pci->Hdr.VendorId == 0x8086) && + (Pci->Hdr.DeviceId == 0x7000) + ) + ) { // - // Here we decide which Serial device to enable in PCI bus + // Add IsaKeyboard to ConIn, + // add IsaSerial to ConOut, ConIn, ErrOut // - if (IS_PCI_16550SERIAL (&Pci)) { - // - // Add them to ConOut, ConIn, ErrOut. - // - DEBUG ((EFI_D_INFO, "Find the 16550 SERIAL device\n")); - PreparePciSerialDevicePath (HandleBuffer[Index]); - continue; - } + DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n")); + PrepareLpcBridgeDevicePath (Handle); + return EFI_SUCCESS; } - - if ((Pci.Hdr.VendorId == 0x8086) && - (Pci.Hdr.DeviceId == 0x7010) - ) { - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationEnable, - EFI_PCI_DEVICE_ENABLE, - NULL - ); - } - // - // Here we decide which VGA device to enable in PCI bus + // Here we decide which Serial device to enable in PCI bus // - if (IS_PCI_VGA (&Pci)) { + if (IS_PCI_16550SERIAL (Pci)) { // - // Add them to ConOut. + // Add them to ConOut, ConIn, ErrOut. // - DEBUG ((EFI_D_INFO, "Find the VGA device\n")); - PreparePciVgaDevicePath (HandleBuffer[Index]); - continue; + DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n")); + PreparePciSerialDevicePath (Handle); + return EFI_SUCCESS; } } - gBS->FreePool (HandleBuffer); + // + // Here we decide which VGA device to enable in PCI bus + // + if (IS_PCI_VGA (Pci)) { + // + // Add them to ConOut. + // + DEBUG ((EFI_D_INFO, "Found PCI VGA device\n")); + PreparePciVgaDevicePath (Handle); + return EFI_SUCCESS; + } - return EFI_SUCCESS; + return Status; +} + + +/** + Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut + + @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE. + + @retval EFI_SUCCESS - PCI Device check and Console variable update successfully. + @retval EFI_STATUS - PCI Device check or Console variable update fail. + +**/ +EFI_STATUS +DetectAndPreparePlatformPciDevicePaths ( + BOOLEAN DetectVgaOnly + ) +{ + mDetectVgaOnly = DetectVgaOnly; + return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath); } @@ -551,8 +661,6 @@ Returns: // // Connect RootBridge // - ConnectRootBridge (); - VarConout = BdsLibGetVariableAndSize ( VarConsoleOut, &gEfiGlobalVariableGuid, @@ -568,7 +676,7 @@ Returns: // // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut // - DetectAndPreparePlatformPciDevicePath (FALSE); + DetectAndPreparePlatformPciDevicePaths (FALSE); // // Have chance to connect the platform default console, @@ -593,7 +701,7 @@ Returns: // // Only detect VGA device and add them to ConOut // - DetectAndPreparePlatformPciDevicePath (TRUE); + DetectAndPreparePlatformPciDevicePaths (TRUE); } // @@ -621,10 +729,10 @@ PciInitialization ( // Bus 0, Device 1, Function 0 - PCI to ISA Bridge // PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00); - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x09); - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0b); - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x09); + PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // LNKA routing target + PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // LNKB routing target + PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // LNKC routing target + PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // LNKD routing target // // Bus 0, Device 1, Function 1 - IDE Controller @@ -635,8 +743,8 @@ PciInitialization ( // // Bus 0, Device 1, Function 3 - Power Managment Controller // - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x0b); - PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3d), 0x01); + PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x09); + PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3d), 0x01); // INTA // // Bus 0, Device 2, Function 0 - Video Controller @@ -646,14 +754,142 @@ PciInitialization ( // // Bus 0, Device 3, Function 0 - Network Controller // - PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0b); - PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3d), 0x01); + PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0a); + PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3d), 0x01); // INTA (-> LNKC) // - // Bus 0, Device 4, Function 0 - RAM Memory + // Bus 0, Device 5, Function 0 - RAM Memory // - PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3c), 0x09); - PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3d), 0x01); + PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3c), 0x0b); + PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3d), 0x01); // INTA (-> LNKA) +} + + +VOID +AcpiInitialization ( + VOID + ) +{ + // + // Set ACPI SCI_EN bit in PMCNTRL + // + IoOr16 ((PciRead32 (PCI_LIB_ADDRESS (0, 1, 3, 0x40)) & ~BIT0) + 4, BIT0); +} + + +EFI_STATUS +EFIAPI +ConnectRecursivelyIfPciMassStorage ( + IN EFI_HANDLE Handle, + IN EFI_PCI_IO_PROTOCOL *Instance, + IN PCI_TYPE00 *PciHeader + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + CHAR16 *DevPathStr; + + if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) { + DevicePath = NULL; + Status = gBS->HandleProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID*)&DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Print Device Path + // + DevPathStr = DevicePathToStr (DevicePath); + if (DevPathStr != NULL) { + DEBUG(( + EFI_D_INFO, + "Found Mass Storage device: %s\n", + DevPathStr + )); + FreePool(DevPathStr); + } + + Status = gBS->ConnectController (Handle, NULL, NULL, TRUE); + if (EFI_ERROR (Status)) { + return Status; + } + + } + + return EFI_SUCCESS; +} + + +/** + This notification function is invoked when the + EMU Variable FVB has been changed. + + @param Event The event that occured + @param Context For EFI compatiblity. Not used. + +**/ +VOID +EFIAPI +EmuVariablesUpdatedCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n")); + UpdateNvVarsOnFileSystem (); +} + + +EFI_STATUS +EFIAPI +VisitingFileSystemInstance ( + IN EFI_HANDLE Handle, + IN VOID *Instance, + IN VOID *Context + ) +{ + EFI_STATUS Status; + STATIC BOOLEAN ConnectedToFileSystem = FALSE; + + if (ConnectedToFileSystem) { + return EFI_ALREADY_STARTED; + } + + Status = ConnectNvVarsToFileSystem (Handle); + if (EFI_ERROR (Status)) { + return Status; + } + + ConnectedToFileSystem = TRUE; + mEmuVariableEvent = + EfiCreateProtocolNotifyEvent ( + &gEfiDevicePathProtocolGuid, + TPL_CALLBACK, + EmuVariablesUpdatedCallback, + NULL, + &mEmuVariableEventReg + ); + PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent); + + return EFI_SUCCESS; +} + + +VOID +PlatformBdsRestoreNvVarsFromHardDisk ( + ) +{ + VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage); + VisitAllInstancesOfProtocol ( + &gEfiSimpleFileSystemProtocolGuid, + VisitingFileSystemInstance, + NULL + ); + } @@ -703,6 +939,7 @@ Returns: BdsLibConnectAll (); PciInitialization (); + AcpiInitialization (); // // Clear the logo after all devices are connected. @@ -738,7 +975,8 @@ Returns: VOID PlatformBdsDiagnostics ( IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel, - IN BOOLEAN QuietBoot + IN BOOLEAN QuietBoot, + IN BASEM_MEMORY_TEST BaseMemoryTest ) /*++ @@ -753,6 +991,8 @@ Arguments: QuietBoot - Indicate if need to enable the quiet boot + BaseMemoryTest - A pointer to BaseMemoryTest() + Returns: None. @@ -774,7 +1014,7 @@ Returns: // // Perform system diagnostic // - Status = BdsMemoryTest (MemoryTestLevel); + Status = BaseMemoryTest (MemoryTestLevel); if (EFI_ERROR (Status)) { DisableQuietBoot (); } @@ -784,7 +1024,7 @@ Returns: // // Perform system diagnostic // - Status = BdsMemoryTest (MemoryTestLevel); + Status = BaseMemoryTest (MemoryTestLevel); } @@ -792,7 +1032,9 @@ VOID EFIAPI PlatformBdsPolicyBehavior ( IN OUT LIST_ENTRY *DriverOptionList, - IN OUT LIST_ENTRY *BootOptionList + IN OUT LIST_ENTRY *BootOptionList, + IN PROCESS_CAPSULES ProcessCapsules, + IN BASEM_MEMORY_TEST BaseMemoryTest ) /*++ @@ -808,6 +1050,10 @@ Arguments: BootOptionList - The header of the boot option link list + ProcessCapsules - A pointer to ProcessCapsules() + + BaseMemoryTest - A pointer to BaseMemoryTest() + Returns: None. @@ -826,6 +1072,19 @@ Returns: DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n")); + ConnectRootBridge (); + + if (PcdGetBool (PcdOvmfFlashVariablesEnable)) { + DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars " + "from disk since flash variables appear to be supported.\n")); + } else { + // + // Try to restore variables from the hard disk early so + // they can be used for the other BDS connect operations. + // + PlatformBdsRestoreNvVarsFromHardDisk (); + } + // // Init the time out value // @@ -873,7 +1132,7 @@ Returns: // // Memory test and Logo show // - PlatformBdsDiagnostics (IGNORE, TRUE); + PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest); // // Perform some platform specific connect sequence @@ -881,35 +1140,20 @@ Returns: PlatformBdsConnectSequence (); // - // Give one chance to enter the setup if we - // have the time out + // Process QEMU's -kernel command line option // - if (Timeout != 0) { - //PlatformBdsEnterFrontPage (Timeout, FALSE); - } + TryRunningQemuKernel (); DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n")); BdsLibConnectAll (); BdsLibEnumerateAllBootOption (BootOptionList); + SetBootOrderFromQemu (BootOptionList); // - // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot - // checking code in real production tip. + // The BootOrder variable may have changed, reload the in-memory list with + // it. // - // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device - // and do enumerate all the default boot options. But in development system board, the boot mode - // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box - // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot. - // - Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); - if (EFI_ERROR(Status)) { - // - // If cannot find "BootOrder" variable, it may be first boot. - // Try to connect all devices and enumerate all boot options here. - // - BdsLibConnectAll (); - BdsLibEnumerateAllBootOption (BootOptionList); - } + BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); // // To give the User a chance to enter Setup here, if user set TimeOut is 0. @@ -949,11 +1193,8 @@ Returns: // // Enter Setup if user input // - Timeout = 0xffff; PlatformBdsEnterFrontPage (Timeout, FALSE); } - - return ; } VOID @@ -1194,3 +1435,4 @@ LockKeyboards ( { return EFI_UNSUPPORTED; } +