From nobody Thu Apr 25 20:18:32 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+40649+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40649+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1557908873; cv=none; d=zoho.com; s=zohoarc; b=hffBfYzL5eVgyoHeq0sFkAkPLR4KAjWX2yD5NNmekOW7aWCzevcrYiCcGw63dwmtqYJ21ZxuPAQNYKRpFYTktiItpQEnfZ7OFM77rHF6CnhKrCGnOL7KbI/Li1zBQPFkzkrAz1yLqPpgfvHEF854JTbtWlrwg6iOxsU6p32EoxM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1557908873; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=SGT8RYMg0Y8RxWVNtROgIjj0v2/SVeIx6Y9tUuWYHPQ=; b=TfDBDTPJB1S/YBy3Gb4kjzSL9UGwxMUDa/SdTos6mlSqshacJsE8cwLsDndSfEH8SW2WX2GOvGT0BxyEgIooh3zLDho5qSDWQEVRfu7QFBoHW83alHwFDdvsIeg66nlKBhOhbmpXuIDK1RlmmImAdpiXRD8IOI4AFoGttm7q6vk= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40649+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1557908873175533.3827475541842; Wed, 15 May 2019 01:27:53 -0700 (PDT) Return-Path: X-Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by groups.io with SMTP; Wed, 15 May 2019 01:27:49 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 May 2019 01:27:47 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by orsmga005.jf.intel.com with ESMTP; 15 May 2019 01:27:27 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , Ray Ni , David Woodhouse , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v1 1/9] OvmfPkg: Copy the required CSM components from framework packages Date: Wed, 15 May 2019 16:27:12 +0800 Message-Id: <20190515082720.12560-2-hao.a.wu@intel.com> In-Reply-To: <20190515082720.12560-1-hao.a.wu@intel.com> References: <20190515082720.12560-1-hao.a.wu@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,hao.a.wu@intel.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1557908871; bh=FiBru8H5TgqatcbHKvARLP/cpgxUJpOdFKoIuiaAokY=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=aAkPuD9yXNNIY2kWmrI5WfUgyxRIehDVE0x2fzPbdxTtF3+MB4eOgiRQnmbMx63duIt dt1M40wu2zkQH0nyCdNI1FUhWlve/WllnkaZUy0l07Vd36PD8AwXHap2oNhjh8rV/kj4Q LKk/H4uExMoJXasSjHDblvc+/lbu+op3uws= X-ZohoMail-DKIM: pass (identity @groups.io) REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1811 This commit copies the exact: Drivers: * VideoDxe * LegacyBiosDxe Libraries: * LegacyBootMaintUiLib * LegacyBootManagerLib Guid header files: * Legacy Bios Guid * LegacyDevOrder Guid Protocol header files: * Firmware Volume Protocol * ISA ACPI Protocol * ISA I/O Protocol * Legacy BIOS Protocol * Legacy BIOS Platform Protocol * Legacy Interrupt Protocol * VGA Mini Port Protocol Framework header files (within IntelFrameworkPkg): * FrameworkDxe.h * Framework/BootScript.h * Framework/DxeCis.h * Framework/FirmwareVolumeHeader.h * Framework/FirmwareVolumeImageFormat.h * Framework/FrameworkInternalFormRepresentation.h * Framework/Hob.h * Framework/StatusCode.h from IntelFramework[Module]Pkg to OvmfPkg/Csm/ folder. Cc: Ray Ni Cc: David Woodhouse Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu --- OvmfPkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf | 80= + OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf | 131= + OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf | 63= + OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf | 58= + OvmfPkg/Csm/BiosThunk/VideoDxe/BiosVideo.h | 532= ++++ OvmfPkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h | 459= +++ OvmfPkg/Csm/Include/Framework/BootScript.h | 41= + OvmfPkg/Csm/Include/Framework/DxeCis.h | 170= + OvmfPkg/Csm/Include/Framework/FirmwareVolumeHeader.h | 79= + OvmfPkg/Csm/Include/Framework/FirmwareVolumeImageFormat.h | 32= + OvmfPkg/Csm/Include/Framework/FrameworkInternalFormRepresentation.h | 397= +++ OvmfPkg/Csm/Include/Framework/Hob.h | 28= + OvmfPkg/Csm/Include/Framework/StatusCode.h | 155= + OvmfPkg/Csm/Include/FrameworkDxe.h | 26= + OvmfPkg/Csm/Include/Guid/LegacyBios.h | 29= + OvmfPkg/Csm/Include/Guid/LegacyDevOrder.h | 39= + OvmfPkg/Csm/Include/Protocol/FirmwareVolume.h | 340= ++ OvmfPkg/Csm/Include/Protocol/IsaAcpi.h | 298= ++ OvmfPkg/Csm/Include/Protocol/IsaIo.h | 356= +++ OvmfPkg/Csm/Include/Protocol/LegacyBios.h | 1553= +++++++++ OvmfPkg/Csm/Include/Protocol/LegacyBiosPlatform.h | 755= +++++ OvmfPkg/Csm/Include/Protocol/LegacyInterrupt.h | 122= + OvmfPkg/Csm/Include/Protocol/VgaMiniPort.h | 88= + OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h | 1460= +++++++++ OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUi.h | 249= ++ OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.h | 79= + OvmfPkg/Csm/LegacyBootManagerLib/InternalLegacyBm.h | 60= + OvmfPkg/Csm/BiosThunk/VideoDxe/BiosVideo.c | 3289= ++++++++++++++++++++ OvmfPkg/Csm/BiosThunk/VideoDxe/ComponentName.c | 306= ++ OvmfPkg/Csm/LegacyBiosDxe/LegacyBbs.c | 377= +++ OvmfPkg/Csm/LegacyBiosDxe/LegacyBda.c | 62= + OvmfPkg/Csm/LegacyBiosDxe/LegacyBios.c | 1214= ++++++++ OvmfPkg/Csm/LegacyBiosDxe/LegacyBootSupport.c | 2173= +++++++++++++ OvmfPkg/Csm/LegacyBiosDxe/LegacyCmos.c | 117= + OvmfPkg/Csm/LegacyBiosDxe/LegacyIde.c | 310= ++ OvmfPkg/Csm/LegacyBiosDxe/LegacyPci.c | 3083= ++++++++++++++++++ OvmfPkg/Csm/LegacyBiosDxe/LegacySio.c | 477= +++ OvmfPkg/Csm/LegacyBiosDxe/Thunk.c | 419= +++ OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUi.c | 1505= +++++++++ OvmfPkg/Csm/LegacyBootManagerLib/LegacyBm.c | 1530= +++++++++ OvmfPkg/Csm/BiosThunk/VideoDxe/BiosVideoDxe.uni | 17= + OvmfPkg/Csm/BiosThunk/VideoDxe/BiosVideoDxeExtra.uni | 14= + OvmfPkg/Csm/LegacyBiosDxe/IA32/InterruptTable.nasm | 63= + OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.uni | 16= + OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxeExtra.uni | 14= + OvmfPkg/Csm/LegacyBiosDxe/X64/InterruptTable.nasm | 64= + OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.uni | 20= + OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiStrings.uni | 43= + OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.Vfr | 67= + OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.uni | 20= + 50 files changed, 22879 insertions(+) diff --git a/OvmfPkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf b/OvmfPkg/Csm/Bios= Thunk/VideoDxe/VideoDxe.inf new file mode 100644 index 0000000000..1526bc4cc2 --- /dev/null +++ b/OvmfPkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf @@ -0,0 +1,80 @@ +## @file +# Video driver based on legacy bios. +# +# This driver by using Legacy Bios protocol service to support csm Video +# and produce Graphics Output Protocol. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D BiosVideoDxe + MODULE_UNI_FILE =3D BiosVideoDxe.uni + FILE_GUID =3D 0B04B2ED-861C-42cd-A22F-C3AAFACCB896 + MODULE_TYPE =3D UEFI_DRIVER + VERSION_STRING =3D 1.0 + + ENTRY_POINT =3D BiosVideoEntryPoint + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 EBC +# +# DRIVER_BINDING =3D gBiosVideoDriverBinding +# COMPONENT_NAME =3D gBiosVideoComponentName +# + +[Sources] + BiosVideo.c + BiosVideo.h + ComponentName.c + VesaBiosExtensions.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + + +[LibraryClasses] + MemoryAllocationLib + DevicePathLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + BaseMemoryLib + ReportStatusCodeLib + DebugLib + PcdLib + + +[Guids] + gEfiLegacyBiosGuid ## PRODUCES ##GUID # Inst= all Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver + gEfiEventExitBootServicesGuid ## CONSUMES ##Event + +[Protocols] + gEfiVgaMiniPortProtocolGuid ## BY_START + gEfiEdidDiscoveredProtocolGuid ## BY_START + gEfiGraphicsOutputProtocolGuid ## BY_START + gEfiEdidActiveProtocolGuid ## BY_START + gEfiLegacyBiosProtocolGuid ## CONSUMES + gEfiPciIoProtocolGuid ## TO_START + gEfiDevicePathProtocolGuid ## TO_START + gEfiDevicePathProtocolGuid ## BY_START + gEfiEdidOverrideProtocolGuid ## SOMETIMES_CONSUMES + +[Pcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoSetTextVgaModeEnab= le ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVbeEnable = ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVgaEnable = ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution = ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution = ## SOMETIMES_CONSUMES + +[UserExtensions.TianoCore."ExtraFiles"] + BiosVideoDxeExtra.uni diff --git a/OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf b/OvmfPkg/Csm/Lega= cyBiosDxe/LegacyBiosDxe.inf new file mode 100644 index 0000000000..471d37365c --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf @@ -0,0 +1,131 @@ +## @file +# Legacy Bios Module to support CSM. +# +# This driver installs Legacy Bios Protocol to support CSM module work in = EFI system. +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D LegacyBiosDxe + MODULE_UNI_FILE =3D LegacyBiosDxe.uni + FILE_GUID =3D F122A15C-C10B-4d54-8F48-60F4F06DD1AD + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + + ENTRY_POINT =3D LegacyBiosInstall + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 +# + +[Sources] + LegacyCmos.c + LegacyIde.c + LegacyBios.c + LegacyBda.c + LegacyBiosInterface.h + LegacyPci.c + +[Sources.Ia32] + IA32/InterruptTable.nasm + Thunk.c + LegacyBootSupport.c + LegacyBbs.c + LegacySio.c + +[Sources.X64] + X64/InterruptTable.nasm + Thunk.c + LegacyBootSupport.c + LegacyBbs.c + LegacySio.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + + +[LibraryClasses] + DevicePathLib + UefiBootServicesTableLib + MemoryAllocationLib + UefiDriverEntryPoint + BaseMemoryLib + UefiLib + DebugLib + DxeServicesTableLib + PcdLib + ReportStatusCodeLib + DebugAgentLib + +[LibraryClasses.IA32] + IoLib + HobLib + UefiRuntimeServicesTableLib + BaseLib + +[LibraryClasses.X64] + IoLib + HobLib + UefiRuntimeServicesTableLib + BaseLib + +[Guids] + gEfiDiskInfoIdeInterfaceGuid ## SOMETIMES_CONSUMES ##GU= ID #Used in LegacyBiosBuildIdeData() to assure device is a disk + gEfiSmbiosTableGuid ## SOMETIMES_CONSUMES ##Sy= stemTable + gEfiLegacyBiosGuid ## SOMETIMES_CONSUMES ##GU= ID #Used in LegacyBiosInstallVgaRom() to locate handle buffer + gEfiEndOfDxeEventGroupGuid ## CONSUMES + +[Guids.IA32] + gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ##Sy= stemTable + gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ##Sy= stemTable + +[Guids.X64] + gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ##Sy= stemTable + gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ##Sy= stemTable + + +[Protocols] + gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES + gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMES + gEfiPciRootBridgeIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiCpuArchProtocolGuid ## CONSUMES + gEfiTimerArchProtocolGuid ## CONSUMES + gEfiIsaIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiPciIoProtocolGuid ## SOMETIMES_CONSUMES + gEfiGenericMemTestProtocolGuid ## CONSUMES + gEfiDiskInfoProtocolGuid ## SOMETIMES_CONSUMES + gEfiSimpleTextInProtocolGuid ## SOMETIMES_CONSUMES + gEfiLegacy8259ProtocolGuid ## CONSUMES + gEfiLegacyBiosPlatformProtocolGuid ## CONSUMES + gEfiLegacyInterruptProtocolGuid ## CONSUMES + gEfiLegacyRegion2ProtocolGuid ## CONSUMES + gEfiLegacyBiosProtocolGuid ## PRODUCES + gEfiSerialIoProtocolGuid ## CONSUMES + gEfiSioProtocolGuid ## CONSUMES + gEdkiiIoMmuProtocolGuid ## CONSUMES + +[Pcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion= ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize = ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEndOpromShadowAddress = ## SOMETIMES_CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLowPmmMemorySize = ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHighPmmMemorySize = ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemoryBase = ## CONSUMES + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemorySize = ## CONSUMES + +[Depex] + gEfiLegacyRegion2ProtocolGuid AND gEfiLegacyInterruptProtocolGuid AND gE= fiLegacyBiosPlatformProtocolGuid AND gEfiLegacy8259ProtocolGuid AND gEfiGen= ericMemTestProtocolGuid AND gEfiCpuArchProtocolGuid AND gEfiTimerArchProtoc= olGuid AND gEfiVariableWriteArchProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + LegacyBiosDxeExtra.uni diff --git a/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf b/Ov= mfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf new file mode 100644 index 0000000000..557b8d8169 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf @@ -0,0 +1,63 @@ +## @file +# Legacy Boot Maintainence UI module is library for BDS phase. +# +# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D LegacyBootMaintUiLib + MODULE_UNI_FILE =3D LegacyBootMaintUiLib.uni + FILE_GUID =3D e6f7f038-3ed9-401a-af1f-5ea7bf644d34 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D NULL|DXE_DRIVER UEFI_APPLICATION + CONSTRUCTOR =3D LegacyBootMaintUiLibConstructor + DESTRUCTOR =3D LegacyBootMaintUiLibDestructor +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 EBC +# + +[Sources] + LegacyBootMaintUiVfr.h + LegacyBootMaintUi.h + LegacyBootMaintUiVfr.Vfr + LegacyBootMaintUiStrings.uni + LegacyBootMaintUi.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + +[LibraryClasses] + DevicePathLib + BaseLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + DebugLib + HiiLib + MemoryAllocationLib + UefiBootManagerLib + UefiLib + PrintLib + BaseMemoryLib + +[Guids] + gEfiIfrTianoGuid ## SOMETIMES_PRODUCES ## UNDEFINED # E= xtended IFR Guid Opcode + gEfiIfrBootMaintenanceGuid ## CONSUMES ## HII # BootMaint HII Pac= kage + gEfiLegacyDevOrderVariableGuid ## PRODUCES ## Variable:L"LegacyDevOrd= er" + +[Protocols] + gEfiHiiConfigAccessProtocolGuid ## PRODUCES + gEfiLegacyBiosProtocolGuid ## CONSUMES + gEfiHiiConfigRoutingProtocolGuid ## CONSUMES + +[Depex] + gEfiHiiDatabaseProtocolGuid + diff --git a/OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf b/Ov= mfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf new file mode 100644 index 0000000000..eaf7b7235d --- /dev/null +++ b/OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf @@ -0,0 +1,58 @@ +## @file +# Legacy Boot Manager module is library for BDS phase. +# +# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D LegacyBootManagerLib + MODULE_UNI_FILE =3D LegacyBootManagerLib.uni + FILE_GUID =3D F1B87BE4-0ACC-409A-A52B-7BFFABCC96A0 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D NULL|DXE_DRIVER UEFI_APPLICATION + CONSTRUCTOR =3D LegacyBootManagerLibConstructor + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 EBC +# + +[Sources] + LegacyBm.c + InternalLegacyBm.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DevicePathLib + MemoryAllocationLib + UefiLib + DebugLib + PrintLib + PerformanceLib + UefiBootManagerLib + +[Guids] + gEfiGlobalVariableGuid ## SOMETIMES_PRODUCES ## V= ariable:L"Boot####" (Boot option variable) + ## SOMETIMES_CONSUMES ## V= ariable:L"BootOrder" (The boot option array) + gEfiLegacyDevOrderVariableGuid + +[Protocols] + gEfiLegacyBiosProtocolGuid ## SOMETIMES_CONSUMES + +[FeaturePcd] + +[Pcd] diff --git a/OvmfPkg/Csm/BiosThunk/VideoDxe/BiosVideo.h b/OvmfPkg/Csm/BiosT= hunk/VideoDxe/BiosVideo.h new file mode 100644 index 0000000000..951f4e6f76 --- /dev/null +++ b/OvmfPkg/Csm/BiosThunk/VideoDxe/BiosVideo.h @@ -0,0 +1,532 @@ +/** @file + +Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _BIOS_GRAPHICS_OUTPUT_H_ +#define _BIOS_GRAPHICS_OUTPUT_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "VesaBiosExtensions.h" + +// +// Packed format support: The number of bits reserved for each of the colo= rs and the actual +// position of RGB in the frame buffer is specified in the VBE Mode inform= ation +// +typedef struct { + UINT8 Position; // Position of the color + UINT8 Mask; // The number of bits expressed as a mask +} BIOS_VIDEO_COLOR_PLACEMENT; + +// +// BIOS Graphics Output Graphical Mode Data +// +typedef struct { + UINT16 VbeModeNumber; + UINT16 BytesPerScanLine; + VOID *LinearFrameBuffer; + UINTN FrameBufferSize; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 ColorDepth; + UINT32 RefreshRate; + UINT32 BitsPerPixel; + BIOS_VIDEO_COLOR_PLACEMENT Red; + BIOS_VIDEO_COLOR_PLACEMENT Green; + BIOS_VIDEO_COLOR_PLACEMENT Blue; + BIOS_VIDEO_COLOR_PLACEMENT Reserved; + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + EFI_PIXEL_BITMASK PixelBitMask; +} BIOS_VIDEO_MODE_DATA; + +// +// BIOS video child handle private data Structure +// +#define BIOS_VIDEO_DEV_SIGNATURE SIGNATURE_32 ('B', 'V', 'M', 'p') + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + + // + // Consumed Protocols + // + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + + // + // Produced Protocols + // + EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput; + EFI_EDID_DISCOVERED_PROTOCOL EdidDiscovered; + EFI_EDID_ACTIVE_PROTOCOL EdidActive; + EFI_VGA_MINI_PORT_PROTOCOL VgaMiniPort; + + // + // General fields + // + BOOLEAN VgaCompatible; + BOOLEAN ProduceGraphicsOutput; + + // + // Graphics Output Protocol related fields + // + BOOLEAN HardwareNeedsStarting; + UINTN CurrentMode; + UINTN MaxMode; + BIOS_VIDEO_MODE_DATA *ModeData; + UINT8 *LineBuffer; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer; + UINT8 *VgaFrameBuffer; + + // + // VESA Bios Extensions related fields + // + UINTN NumberOfPagesBelow1MB; /= / Number of 4KB pages in PagesBelow1MB + EFI_PHYSICAL_ADDRESS PagesBelow1MB; /= / Buffer for all VBE Information Blocks + VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *VbeInformationBlock; /= / 0x200 bytes. Must be allocated below 1MB + VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *VbeModeInformationBlock; /= / 0x100 bytes. Must be allocated below 1MB + VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *VbeEdidDataBlock; /= / 0x80 bytes. Must be allocated below 1MB + VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *VbeCrtcInformationBlock; /= / 59 bytes. Must be allocated below 1MB + UINTN VbeSaveRestorePages; /= / Number of 4KB pages in VbeSaveRestoreBuffer + EFI_PHYSICAL_ADDRESS VbeSaveRestoreBuffer; /= / Must be allocated below 1MB + // + // Status code + // + EFI_DEVICE_PATH_PROTOCOL *GopDevicePath; + + EFI_EVENT ExitBootServicesEvent; +} BIOS_VIDEO_DEV; + +#define BIOS_VIDEO_DEV_FROM_PCI_IO_THIS(a) CR (a, BIOS_VIDEO_DEV= , PciIo, BIOS_VIDEO_DEV_SIGNATURE) +#define BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS(a) CR (a, BIOS_VIDEO_DEV= , GraphicsOutput, BIOS_VIDEO_DEV_SIGNATURE) +#define BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS(a) CR (a, BIOS_VIDEO_DEV= , VgaMiniPort, BIOS_VIDEO_DEV_SIGNATURE) + +#define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER 0xffff + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gBiosVideoComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2; + +// +// Driver Binding Protocol functions +// + +/** + Supported. + + @param This Pointer to driver binding protocol + @param Controller Controller handle to connect + @param RemainingDevicePath A pointer to the remaining portion of a d= evice + path + + @retval EFI_STATUS EFI_SUCCESS:This controller can be manage= d by this + driver, Otherwise, this controller cannot= be + managed by this driver + +**/ +EFI_STATUS +EFIAPI +BiosVideoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + + +/** + Install Graphics Output Protocol onto VGA device handles. + + @param This Pointer to driver binding protocol + @param Controller Controller handle to connect + @param RemainingDevicePath A pointer to the remaining portion of a d= evice + path + + @return EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +BiosVideoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + + +/** + Stop. + + @param This Pointer to driver binding protocol + @param Controller Controller handle to connect + @param NumberOfChildren Number of children handle created by this= driver + @param ChildHandleBuffer Buffer containing child handle created + + @retval EFI_SUCCESS Driver disconnected successfully from con= troller + @retval EFI_UNSUPPORTED Cannot find BIOS_VIDEO_DEV structure + +**/ +EFI_STATUS +EFIAPI +BiosVideoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// Private worker functions +// + +/** + Check for VBE device. + + @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure + + @retval EFI_SUCCESS VBE device found + +**/ +EFI_STATUS +BiosVideoCheckForVbe ( + IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate + ); + + +/** + Check for VGA device. + + @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure + + @retval EFI_SUCCESS Standard VGA device found + +**/ +EFI_STATUS +BiosVideoCheckForVga ( + IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate + ); + + + + +/** + Release resource for biso video instance. + + @param BiosVideoPrivate Video child device private data structure + +**/ +VOID +BiosVideoDeviceReleaseResource ( + BIOS_VIDEO_DEV *BiosVideoPrivate + ); + +// +// BIOS Graphics Output Protocol functions +// + +/** + Graphics Output protocol interface to get video mode. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the I= nfo + buffer. + @param Info Caller allocated buffer that returns info= rmation + about ModeNumber. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retri= eve the + video mode. + @retval EFI_NOT_STARTED Video display is not initialized. Call Se= tMode () + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputQueryMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ); + + +/** + Graphics Output protocol interface to set video mode. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to be set. + + @retval EFI_SUCCESS Graphics mode was changed. + @retval EFI_DEVICE_ERROR The device had an error and could not com= plete the + request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this devic= e. + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputSetMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This, + IN UINT32 ModeNumber + ); + + +/** + Graphics Output protocol instance to block transfer for VBE device. + + @param This Pointer to Graphics Output protocol insta= nce + @param BltBuffer The data to transfer to screen + @param BltOperation The operation to perform + @param SourceX The X coordinate of the source for BltOpe= ration + @param SourceY The Y coordinate of the source for BltOpe= ration + @param DestinationX The X coordinate of the destination for + BltOperation + @param DestinationY The Y coordinate of the destination for + BltOperation + @param Width The width of a rectangle in the blt recta= ngle in + pixels + @param Height The height of a rectangle in the blt rect= angle in + pixels + @param Delta Not used for EfiBltVideoFill and + EfiBltVideoToVideo operation. If a Delta = of 0 is + used, the entire BltBuffer will be operat= ed on. If + a subrectangle of the BltBuffer is used, = then + Delta represents the number of bytes in a= row of + the BltBuffer. + + @retval EFI_INVALID_PARAMETER Invalid parameter passed in + @retval EFI_SUCCESS Blt operation success + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputVbeBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta + ); + + +/** + Grahpics Output protocol instance to block transfer for VGA device. + + @param This Pointer to Grahpics Output protocol insta= nce + @param BltBuffer The data to transfer to screen + @param BltOperation The operation to perform + @param SourceX The X coordinate of the source for BltOpe= ration + @param SourceY The Y coordinate of the source for BltOpe= ration + @param DestinationX The X coordinate of the destination for + BltOperation + @param DestinationY The Y coordinate of the destination for + BltOperation + @param Width The width of a rectangle in the blt recta= ngle in + pixels + @param Height The height of a rectangle in the blt rect= angle in + pixels + @param Delta Not used for EfiBltVideoFill and + EfiBltVideoToVideo operation. If a Delta = of 0 is + used, the entire BltBuffer will be operat= ed on. If + a subrectangle of the BltBuffer is used, = then + Delta represents the number of bytes in a= row of + the BltBuffer. + + @retval EFI_INVALID_PARAMETER Invalid parameter passed in + @retval EFI_SUCCESS Blt operation success + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputVgaBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta + ); + +// +// BIOS VGA Mini Port Protocol functions +// + +/** + VgaMiniPort protocol interface to set mode. + + @param This Pointer to VgaMiniPort protocol instance + @param ModeNumber The index of the mode + + @retval EFI_UNSUPPORTED The requested mode is not supported + @retval EFI_SUCCESS The requested mode is set successfully + +**/ +EFI_STATUS +EFIAPI +BiosVideoVgaMiniPortSetMode ( + IN EFI_VGA_MINI_PORT_PROTOCOL *This, + IN UINTN ModeNumber + ); + +/** + Event handler for Exit Boot Service. + + @param Event The event that be siganlled when exiting boot servic= e. + @param Context Pointer to instance of BIOS_VIDEO_DEV. + +**/ +VOID +EFIAPI +BiosVideoNotifyExitBootServices ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// +// Standard VGA Definitions +// +#define VGA_HORIZONTAL_RESOLUTION 640 +#define VGA_VERTICAL_RESOLUTION 480 +#define VGA_NUMBER_OF_BIT_PLANES 4 +#define VGA_PIXELS_PER_BYTE 8 +#define VGA_BYTES_PER_SCAN_LINE (VGA_HORIZONTAL_= RESOLUTION / VGA_PIXELS_PER_BYTE) +#define VGA_BYTES_PER_BIT_PLANE (VGA_VERTICAL_RE= SOLUTION * VGA_BYTES_PER_SCAN_LINE) + +#define VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER 0x3ce +#define VGA_GRAPHICS_CONTROLLER_DATA_REGISTER 0x3cf + +#define VGA_GRAPHICS_CONTROLLER_SET_RESET_REGISTER 0x00 + +#define VGA_GRAPHICS_CONTROLLER_ENABLE_SET_RESET_REGISTER 0x01 + +#define VGA_GRAPHICS_CONTROLLER_COLOR_COMPARE_REGISTER 0x02 + +#define VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER 0x03 +#define VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE 0x00 +#define VGA_GRAPHICS_CONTROLLER_FUNCTION_AND 0x08 +#define VGA_GRAPHICS_CONTROLLER_FUNCTION_OR 0x10 +#define VGA_GRAPHICS_CONTROLLER_FUNCTION_XOR 0x18 + +#define VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER 0x04 + +#define VGA_GRAPHICS_CONTROLLER_MODE_REGISTER 0x05 +#define VGA_GRAPHICS_CONTROLLER_READ_MODE_0 0x00 +#define VGA_GRAPHICS_CONTROLLER_READ_MODE_1 0x08 +#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0 0x00 +#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1 0x01 +#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2 0x02 +#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_3 0x03 + +#define VGA_GRAPHICS_CONTROLLER_MISCELLANEOUS_REGISTER 0x06 + +#define VGA_GRAPHICS_CONTROLLER_COLOR_DONT_CARE_REGISTER 0x07 + +#define VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER 0x08 + +/** + Install child handles if the Handle supports MBR format. + + @param This Calling context. + @param ParentHandle Parent Handle + @param ParentPciIo Parent PciIo interface + @param ParentLegacyBios Parent LegacyBios interface + @param ParentDevicePath Parent Device Path + @param RemainingDevicePath Remaining Device Path + + @retval EFI_SUCCESS If a child handle was added + @retval other A child handle was not added + +**/ +EFI_STATUS +BiosVideoChildHandleInstall ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ParentHandle, + IN EFI_PCI_IO_PROTOCOL *ParentPciIo, + IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Deregister an video child handle and free resources. + + @param This Protocol instance pointer. + @param Controller Video controller handle + @param Handle Video child handle + + @return EFI_STATUS + +**/ +EFI_STATUS +BiosVideoChildHandleUninstall ( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + EFI_HANDLE Handle + ); + +/** + Release resource for biso video instance. + + @param BiosVideoPrivate Video child device private data structure + +**/ +VOID +BiosVideoDeviceReleaseResource ( + BIOS_VIDEO_DEV *BiosVideoPrivate + ); + +/** + Check if all video child handles have been uninstalled. + + @param Controller Video controller handle + + @return TRUE Child handles exist. + @return FALSE All video child handles have been uninsta= lled. + +**/ +BOOLEAN +HasChildHandle ( + IN EFI_HANDLE Controller + ); +#endif diff --git a/OvmfPkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h b/OvmfPkg/= Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h new file mode 100644 index 0000000000..dbf706179f --- /dev/null +++ b/OvmfPkg/Csm/BiosThunk/VideoDxe/VesaBiosExtensions.h @@ -0,0 +1,459 @@ +/** @file + +Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _VESA_BIOS_EXTENSIONS_H_ +#define _VESA_BIOS_EXTENSIONS_H_ + +// +// Turn on byte packing of data structures +// +#pragma pack(1) +// +// VESA BIOS Extensions status codes +// +#define VESA_BIOS_EXTENSIONS_STATUS_SUCCESS 0x004f + +// +// VESA BIOS Extensions Services +// +#define VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION 0x4f00 + +/*++ + + Routine Description: + Function 00 : Return Controller Information + + Arguments: + Inputs: + AX =3D 0x4f00 + ES:DI =3D Pointer to buffer to place VESA_BIOS_EXTENSIONS_INFORMATIO= N_BLOCK structure + Outputs: + AX =3D Return Status + +--*/ +#define VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION 0x4f01 + +/*++ + + Routine Description: + Function 01 : Return Mode Information + + Arguments: + Inputs: + AX =3D 0x4f01 + CX =3D Mode Number + ES:DI =3D Pointer to buffer to place VESA_BIOS_EXTENSIONS_MODE_INFOR= MATION_BLOCK structure + Outputs: + AX =3D Return Status + +--*/ +#define VESA_BIOS_EXTENSIONS_SET_MODE 0x4f02 + +/*++ + + Routine Description: + Function 02 : Set Mode + + Arguments: + Inputs: + AX =3D 0x4f02 + BX =3D Desired mode to set + D0-D8 =3D Mode Number + D9-D10 =3D Reserved (must be 0) + D11 =3D 0 - Use current default refresh rate + =3D 1 - Use user specfieid CRTC values for refresh rate + D12-D13 =3D Reserved (must be 0) + D14 =3D 0 - Use windowed frame buffer model + =3D 1 - Use linear/flat frame buffer model + D15 =3D 0 - Clear display memory + =3D 1 - Don't clear display memory + ES:DI =3D Pointer to buffer to the VESA_BIOS_EXTENSIONS_CRTC_INFORMA= TION_BLOCK structure + Outputs: + AX =3D Return Status + +--*/ +#define VESA_BIOS_EXTENSIONS_RETURN_CURRENT_MODE 0x4f03 + +/*++ + + Routine Description: + Function 03 : Return Current Mode + + Arguments: + Inputs: + AX =3D 0x4f03 + Outputs: + AX =3D Return Status + BX =3D Current mode + D0-D13 =3D Mode Number + D14 =3D 0 - Windowed frame buffer model + =3D 1 - Linear/flat frame buffer model + D15 =3D 0 - Memory cleared at last mode set + =3D 1 - Memory not cleared at last mode set + +--*/ +#define VESA_BIOS_EXTENSIONS_SAVE_RESTORE_STATE 0x4f04 + +/*++ + + Routine Description: + Function 04 : Save/Restore State + + Arguments: + Inputs: + AX =3D 0x4f03 + DL =3D 0x00 - Return Save/Restore State buffer size + =3D 0x01 - Save State + =3D 0x02 - Restore State + CX =3D Requested Status + D0 =3D Save/Restore controller hardware state + D1 =3D Save/Restore BIOS data state + D2 =3D Save/Restore DAC state + D3 =3D Save/Restore Regsiter state + ES:BX =3D Pointer to buffer if DL=3D1 or DL=3D2 + Outputs: + AX =3D Return Status + BX =3D Number of 64 byte blocks to hold the state buffer if DL=3D0 + +--*/ +#define VESA_BIOS_EXTENSIONS_EDID 0x4f15 + +/*++ + + Routine Description: + Function 15 : implement VBE/DDC service + + Arguments: + Inputs: + AX =3D 0x4f15 + BL =3D 0x00 - Report VBE/DDC Capabilities + CX =3D 0x00 - Controller unit number (00 =3D primary controller) + ES:DI =3D Null pointer, must be 0:0 in version 1.0 + Outputs: + AX =3D Return Status + BH =3D Approx. time in seconds, rounded up, to transfer one EDID = block(128 bytes) + BL =3D DDC level supported + D0 =3D 0 DDC1 not supported + =3D 1 DDC1 supported + D1 =3D 0 DDC2 not supported + =3D 1 DDC2 supported + D2 =3D 0 Screen not blanked during data transfer + =3D 1 Screen blanked during data transfer + + Inputs: + AX =3D 0x4f15 + BL =3D 0x01 - Read EDID + CX =3D 0x00 - Controller unit number (00 =3D primary controller) + DX =3D 0x00 - EDID block number + ES:DI =3D Pointer to buffer in which the EDID block is returned + Outputs: + AX =3D Return Status +--*/ + +// +// Timing data from EDID data block +// +#define VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE 128 +#define VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER 17 + +// +// Established Timings: 24 possible resolutions +// Standard Timings: 8 possible resolutions +// Detailed Timings: 4 possible resolutions +// +#define VESA_BIOS_EXTENSIONS_EDID_TIMING_MAX_NUMBER 36 + +// +// Timing data size for Established Timings, Standard Timings and Detailed= Timings +// +#define VESA_BIOS_EXTENSIONS_ESTABLISHED_TIMING_SIZE 3 +#define VESA_BIOS_EXTENSIONS_STANDARD_TIMING_SIZE 16 +#define VESA_BIOS_EXTENSIONS_DETAILED_TIMING_EACH_DESCRIPTOR_SIZE 18 +#define VESA_BIOS_EXTENSIONS_DETAILED_TIMING_DESCRIPTOR_MAX_SIZE 72 + +typedef struct { + UINT16 HorizontalResolution; + UINT16 VerticalResolution; + UINT16 RefreshRate; +} VESA_BIOS_EXTENSIONS_EDID_TIMING; + +typedef struct { + UINT32 ValidNumber; + UINT32 Key[VESA_BIOS_EXTENSIONS_EDID_TIMING_MAX_NUMBER]; +} VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING; + +typedef struct { + UINT8 Header[8]; //EDID header "00 FF FF FF FF = FF FF 00" + UINT16 ManufactureName; //EISA 3-character ID + UINT16 ProductCode; //Vendor assigned code + UINT32 SerialNumber; //32-bit serial number + UINT8 WeekOfManufacture; //Week number + UINT8 YearOfManufacture; //Year + UINT8 EdidVersion; //EDID Structure Version + UINT8 EdidRevision; //EDID Structure Revision + UINT8 VideoInputDefinition; + UINT8 MaxHorizontalImageSize; //cm + UINT8 MaxVerticalImageSize; //cm + UINT8 DisplayTransferCharacteristic; + UINT8 FeatureSupport; + UINT8 RedGreenLowBits; //Rx1 Rx0 Ry1 Ry0 Gx1 Gx0 Gy1G= y0 + UINT8 BlueWhiteLowBits; //Bx1 Bx0 By1 By0 Wx1 Wx0 Wy1 = Wy0 + UINT8 RedX; //Red-x Bits 9 - 2 + UINT8 RedY; //Red-y Bits 9 - 2 + UINT8 GreenX; //Green-x Bits 9 - 2 + UINT8 GreenY; //Green-y Bits 9 - 2 + UINT8 BlueX; //Blue-x Bits 9 - 2 + UINT8 BlueY; //Blue-y Bits 9 - 2 + UINT8 WhiteX; //White-x Bits 9 - 2 + UINT8 WhiteY; //White-x Bits 9 - 2 + UINT8 EstablishedTimings[VESA_BIOS_EXTENSIONS_ESTABLISHED_TIMING_SIZE]; + UINT8 StandardTimingIdentification[VESA_BIOS_EXTENSIONS_STANDARD_TIMIN= G_SIZE]; + UINT8 DetailedTimingDescriptions[VESA_BIOS_EXTENSIONS_DETAILED_TIMING_= DESCRIPTOR_MAX_SIZE]; + UINT8 ExtensionFlag; //Number of (optional) 128-byt= e EDID extension blocks to follow + UINT8 Checksum; +} VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK; + +// +// Super VGA Information Block +// +typedef struct { + UINT32 VESASignature; // 'VESA' 4 byte signature + UINT16 VESAVersion; // VBE version number + UINT32 OEMStringPtr; // Pointer to OEM string + UINT32 Capabilities; // Capabilities of video card + UINT32 VideoModePtr; // Pointer to an array of 16-bit supported mo= des values terminated by 0xFFFF + UINT16 TotalMemory; // Number of 64kb memory blocks + UINT16 OemSoftwareRev; // VBE implementation Software revision + UINT32 OemVendorNamePtr; // VbeFarPtr to Vendor Name String + UINT32 OemProductNamePtr; // VbeFarPtr to Product Name String + UINT32 OemProductRevPtr; // VbeFarPtr to Product Revision String + UINT8 Reserved[222]; // Reserved for VBE implementation scratch a= rea + UINT8 OemData[256]; // Data area for OEM strings. Pad to 512 by= te block size +} VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK; + +// +// Super VGA Information Block VESASignature values +// +#define VESA_BIOS_EXTENSIONS_VESA_SIGNATURE SIGNATURE_32 ('V', 'E', 'S', '= A') +#define VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE SIGNATURE_32 ('V', 'B', 'E', '= 2') + +// +// Super VGA Information Block VESAVersion values +// +#define VESA_BIOS_EXTENSIONS_VERSION_1_2 0x0102 +#define VESA_BIOS_EXTENSIONS_VERSION_2_0 0x0200 +#define VESA_BIOS_EXTENSIONS_VERSION_3_0 0x0300 + +// +// Super VGA Information Block Capabilities field bit defintions +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_8_BIT_DAC 0x01 // 0: DAC width is= fixed at 6 bits/color +// 1: DAC width switchable to 8 bits/color +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_VGA 0x02 // 0: Controller is = VGA compatible +// 1: Controller is not VGA compatible +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_NORMAL_RAMDAC 0x04 // 0: Norm= al RAMDAC operation +// 1: Use blank bit in function 9 to program RAMDAC +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_STEREOSCOPIC 0x08 // 0: No hardw= are stereoscopic signal support +// 1: Hardware stereoscopic signal support +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_VESA_EVC 0x10 // 0: Stero signal= ing supported via external VESA stereo connector +// 1: Stero signaling supported via VESA EVC connector +// +// Super VGA mode number bite field definitions +// +#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA 0x0100 // 0: Not a VESA def= ined VBE mode +// 1: A VESA defined VBE mode +// +#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_REFRESH_CONTROL_USER 0x0800 // 0= : Use current BIOS default referesh rate +// 1: Use the user specified CRTC values for refresh rate +// +#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER 0x4000 // 0= : Use a banked/windowed frame buffer +// 1: Use a linear/flat frame buffer +// +#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_PRESERVE_MEMORY 0x8000 // 0: Cl= ear display memory +// 1: Preseve display memory +// +// Super VGA Information Block mode list terminator value +// +#define VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST 0xffff + +// +// Window Function +// +typedef +VOID +(*VESA_BIOS_EXTENSIONS_WINDOW_FUNCTION) ( + VOID + ); + +// +// Super VGA Mode Information Block +// +typedef struct { + // + // Manadory fields for all VESA Bios Extensions revisions + // + UINT16 ModeAttributes; // Mode attribut= es + UINT8 WinAAttributes; // Window A attr= ibutes + UINT8 WinBAttributes; // Window B attr= ibutes + UINT16 WinGranularity; // Window granul= arity in k + UINT16 WinSize; // Window size i= n k + UINT16 WinASegment; // Window A segm= ent + UINT16 WinBSegment; // Window B segm= ent + UINT32 WindowFunction; // Pointer to wi= ndow function + UINT16 BytesPerScanLine; // Bytes per sca= nline + // + // Manadory fields for VESA Bios Extensions 1.2 and above + // + UINT16 XResolution; // Horizonta= l resolution + UINT16 YResolution; // Vertical = resolution + UINT8 XCharSize; // Character= cell width + UINT8 YCharSize; // Character= cell height + UINT8 NumberOfPlanes; // Number of= memory planes + UINT8 BitsPerPixel; // Bits per = pixel + UINT8 NumberOfBanks; // Number of= CGA style banks + UINT8 MemoryModel; // Memory mo= del type + UINT8 BankSize; // Size of C= GA style banks + UINT8 NumberOfImagePages; // Number of= images pages + UINT8 Reserved1; // Reserved + UINT8 RedMaskSize; // Size of d= irect color red mask + UINT8 RedFieldPosition; // Bit posn = of lsb of red mask + UINT8 GreenMaskSize; // Size of d= irect color green mask + UINT8 GreenFieldPosition; // Bit posn = of lsb of green mask + UINT8 BlueMaskSize; // Size of d= irect color blue mask + UINT8 BlueFieldPosition; // Bit posn = of lsb of blue mask + UINT8 RsvdMaskSize; // Size of d= irect color res mask + UINT8 RsvdFieldPosition; // Bit posn = of lsb of res mask + UINT8 DirectColorModeInfo; // Direct co= lor mode attributes + // + // Manadory fields for VESA Bios Extensions 2.0 and above + // + UINT32 PhysBasePtr; // Physical Address = for flat memory frame buffer + UINT32 Reserved2; // Reserved + UINT16 Reserved3; // Reserved + // + // Manadory fields for VESA Bios Extensions 3.0 and above + // + UINT16 LinBytesPerScanLine; // Bytes/s= can line for linear modes + UINT8 BnkNumberOfImagePages; // Number = of images for banked modes + UINT8 LinNumberOfImagePages; // Number = of images for linear modes + UINT8 LinRedMaskSize; // Size of= direct color red mask (linear mode) + UINT8 LinRedFieldPosition; // Bit pos= iiton of lsb of red mask (linear modes) + UINT8 LinGreenMaskSize; // Size of= direct color green mask (linear mode) + UINT8 LinGreenFieldPosition; // Bit pos= iiton of lsb of green mask (linear modes) + UINT8 LinBlueMaskSize; // Size of= direct color blue mask (linear mode) + UINT8 LinBlueFieldPosition; // Bit pos= iiton of lsb of blue mask (linear modes) + UINT8 LinRsvdMaskSize; // Size of= direct color reserved mask (linear mode) + UINT8 LinRsvdFieldPosition; // Bit pos= iiton of lsb of reserved mask (linear modes) + UINT32 MaxPixelClock; // Maximum= pixel clock (in Hz) for graphics mode + UINT8 Pad[190]; // Pad to = 256 byte block size +} VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK; + +// +// Super VGA Mode Information Block ModeAttributes field bit defintions +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_HARDWARE 0x0001 // 0: Mode n= ot supported in handware +// 1: Mode supported in handware +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_TTY 0x0004 // 0: TTY Output f= unctions not supported by BIOS +// 1: TTY Output functions supported by BIOS +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR 0x0008 // 0: Monochrome= mode +// 1: Color mode +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS 0x0010 // 0: Text m= ode +// 1: Graphics mode +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_VGA 0x0020 // 0: VGA comp= atible mode +// 1: Not a VGA compatible mode +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_WINDOWED 0x0040 // 0: VG= A compatible windowed memory mode +// 1: Not a VGA compatible windowed memory mode +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER 0x0080 //= 0: No linear fram buffer mode available +// 1: Linear frame buffer mode available +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DOUBLE_SCAN 0x0100 // 0: No d= ouble scan mode available +// 1: Double scan mode available +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_INTERLACED 0x0200 // 0: No i= nterlaced mode is available +// 1: Interlaced mode is available +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NO_TRIPPLE_BUFFER 0x0400 // 0= : No hardware triple buffer mode support available +// 1: Hardware triple buffer mode support available +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_STEREOSCOPIC 0x0800 // 0: No= hardware steroscopic display support +// 1: Hardware steroscopic display support +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DUAL_DISPLAY 0x1000 // 0: No= dual display start address support +// 1: Dual display start address support +// +// Super VGA Mode Information Block WinAAttribite/WinBAttributes field bit= defintions +// +#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_RELOCATABLE 0x01 // 0: Single= non-relocatable window only +// 1: Relocatable window(s) are supported +// +#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_READABLE 0x02 // 0: Window i= s not readable +// 1: Window is readable +// +#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_WRITABLE 0x04 // 0: Window i= s not writable +// 1: Window is writable +// +// Super VGA Mode Information Block DirectColorMode field bit defintions +// +#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_PROG_COLOR_RAMP 0x01 // 0= : Color ram is fixed +// 1: Color ramp is programmable +// +#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_RSVD_USABLE 0x02 // 0: Bi= ts in Rsvd field are reserved +// 1: Bits in Rsdv field are usable +// +// Super VGA Memory Models +// +typedef enum { + MemPL =3D 3, // Planar memory model + MemPK =3D 4, // Packed pixel memory model + MemRGB=3D 6, // Direct color RGB memory model + MemYUV=3D 7 // Direct color YUV memory model +} VESA_BIOS_EXTENSIONS_MEMORY_MODELS; + +// +// Super VGA CRTC Information Block +// +typedef struct { + UINT16 HorizontalTotal; // Horizontal total in pixels + UINT16 HorizontalSyncStart; // Horizontal sync start in pixels + UINT16 HorizontalSyncEnd; // Horizontal sync end in pixels + UINT16 VericalTotal; // Vertical total in pixels + UINT16 VericalSyncStart; // Vertical sync start in pixels + UINT16 VericalSyncEnd; // Vertical sync end in pixels + UINT8 Flags; // Flags (Interlaced/DoubleScan/etc). + UINT32 PixelClock; // Pixel clock in units of Hz + UINT16 RefreshRate; // Refresh rate in units of 0.01 Hz + UINT8 Reserved[40]; // Pad +} VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK; + +#define VESA_BIOS_EXTENSIONS_CRTC_FLAGS_DOUBLE_SCAN 0x01 // 0: Graphics m= ode is not souble scanned +// 1: Graphics mode is double scanned +// +#define VESA_BIOS_EXTENSIONS_CRTC_FLAGSINTERLACED 0x02 // 0: Graphics mod= e is not interlaced +// 1: Graphics mode is interlaced +// +#define VESA_BIOS_EXTENSIONS_CRTC_HORIZONTAL_SYNC_NEGATIVE 0x04 // 0: Ho= rizontal sync polarity is positive(+) +// 0: Horizontal sync polarity is negative(-) +// +#define VESA_BIOS_EXTENSIONS_CRTC_VERITICAL_SYNC_NEGATIVE 0x08 // 0: Veri= cal sync polarity is positive(+) +// 0: Verical sync polarity is negative(-) +// +// Turn off byte packing of data structures +// +#pragma pack() + +#endif diff --git a/OvmfPkg/Csm/Include/Framework/BootScript.h b/OvmfPkg/Csm/Inclu= de/Framework/BootScript.h new file mode 100644 index 0000000000..cb7220c1a7 --- /dev/null +++ b/OvmfPkg/Csm/Include/Framework/BootScript.h @@ -0,0 +1,41 @@ +/** @file + This file contains the boot script defintions that are shared between the + Boot Script Executor PPI and the Boot Script Save Protocol. + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _BOOT_SCRIPT_H_ +#define _BOOT_SCRIPT_H_ + +#include +/// +/// The framework implementation defines follow opcode that are different = from the PI specification: +/// Add FRAMEWORK_ prefix to avoid naming conflict. +/// +/// S3 Boot Script Table identifier. +/// +#define FRAMEWORK_EFI_ACPI_S3_RESUME_SCRIPT_TABLE 0x00 +/// +/// The opcode is used to add a record for memory reads of the memory loca= tion and continues when the +/// exit criteria is satisfied, or after a defined duration. +/// +#define FRAMEWORK_EFI_BOOT_SCRIPT_MEM_POLL_OPCODE 0x09 +/// +/// The opcode is used to add a record for dispatching specified arbitrary= code into a specified +/// boot script table. +/// +#define FRAMEWORK_EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE 0x0D +/// +/// The opcode indicates the start of the boot script table. +/// +#define FRAMEWORK_EFI_BOOT_SCRIPT_TABLE_OPCODE 0xAA +/// +/// The opcode indicates the end of the boot script table. +/// +#define FRAMEWORK_EFI_BOOT_SCRIPT_TERMINATE_OPCODE 0xFF + + +#endif diff --git a/OvmfPkg/Csm/Include/Framework/DxeCis.h b/OvmfPkg/Csm/Include/F= ramework/DxeCis.h new file mode 100644 index 0000000000..98a947e420 --- /dev/null +++ b/OvmfPkg/Csm/Include/Framework/DxeCis.h @@ -0,0 +1,170 @@ +/** @file + Include file for definitions in the Intel Platform Innovation Framework = for EFI + Driver Execution Environment Core Interface Specification (DXE CIS) Vers= ion 0.91. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _DXECIS_H_ +#define _DXECIS_H_ + +#include + +/** + Functions of this type are used with the Framework MP Services Protocol = and + the SMM Services Table to execute a procedure on enabled APs. The cont= ext + the AP should use durng execution is specified by Buffer. + + @param[in] Buffer The pointer to the procedure's argument. + +**/ +typedef +VOID +(EFIAPI *FRAMEWORK_EFI_AP_PROCEDURE)( + IN VOID *Buffer + ); + +/// +/// The Framework EFI Runtime Services Table as an extension to the EFI 1.= 10 Runtime Services Table. +/// +typedef struct { + // + // Table header for the Framework EFI Runtime Services Table + // + EFI_TABLE_HEADER Hdr; + // + // Time services + // + EFI_GET_TIME GetTime; + EFI_SET_TIME SetTime; + EFI_GET_WAKEUP_TIME GetWakeupTime; + EFI_SET_WAKEUP_TIME SetWakeupTime; + // + // Virtual memory services + // + EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap; + EFI_CONVERT_POINTER ConvertPointer; + // + // Variable services + // + EFI_GET_VARIABLE GetVariable; + EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName; + EFI_SET_VARIABLE SetVariable; + // + // Misc + // + EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonotonicCount; + EFI_RESET_SYSTEM ResetSystem; + /// + /// A Framework extension to the EFI 1.10 runtime table. + /// It was moved to a protocol to avoid conflict with UEFI 2.0. + /// + EFI_REPORT_STATUS_CODE ReportStatusCode; +} FRAMEWORK_EFI_RUNTIME_SERVICES; + +/// +/// The Framework EFI Boot Services Table. Complies with the DxeCis specif= ication. +/// +typedef struct { + /// + /// The table header for the EFI Boot Services Table. + /// + EFI_TABLE_HEADER Hdr; + + // + // Task Priority Services + // + EFI_RAISE_TPL RaiseTPL; + EFI_RESTORE_TPL RestoreTPL; + + // + // Memory Services + // + EFI_ALLOCATE_PAGES AllocatePages; + EFI_FREE_PAGES FreePages; + EFI_GET_MEMORY_MAP GetMemoryMap; + EFI_ALLOCATE_POOL AllocatePool; + EFI_FREE_POOL FreePool; + + // + // Event & Timer Services + // + EFI_CREATE_EVENT CreateEvent; + EFI_SET_TIMER SetTimer; + EFI_WAIT_FOR_EVENT WaitForEvent; + EFI_SIGNAL_EVENT SignalEvent; + EFI_CLOSE_EVENT CloseEvent; + EFI_CHECK_EVENT CheckEvent; + + // + // Protocol Handler Services + // + EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface; + EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface; + EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface; + EFI_HANDLE_PROTOCOL HandleProtocol; + EFI_HANDLE_PROTOCOL PcHandleProtocol; + EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify; + EFI_LOCATE_HANDLE LocateHandle; + EFI_LOCATE_DEVICE_PATH LocateDevicePath; + EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable; + + // + // Image Services + // + EFI_IMAGE_LOAD LoadImage; + EFI_IMAGE_START StartImage; + EFI_EXIT Exit; + EFI_IMAGE_UNLOAD UnloadImage; + EFI_EXIT_BOOT_SERVICES ExitBootServices; + + // + // Miscellaneous Services + // + EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount; + EFI_STALL Stall; + EFI_SET_WATCHDOG_TIMER SetWatchdogTimer; + + // + // DriverSupport Services + // + EFI_CONNECT_CONTROLLER ConnectController; + EFI_DISCONNECT_CONTROLLER DisconnectController; + + // + // Open and Close Protocol Services + // + EFI_OPEN_PROTOCOL OpenProtocol; + EFI_CLOSE_PROTOCOL CloseProtocol; + EFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation; + + // + // Library Services + // + EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle; + EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer; + EFI_LOCATE_PROTOCOL LocateProtocol; + EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInter= faces; + EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInt= erfaces; + + // + // 32-bit CRC Services + // + EFI_CALCULATE_CRC32 CalculateCrc32; + + // + // Miscellaneous Services + // + EFI_COPY_MEM CopyMem; + EFI_SET_MEM SetMem; +} FRAMEWORK_EFI_BOOT_SERVICES; + +#define EFI_EVENT_RUNTIME_CONTEXT 0x20000000 +#define EFI_EVENT_NOTIFY_SIGNAL_ALL 0x00000400 +#define EFI_EVENT_SIGNAL_READY_TO_BOOT 0x00000203 +#define EFI_EVENT_SIGNAL_LEGACY_BOOT 0x00000204 + +#endif + diff --git a/OvmfPkg/Csm/Include/Framework/FirmwareVolumeHeader.h b/OvmfPkg= /Csm/Include/Framework/FirmwareVolumeHeader.h new file mode 100644 index 0000000000..e2b5a28b8b --- /dev/null +++ b/OvmfPkg/Csm/Include/Framework/FirmwareVolumeHeader.h @@ -0,0 +1,79 @@ +/** @file + Defines the data structure that is the volume header found at the beginn= ing of + all firmware volumes that are either memory mapped or have an + associated FirmwareVolumeBlock protocol. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Revision Reference: + These definitions are from the Firmware Volume Block Spec 0.9. + +**/ + +#ifndef __EFI_FIRMWARE_VOLUME_HEADER_H__ +#define __EFI_FIRMWARE_VOLUME_HEADER_H__ + +/// +/// Firmware Volume Block Attributes bit definitions. +///@{ +#define EFI_FVB_READ_DISABLED_CAP 0x00000001 +#define EFI_FVB_READ_ENABLED_CAP 0x00000002 +#define EFI_FVB_READ_STATUS 0x00000004 + +#define EFI_FVB_WRITE_DISABLED_CAP 0x00000008 +#define EFI_FVB_WRITE_ENABLED_CAP 0x00000010 +#define EFI_FVB_WRITE_STATUS 0x00000020 + +#define EFI_FVB_LOCK_CAP 0x00000040 +#define EFI_FVB_LOCK_STATUS 0x00000080 + +#define EFI_FVB_STICKY_WRITE 0x00000200 +#define EFI_FVB_MEMORY_MAPPED 0x00000400 +#define EFI_FVB_ERASE_POLARITY 0x00000800 + +#define EFI_FVB_ALIGNMENT_CAP 0x00008000 +#define EFI_FVB_ALIGNMENT_2 0x00010000 +#define EFI_FVB_ALIGNMENT_4 0x00020000 +#define EFI_FVB_ALIGNMENT_8 0x00040000 +#define EFI_FVB_ALIGNMENT_16 0x00080000 +#define EFI_FVB_ALIGNMENT_32 0x00100000 +#define EFI_FVB_ALIGNMENT_64 0x00200000 +#define EFI_FVB_ALIGNMENT_128 0x00400000 +#define EFI_FVB_ALIGNMENT_256 0x00800000 +#define EFI_FVB_ALIGNMENT_512 0x01000000 +#define EFI_FVB_ALIGNMENT_1K 0x02000000 +#define EFI_FVB_ALIGNMENT_2K 0x04000000 +#define EFI_FVB_ALIGNMENT_4K 0x08000000 +#define EFI_FVB_ALIGNMENT_8K 0x10000000 +#define EFI_FVB_ALIGNMENT_16K 0x20000000 +#define EFI_FVB_ALIGNMENT_32K 0x40000000 +#define EFI_FVB_ALIGNMENT_64K 0x80000000 +///@} + +/// This is a simple macro defined as the set of all FV Block Attributes s= ignifying capabilities. +#define EFI_FVB_CAPABILITIES ( EFI_FVB_READ_DISABLED_CAP | \ + EFI_FVB_READ_ENABLED_CAP | \ + EFI_FVB_WRITE_DISABLED_CAP | \ + EFI_FVB_WRITE_ENABLED_CAP | \ + EFI_FVB_LOCK_CAP \ + ) + +/** A parameterized macro defining a boolean expression that tests the sta= te of a particular bit. + * + * @param FvbAttributes Indicates a test for CLEAR if EFI_FVB_ERASE_POLA= RITY is 1, else test for SET. + * + * @param TestAttributes The set of bits to test. + * + * @param Bit A value indicating the bit(s) to test. + * If multiple bits are set, the logical OR of thei= r tests is the expression's value. +**/ +#define EFI_TEST_FFS_ATTRIBUTES_BIT( FvbAttributes, TestAttributes, Bit) \ + ((BOOLEAN) \ + ((FvbAttributes & EFI_FVB_ERASE_POLARITY) ? (((~TestAttributes) & Bi= t) =3D=3D Bit) : ((TestAttributes & Bit) =3D=3D Bit)) \ + ) + +/// A simple macro defined as the set of all FV Block Attribute bits that = indicate status. +#define EFI_FVB_STATUS (EFI_FVB_READ_STATUS | EFI_FVB_WRITE_STATUS | EF= I_FVB_LOCK_STATUS) + +#endif /* __EFI_FIRMWARE_VOLUME_HEADER_H__ */ diff --git a/OvmfPkg/Csm/Include/Framework/FirmwareVolumeImageFormat.h b/Ov= mfPkg/Csm/Include/Framework/FirmwareVolumeImageFormat.h new file mode 100644 index 0000000000..c77e39b4c0 --- /dev/null +++ b/OvmfPkg/Csm/Include/Framework/FirmwareVolumeImageFormat.h @@ -0,0 +1,32 @@ +/** @file + This file defines the data structures that are architecturally defined f= or file + images loaded via the FirmwareVolume protocol. The Firmware Volume spec= ification + is the basis for these definitions. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Revision Reference: + These definitions are from the Firmware Volume Spec 0.9. + +**/ + +#ifndef __FIRMWARE_VOLUME_IMAGE_FORMAT_H__ +#define __FIRMWARE_VOLUME_IMAGE_FORMAT_H__ + +// +// Bit values for AuthenticationStatus +// +#define EFI_AGGREGATE_AUTH_STATUS_PLATFORM_OVERRIDE 0x000001 +#define EFI_AGGREGATE_AUTH_STATUS_IMAGE_SIGNED 0x000002 +#define EFI_AGGREGATE_AUTH_STATUS_NOT_TESTED 0x000004 +#define EFI_AGGREGATE_AUTH_STATUS_TEST_FAILED 0x000008 +#define EFI_AGGREGATE_AUTH_STATUS_ALL 0x00000f + +#define EFI_LOCAL_AUTH_STATUS_PLATFORM_OVERRIDE 0x010000 +#define EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED 0x020000 +#define EFI_LOCAL_AUTH_STATUS_NOT_TESTED 0x040000 +#define EFI_LOCAL_AUTH_STATUS_TEST_FAILED 0x080000 +#define EFI_LOCAL_AUTH_STATUS_ALL 0x0f0000 + +#endif diff --git a/OvmfPkg/Csm/Include/Framework/FrameworkInternalFormRepresentat= ion.h b/OvmfPkg/Csm/Include/Framework/FrameworkInternalFormRepresentation.h new file mode 100644 index 0000000000..04cbae1ef5 --- /dev/null +++ b/OvmfPkg/Csm/Include/Framework/FrameworkInternalFormRepresentation.h @@ -0,0 +1,397 @@ +/** @file + This file defines the encoding for the VFR (Visual Form Representation) = language. + Framework IFR is primarily consumed by the EFI presentation engine, and = produced by EFI + internal application and drivers as well as all add-in card option-ROM d= rivers + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Revision Reference: + These definitions are from the Framework Specification HII 0.92. + +**/ + +#ifndef __FRAMEWORK_INTERNAL_FORMREPRESENTATION_H__ +#define __FRAMEWORK_INTERNAL_FORMREPRESENTATION_H__ + +typedef UINT16 STRING_REF; + +// +// IFR Op codes +// +#define FRAMEWORK_EFI_IFR_FORM_OP 0x01 +#define FRAMEWORK_EFI_IFR_SUBTITLE_OP 0x02 +#define FRAMEWORK_EFI_IFR_TEXT_OP 0x03 +#define EFI_IFR_GRAPHIC_OP 0x04 +#define FRAMEWORK_EFI_IFR_ONE_OF_OP 0x05 +#define FRAMEWORK_EFI_IFR_CHECKBOX_OP 0x06 +#define FRAMEWORK_EFI_IFR_NUMERIC_OP 0x07 +#define FRAMEWORK_EFI_IFR_PASSWORD_OP 0x08 +#define FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP 0x09 ///< ONEOF OPTION = field. +#define FRAMEWORK_EFI_IFR_SUPPRESS_IF_OP 0x0A +#define EFI_IFR_END_FORM_OP 0x0B +#define EFI_IFR_HIDDEN_OP 0x0C +#define EFI_IFR_END_FORM_SET_OP 0x0D +#define FRAMEWORK_EFI_IFR_FORM_SET_OP 0x0E +#define FRAMEWORK_EFI_IFR_REF_OP 0x0F +#define EFI_IFR_END_ONE_OF_OP 0x10 +#define FRAMEWORK_EFI_IFR_END_OP EFI_IFR_END_ONE_OF_OP +#define FRAMEWORK_EFI_IFR_INCONSISTENT_IF_OP 0x11 +#define FRAMEWORK_EFI_IFR_EQ_ID_VAL_OP 0x12 +#define FRAMEWORK_EFI_IFR_EQ_ID_ID_OP 0x13 +#define FRAMEWORK_EFI_IFR_EQ_ID_LIST_OP 0x14 +#define FRAMEWORK_EFI_IFR_AND_OP 0x15 +#define FRAMEWORK_EFI_IFR_OR_OP 0x16 +#define FRAMEWORK_EFI_IFR_NOT_OP 0x17 +#define EFI_IFR_END_IF_OP 0x18 ///< For endif of = inconsistentif, suppressif, grayoutif. +#define EFI_IFR_GRAYOUT_IF_OP 0x19 +#define FRAMEWORK_EFI_IFR_DATE_OP 0x1A +#define FRAMEWORK_EFI_IFR_TIME_OP 0x1B +#define FRAMEWORK_EFI_IFR_STRING_OP 0x1C +#define EFI_IFR_LABEL_OP 0x1D +#define EFI_IFR_SAVE_DEFAULTS_OP 0x1E +#define EFI_IFR_RESTORE_DEFAULTS_OP 0x1F +#define EFI_IFR_BANNER_OP 0x20 +#define EFI_IFR_INVENTORY_OP 0x21 +#define EFI_IFR_EQ_VAR_VAL_OP 0x22 +#define FRAMEWORK_EFI_IFR_ORDERED_LIST_OP 0x23 +#define FRAMEWORK_EFI_IFR_VARSTORE_OP 0x24 +#define EFI_IFR_VARSTORE_SELECT_OP 0x25 +#define EFI_IFR_VARSTORE_SELECT_PAIR_OP 0x26 +#define EFI_IFR_LAST_OPCODE EFI_IFR_VARSTORE_SELECT_= PAIR_OP +#define EFI_IFR_OEM_OP 0xFE +#define EFI_IFR_NV_ACCESS_COMMAND 0xFF + +// +// Define values for the flags fields in some VFR opcodes. These are +// bitmasks. +// +#define EFI_IFR_FLAG_DEFAULT 0x01 +#define EFI_IFR_FLAG_MANUFACTURING 0x02 +#define EFI_IFR_FLAG_INTERACTIVE 0x04 +#define EFI_IFR_FLAG_NV_ACCESS 0x08 +#define EFI_IFR_FLAG_RESET_REQUIRED 0x10 +#define EFI_IFR_FLAG_LATE_CHECK 0x20 + +#define EFI_NON_DEVICE_CLASS 0x00 ///< Useful when you do no= t want something in the Device Manager. +#define EFI_DISK_DEVICE_CLASS 0x01 +#define EFI_VIDEO_DEVICE_CLASS 0x02 +#define EFI_NETWORK_DEVICE_CLASS 0x04 +#define EFI_INPUT_DEVICE_CLASS 0x08 +#define EFI_ON_BOARD_DEVICE_CLASS 0x10 +#define EFI_OTHER_DEVICE_CLASS 0x20 + +#define EFI_SETUP_APPLICATION_SUBCLASS 0x00 +#define EFI_GENERAL_APPLICATION_SUBCLASS 0x01 +#define EFI_FRONT_PAGE_SUBCLASS 0x02 +#define EFI_SINGLE_USE_SUBCLASS 0x03 ///< Used to display a sin= gle entity ,and then exit. + +/// +/// Used to flag dynamically created op-codes. This is meaningful to the I= FR Library set +/// and the browser because we need to distinguish between compiled NV map= data and created data. +/// We do not allow new entries to be created in the NV map dynamically, b= ut we do need +/// to display this information correctly. To dynamically create op-codes= and assume that their +/// data will be saved, ensure that the NV starting location they refer to= is pre-defined in the +/// NV map. +/// +#define EFI_IFR_FLAG_CREATED 128 + + +#pragma pack(1) +// +// IFR Structure definitions +// +typedef struct { + UINT8 OpCode; + UINT8 Length; +} FRAMEWORK_EFI_IFR_OP_HEADER; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + STRING_REF FormSetTitle; + STRING_REF Help; + EFI_PHYSICAL_ADDRESS CallbackHandle; + UINT16 Class; + UINT16 SubClass; + UINT16 NvDataSize; ///< Set once; the size of= the NV data as defined in the script. +} FRAMEWORK_EFI_IFR_FORM_SET; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 FormId; + STRING_REF FormTitle; +} FRAMEWORK_EFI_IFR_FORM; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 LabelId; +} EFI_IFR_LABEL; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + STRING_REF SubTitle; +} FRAMEWORK_EFI_IFR_SUBTITLE; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + STRING_REF Help; + STRING_REF Text; + STRING_REF TextTwo; + UINT8 Flags; ///< This is included solely f= or purposes of interactive/dynamic support. + UINT16 Key; ///< The value to be passed to= the caller to identify this particular op-code. +} FRAMEWORK_EFI_IFR_TEXT; + +// +// goto +// +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 FormId; + STRING_REF Prompt; + STRING_REF Help; ///< The string Token for the = context-help. + UINT8 Flags; ///< This is included solely f= or purposes of interactive/dynamic support. + UINT16 Key; ///< The value to be passed to= the caller to identify this particular op-code. +} FRAMEWORK_EFI_IFR_REF; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; +} EFI_IFR_END_FORM; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; +} EFI_IFR_END_FORM_SET; + +// +// Also notice that the IFR_ONE_OF and IFR_CHECK_BOX are identical in stru= cture...... +// code assumes this to be true, if this ever changes we need to revisit t= he InitializeTagStructures code +// +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; ///< The ID designating wh= at the question is about... + UINT8 Width; ///< The Size of the Data = being saved. + STRING_REF Prompt; ///< The String Token for = the Prompt. + STRING_REF Help; ///< The string Token for = the context-help. +} FRAMEWORK_EFI_IFR_ONE_OF; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; ///< The offset in NV for = storage of the data. + UINT8 MaxEntries; ///< The maximum number of= options in the ordered list (=3Dsize of NVStore). + STRING_REF Prompt; ///< The string token for = the prompt. + STRING_REF Help; ///< The string token for = the context-help. +} FRAMEWORK_EFI_IFR_ORDERED_LIST; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; ///< The ID designating wh= at the question is about... + UINT8 Width; ///< The Size of the Data = being saved. + STRING_REF Prompt; ///< The String Token for = the Prompt. + STRING_REF Help; ///< The string Token for = the context-help. + UINT8 Flags; ///< If non-zero, it means= that it is the default option. + UINT16 Key; ///< Value to be passed to= caller to identify this particular op-code. +} FRAMEWORK_EFI_IFR_CHECKBOX, EFI_IFR_CHECK_BOX; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + STRING_REF Option; ///< The string token desc= ribing the option. + UINT16 Value; ///< The value associated = with this option that is stored in the NVRAM. + UINT8 Flags; ///< If non-zero, it means= that it is the default option. + UINT16 Key; ///< Value to be passed to= caller to identify this particular op-code. +} FRAMEWORK_EFI_IFR_ONE_OF_OPTION; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; ///< The ID designating wh= at the question is about... + UINT8 Width; ///< The Size of the Data = being saved. + STRING_REF Prompt; ///< The String Token for = the Prompt. + STRING_REF Help; ///< The string Token for = the context-help. + UINT8 Flags; ///< This is included sole= ly for purposes of interactive/dynamic support. + UINT16 Key; ///< The value to be passe= d to caller to identify this particular op-code. + UINT16 Minimum; + UINT16 Maximum; + UINT16 Step; ///< Zero means manual inp= ut. Otherwise, arrow selection is called for. + UINT16 Default; +} FRAMEWORK_EFI_IFR_NUMERIC; + +// +// There is an interesting twist with regards to Time and Date. This is o= ne of the few items which can accept input +// from a user, and may or may not need to use storage in the NVRAM space.= The decided method for determining +// if NVRAM space will be used (only for a TimeOp or DateOp) is: If .Ques= tionId =3D=3D 0 && .Width =3D=3D 0 (normally an +// impossibility) then use system resources to store the data away and not= NV resources. In other words, the setup +// engine will call gRT->SetTime, and gRT->SetDate for the saving of data,= and the values displayed will be from the +// gRT->GetXXXX series of calls. +// +typedef struct { + FRAMEWORK_EFI_IFR_NUMERIC Hour; + FRAMEWORK_EFI_IFR_NUMERIC Minute; + FRAMEWORK_EFI_IFR_NUMERIC Second; +} FRAMEWORK_EFI_IFR_TIME; + +typedef struct { + FRAMEWORK_EFI_IFR_NUMERIC Year; + FRAMEWORK_EFI_IFR_NUMERIC Month; + FRAMEWORK_EFI_IFR_NUMERIC Day; +} FRAMEWORK_EFI_IFR_DATE; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 QuestionId;///< The ID designating wha= t the question is about... + UINT8 Width; ///< The Size of the Data b= eing saved. + STRING_REF Prompt; ///< The String Token for t= he Prompt. + STRING_REF Help; ///< The string Token for t= he context-help. + UINT8 Flags; ///< This is included solel= y for purposes of interactive/dynamic support. + UINT16 Key; ///< The value to be passed= to caller to identify this particular op-code. + UINT8 MinSize; ///< Minimum allowable size= d password. + UINT8 MaxSize; ///< Maximum allowable size= d password. + UINT16 Encoding; +} FRAMEWORK_EFI_IFR_PASSWORD; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; ///< The ID designating wh= at the question is about... + UINT8 Width; ///< The Size of the Data = being saved. + STRING_REF Prompt; ///< The String Token for = the Prompt. + STRING_REF Help; ///< The string Token for = the context-help. + UINT8 Flags; ///< This is included sole= ly for purposes of interactive/dynamic support. + UINT16 Key; ///< The value to be passe= d to caller to identify this particular op-code. + UINT8 MinSize; ///< Minimum allowable siz= ed password. + UINT8 MaxSize; ///< Maximum allowable siz= ed password. +} FRAMEWORK_EFI_IFR_STRING; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; +} EFI_IFR_END_ONE_OF; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 Value; + UINT16 Key; +} EFI_IFR_HIDDEN; + +/// +/// Inconsistent with specification here: +/// The following defintion may not comply with Framework Specification HI= I 0.92. To +/// keep the inconsistant is for implementation needed. +///@{ +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT8 Flags; +} EFI_IFR_SUPPRESS; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT8 Flags; +} EFI_IFR_GRAY_OUT; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + STRING_REF Popup; + UINT8 Flags; +} EFI_IFR_INCONSISTENT; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; ///< The offset into var= iable storage. + UINT8 Width; ///< The size of variabl= e storage. + UINT16 Value; ///< The value to compar= e against. +} FRAMEWORK_EFI_IFR_EQ_ID_VAL; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; ///< The offset into var= iable storage. + UINT8 Width; ///< The size of variabl= e storage. + UINT16 ListLength; + UINT16 ValueList[1]; +} FRAMEWORK_EFI_IFR_EQ_ID_LIST; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 QuestionId1; ///< The offset into var= iable storage for first value to compare. + UINT8 Width; ///< The size of variabl= e storage (must be same for both). + UINT16 QuestionId2; ///< The offset into var= iable storage for second value to compare. +} FRAMEWORK_EFI_IFR_EQ_ID_ID; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 VariableId; ///< The offset into var= iable storage. + UINT16 Value; ///< The value to compar= e against. +} EFI_IFR_EQ_VAR_VAL; +///@} + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; +} FRAMEWORK_EFI_IFR_AND; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; +} FRAMEWORK_EFI_IFR_OR; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; +} FRAMEWORK_EFI_IFR_NOT; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; +} EFI_IFR_END_EXPR, EFI_IFR_END_IF; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 FormId; + STRING_REF Prompt; + STRING_REF Help; + UINT8 Flags; + UINT16 Key; +} EFI_IFR_SAVE_DEFAULTS; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + STRING_REF Help; + STRING_REF Text; + STRING_REF TextTwo; ///< Optional text. +} EFI_IFR_INVENTORY; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; ///< GUID for the variable. + UINT16 VarId; ///< The variable store ID= , as referenced elsewhere in the form. + UINT16 Size; ///< The size of the varia= ble storage. +} FRAMEWORK_EFI_IFR_VARSTORE; + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 VarId; ///< The variable store ID= , as referenced elsewhere in the form. +} EFI_IFR_VARSTORE_SELECT; + +/// +/// Used for the ideqid VFR statement where two variable stores may be ref= erenced in the +/// same VFR statement. +/// A browser should treat this as an FRAMEWORK_EFI_IFR_VARSTORE_SELECT st= atement and assume that all following +/// IFR opcodes use the VarId as defined here. +/// +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + UINT16 VarId; ///< The variable stor= e ID, as referenced elsewhere in the form. + UINT16 SecondaryVarId; ///< The variable stor= e ID, as referenced elsewhere in the form. +} EFI_IFR_VARSTORE_SELECT_PAIR; + +/// +/// Save defaults and restore defaults have same structure. +/// +#define EFI_IFR_RESTORE_DEFAULTS EFI_IFR_SAVE_DEFAULTS + +typedef struct { + FRAMEWORK_EFI_IFR_OP_HEADER Header; + STRING_REF Title; ///< The string token fo= r the banner title. + UINT16 LineNumber; ///< 1-based line number. + UINT8 Alignment; ///< Left, center, or ri= ght-aligned. +} EFI_IFR_BANNER; + +#define EFI_IFR_BANNER_ALIGN_LEFT 0 +#define EFI_IFR_BANNER_ALIGN_CENTER 1 +#define EFI_IFR_BANNER_ALIGN_RIGHT 2 +#define EFI_IFR_BANNER_TIMEOUT 0xFF + +#pragma pack() + +#endif diff --git a/OvmfPkg/Csm/Include/Framework/Hob.h b/OvmfPkg/Csm/Include/Fram= ework/Hob.h new file mode 100644 index 0000000000..f6a71fabe4 --- /dev/null +++ b/OvmfPkg/Csm/Include/Framework/Hob.h @@ -0,0 +1,28 @@ +/** @file + This file defines the data structures per HOB specification v0.9. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Revision Reference: + These definitions are from the HOB Spec 0.9 that were not adopted by the= PI specifications. + +**/ + +#ifndef _HOB_H_ +#define _HOB_H_ + +/// +/// Capsule volume HOB -- identical to a firmware volume. +/// This macro is defined to comply with the hob Framework Spec. And the m= arco was +/// retired in the PI1.0 specification. +/// +#define EFI_HOB_TYPE_CV 0x0008 + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 Length; +} EFI_HOB_CAPSULE_VOLUME; + +#endif diff --git a/OvmfPkg/Csm/Include/Framework/StatusCode.h b/OvmfPkg/Csm/Inclu= de/Framework/StatusCode.h new file mode 100644 index 0000000000..753029c13c --- /dev/null +++ b/OvmfPkg/Csm/Include/Framework/StatusCode.h @@ -0,0 +1,155 @@ +/** @file + Status Code Definitions, according to Intel Platform Innovation Framework + for EFI Status Codes Specification + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Revision Reference: + Intel Platform Innovation Framework for EFI Status Codes Specification + Version 0.92. + +**/ + +#ifndef _FRAMEWORK_STATUS_CODE_H_ +#define _FRAMEWORK_STATUS_CODE_H_ + +// +// Required for X64 defines for CPU exception types +// +#include + +/// +/// Software Class DXE BS Driver Subclass Progress Code definitions. +/// +/// Inconsistent with specification here: +/// The Framework Specification, StatusCodes 0.92, does not define the mac= ros. +/// +///@{ +#define EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS (EFI_SUBCLASS_SPECIF= IC | 0x00000005) +#define EFI_SW_DXE_BS_PC_VERIFYING_PASSWORD (EFI_SUBCLASS_SPECIF= IC | 0x00000006) +///@} + +/// +/// Software Class DXE RT Driver Subclass Progress Code definitions. +/// +/// Inconsistent with specification here: +/// The Framework Specification, StatusCodes 0.92, does not define the mac= ros. +/// +///@{ +#define EFI_SW_DXE_RT_PC_S0 (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_DXE_RT_PC_S1 (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_DXE_RT_PC_S2 (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_DXE_RT_PC_S3 (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_DXE_RT_PC_S4 (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_DXE_RT_PC_S5 (EFI_SUBCLASS_SPECIFIC | 0x00000005) +///@} + +/// +/// Software Subclass definitions. +/// +/// Inconsistent with specification here: +/// The Framework Specification, StatusCodes 0.92, does not define the mac= ros. +/// +#define EFI_SOFTWARE_X64_EXCEPTION (EFI_SOFTWARE | 0x00130000) + +/// +/// Software Class X64 Exception Subclass Error Code definitions. +/// These exceptions are derived from the debug protocol definitions in th= e EFI +/// specification. +/// +/// Inconsistent with specification here: +/// The Framework Specification, StatusCodes 0.92, does not define the mac= ros. +/// +///@{ +#define EFI_SW_EC_X64_DIVIDE_ERROR EXCEPT_X64_DIVIDE_ERROR +#define EFI_SW_EC_X64_DEBUG EXCEPT_X64_DEBUG +#define EFI_SW_EC_X64_NMI EXCEPT_X64_NMI +#define EFI_SW_EC_X64_BREAKPOINT EXCEPT_X64_BREAKPOINT +#define EFI_SW_EC_X64_OVERFLOW EXCEPT_X64_OVERFLOW +#define EFI_SW_EC_X64_BOUND EXCEPT_X64_BOUND +#define EFI_SW_EC_X64_INVALID_OPCODE EXCEPT_X64_INVALID_OPCODE +#define EFI_SW_EC_X64_DOUBLE_FAULT EXCEPT_X64_DOUBLE_FAULT +#define EFI_SW_EC_X64_INVALID_TSS EXCEPT_X64_INVALID_TSS +#define EFI_SW_EC_X64_SEG_NOT_PRESENT EXCEPT_X64_SEG_NOT_PRESENT +#define EFI_SW_EC_X64_STACK_FAULT EXCEPT_X64_STACK_FAULT +#define EFI_SW_EC_X64_GP_FAULT EXCEPT_X64_GP_FAULT +#define EFI_SW_EC_X64_PAGE_FAULT EXCEPT_X64_PAGE_FAULT +#define EFI_SW_EC_X64_FP_ERROR EXCEPT_X64_FP_ERROR +#define EFI_SW_EC_X64_ALIGNMENT_CHECK EXCEPT_X64_ALIGNMENT_CHECK +#define EFI_SW_EC_X64_MACHINE_CHECK EXCEPT_X64_MACHINE_CHECK +#define EFI_SW_EC_X64_SIMD EXCEPT_X64_SIMD +///@} + +/// +/// Software Class EFI After Life Subclass Progress Code definitions. +/// +///@{ +#define EFI_SW_AL_PC_ENTRY_POINT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_AL_PC_RETURN_TO_LAST (EFI_SUBCLASS_SPECIFIC | 0x00000001) +///@} + +/// +/// Software Class DXE Core Subclass Error Code definitions. +/// +/// Inconsistent with specification here: +/// The Framework Specification, StatusCodes 0.92, does not define the mac= ros. +/// +#define EFI_SW_CSM_LEGACY_ROM_INIT (EFI_SUBCLASS_SPECIFIC |= 0x00000000) + +/// +/// IO Bus Class ATA/ATAPI Subclass Progress Code definitions. +/// +/// +/// Inconsistent with specification here: +/// The Framework Specification, StatusCodes 0.92, does not define the mac= ros. +/// +///@{ +#define EFI_IOB_ATA_BUS_SMART_ENABLE (EFI_SUBCLASS_SPECIFIC | 0x0= 0000000) +#define EFI_IOB_ATA_BUS_SMART_DISABLE (EFI_SUBCLASS_SPECIFIC | 0x0= 0000001) +#define EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD (EFI_SUBCLASS_SPECIFIC | 0x0= 0000002) +#define EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD (EFI_SUBCLASS_SPECIFIC | 0x0= 0000003) +///@} + +/// +/// IO Bus Class ATA/ATAPI Subclass Error Code definitions. +/// +/// +/// Inconsistent with specification here: +/// The Framework Specification, StatusCodes 0.92, does not define the mac= ros. +/// +///@{ +#define EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED (EFI_SUBCLASS_SPECIFIC | 0x000= 00000) +#define EFI_IOB_ATA_BUS_SMART_DISABLED (EFI_SUBCLASS_SPECIFIC | 0x000= 00001) +///@} + +/// +/// The reason that the processor was disabled. +/// +/// Inconsistent with specification here: +/// The Framework Specification, StatusCodes 0.92, does not define the mac= ros. +/// +///@{ +#define EFI_CPU_CAUSE_NOT_DISABLED 0x0000 +///@} + +/// +/// Software Class PEI Module Subclass Progress Code definitions. +/// +///@{ +#define EFI_SW_PEIM_PC_RECOVERY_BEGIN EFI_SW_PEI_PC_RECOVERY_BEGIN +#define EFI_SW_PEIM_PC_CAPSULE_LOAD EFI_SW_PEI_PC_CAPSULE_LOAD +#define EFI_SW_PEIM_PC_CAPSULE_START EFI_SW_PEI_PC_CAPSULE_START +#define EFI_SW_PEIM_PC_RECOVERY_USER EFI_SW_PEI_PC_RECOVERY_USER +#define EFI_SW_PEIM_PC_RECOVERY_AUTO EFI_SW_PEI_PC_RECOVERY_AUTO +///@} + +/// +/// Software Class PEI Core Subclass Error Code definitions. +/// +///@{ +#define EFI_SW_PEIM_CORE_EC_DXE_CORRUPT EFI_SW_PEI_CORE_EC_DXE_CORRU= PT +#define EFI_SW_PEIM_CORE_EC_DXEIPL_NOT_FOUND EFI_SW_PEI_CORE_EC_DXEIPL_NO= T_FOUND +///@} + +#endif diff --git a/OvmfPkg/Csm/Include/FrameworkDxe.h b/OvmfPkg/Csm/Include/Frame= workDxe.h new file mode 100644 index 0000000000..1d801960fe --- /dev/null +++ b/OvmfPkg/Csm/Include/FrameworkDxe.h @@ -0,0 +1,26 @@ +/** @file + The root header file that provides Framework extension to UEFI/PI for mo= dules. It can be included by + DXE, RUNTIME and SMM type modules that use Framework definitions. + + + This header file includes Framework extension definitions common to DXE + modules. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _FRAMEWORK_DXE_H_ +#define _FRAMEWORK_DXE_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/OvmfPkg/Csm/Include/Guid/LegacyBios.h b/OvmfPkg/Csm/Include/Gu= id/LegacyBios.h new file mode 100644 index 0000000000..e35fbff8d5 --- /dev/null +++ b/OvmfPkg/Csm/Include/Guid/LegacyBios.h @@ -0,0 +1,29 @@ +/** @file + Defines a Tag GUID used to mark a UEFI legacy BIOS thunk driver based + on legacy BIOS services and legacy option ROM. This Tag GUID must be ins= talled on + the ImageHandle of any module that follows the EFI Driver Model and uses + the Int86() or FarCall() services of the Legacy Bios Protocol to produce + a standard UEFI I/O Protocol. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _LEGACY_BIOS_H_ +#define _LEGACY_BIOS_H_ + +/// +/// The Global ID for the Legacy BIOS GUID that must be installed onto the= ImageHandle +/// of any module follows the EFI Driver Model and uses the Int86() or Far= Call() +/// services of the Legacy BIOS Protocol to produce a standard UEFI I/O Pr= otocol. +/// +#define EFI_LEGACY_BIOS_GUID \ + { \ + 0x2e3044ac, 0x879f, 0x490f, {0x97, 0x60, 0xbb, 0xdf, 0xaf, 0x69, 0x5f,= 0x50 } \ + } + +extern EFI_GUID gEfiLegacyBiosGuid; + +#endif diff --git a/OvmfPkg/Csm/Include/Guid/LegacyDevOrder.h b/OvmfPkg/Csm/Includ= e/Guid/LegacyDevOrder.h new file mode 100644 index 0000000000..8ec3de5e38 --- /dev/null +++ b/OvmfPkg/Csm/Include/Guid/LegacyDevOrder.h @@ -0,0 +1,39 @@ +/** @file + Guid of a NV Variable which store the information about the + FD/HD/CD/NET/BEV order. + +Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __LEGACY_DEV_ORDER_VARIABLE_GUID_H__ +#define __LEGACY_DEV_ORDER_VARIABLE_GUID_H__ + +/// +/// Name and Guid of a NV Variable which stores the information about the +/// FD/HD/CD/NET/BEV order +/// +#define EFI_LEGACY_DEV_ORDER_VARIABLE_GUID \ + { \ + 0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0= x52} \ + } + +typedef UINT8 BBS_TYPE; + +#pragma pack(1) +typedef struct { + BBS_TYPE BbsType; + /// + /// Length =3D sizeof (UINT16) + sizeof (Data) + /// + UINT16 Length; + UINT16 Data[1]; +} LEGACY_DEV_ORDER_ENTRY; +#pragma pack() + +#define VAR_LEGACY_DEV_ORDER L"LegacyDevOrder" + +extern EFI_GUID gEfiLegacyDevOrderVariableGuid; + +#endif diff --git a/OvmfPkg/Csm/Include/Protocol/FirmwareVolume.h b/OvmfPkg/Csm/In= clude/Protocol/FirmwareVolume.h new file mode 100644 index 0000000000..5e0216c765 --- /dev/null +++ b/OvmfPkg/Csm/Include/Protocol/FirmwareVolume.h @@ -0,0 +1,340 @@ +/** @file + This file declares the Firmware Volume Protocol. + + The Firmware Volume Protocol provides file-level access to the firmware = volume. + Each firmware volume driver must produce an instance of the Firmware Vol= ume + Protocol if the firmware volume is to be visible to the system. The Firm= ware + Volume Protocol also provides mechanisms for determining and modifying s= ome + attributes of the firmware volume. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Revision Reference: + This protocol is defined in Firmware Volume specification. + Version 0.9. + +**/ + +#ifndef _FIRMWARE_VOLUME_H_ +#define _FIRMWARE_VOLUME_H_ + + +// +// Firmware Volume Protocol GUID definition +// +#define EFI_FIRMWARE_VOLUME_PROTOCOL_GUID \ + { \ + 0x389F751F, 0x1838, 0x4388, {0x83, 0x90, 0xCD, 0x81, 0x54, 0xBD, 0x27,= 0xF8 } \ + } + +#define FV_DEVICE_SIGNATURE SIGNATURE_32 ('_', 'F', 'V', '_') + +typedef struct _EFI_FIRMWARE_VOLUME_PROTOCOL EFI_FIRMWARE_VOLUME_PROTOCOL; + +// +// FRAMEWORK_EFI_FV_ATTRIBUTES bit definitions +// +typedef UINT64 FRAMEWORK_EFI_FV_ATTRIBUTES; + +// +// ************************************************************ +// FRAMEWORK_EFI_FV_ATTRIBUTES bit definitions +// ************************************************************ +// +#define EFI_FV_READ_DISABLE_CAP 0x0000000000000001ULL +#define EFI_FV_READ_ENABLE_CAP 0x0000000000000002ULL +#define EFI_FV_READ_STATUS 0x0000000000000004ULL + +#define EFI_FV_WRITE_DISABLE_CAP 0x0000000000000008ULL +#define EFI_FV_WRITE_ENABLE_CAP 0x0000000000000010ULL +#define EFI_FV_WRITE_STATUS 0x0000000000000020ULL + +#define EFI_FV_LOCK_CAP 0x0000000000000040ULL +#define EFI_FV_LOCK_STATUS 0x0000000000000080ULL +#define EFI_FV_WRITE_POLICY_RELIABLE 0x0000000000000100ULL + +#define EFI_FV_ALIGNMENT_CAP 0x0000000000008000ULL +#define EFI_FV_ALIGNMENT_2 0x0000000000010000ULL +#define EFI_FV_ALIGNMENT_4 0x0000000000020000ULL +#define EFI_FV_ALIGNMENT_8 0x0000000000040000ULL +#define EFI_FV_ALIGNMENT_16 0x0000000000080000ULL +#define EFI_FV_ALIGNMENT_32 0x0000000000100000ULL +#define EFI_FV_ALIGNMENT_64 0x0000000000200000ULL +#define EFI_FV_ALIGNMENT_128 0x0000000000400000ULL +#define EFI_FV_ALIGNMENT_256 0x0000000000800000ULL +#define EFI_FV_ALIGNMENT_512 0x0000000001000000ULL +#define EFI_FV_ALIGNMENT_1K 0x0000000002000000ULL +#define EFI_FV_ALIGNMENT_2K 0x0000000004000000ULL +#define EFI_FV_ALIGNMENT_4K 0x0000000008000000ULL +#define EFI_FV_ALIGNMENT_8K 0x0000000010000000ULL +#define EFI_FV_ALIGNMENT_16K 0x0000000020000000ULL +#define EFI_FV_ALIGNMENT_32K 0x0000000040000000ULL +#define EFI_FV_ALIGNMENT_64K 0x0000000080000000ULL + +// +// Protocol API definitions +// + +/** + Retrieves attributes, insures positive polarity of attribute bits, and r= eturns + resulting attributes in an output parameter. + + @param This Indicates the EFI_FIRMWARE_VOLUME_PROTOCOL= instance. + @param Attributes Output buffer containing attributes. + + @retval EFI_SUCCESS The firmware volume attributes were return= ed. +**/ +typedef +EFI_STATUS +(EFIAPI *FRAMEWORK_EFI_FV_GET_ATTRIBUTES)( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + OUT FRAMEWORK_EFI_FV_ATTRIBUTES *Attributes + ); + +/** + Sets volume attributes + + @param This Indicates the EFI_FIRMWARE_VOLUME_PROTOCOL= instance. + @param Attributes On input, Attributes is a pointer to an + EFI_FV_ATTRIBUTES containing the desired f= irmware + volume settings. On successful return, it = contains + the new settings of the firmware volume. On + unsuccessful return, Attributes is not mod= ified + and the firmware volume settings are not c= hanged. + + @retval EFI_INVALID_PARAMETER A bit in Attributes was invalid. + @retval EFI_SUCCESS The requested firmware volume attributes w= ere set + and the resulting EFI_FV_ATTRIBUTES is ret= urned in + Attributes. + @retval EFI_ACCESS_DENIED The Device is locked and does not permit m= odification. + +**/ +typedef +EFI_STATUS +(EFIAPI *FRAMEWORK_EFI_FV_SET_ATTRIBUTES)( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN OUT FRAMEWORK_EFI_FV_ATTRIBUTES *Attributes + ); + +/** + Read the requested file (NameGuid) or file information from the firmware= volume + and returns data in Buffer. + + @param This The EFI_FIRMWARE_VOLUME_PROTOCOL instance. + @param NameGuid The pointer to EFI_GUID, which is the file= name of + the file to read. + @param Buffer The pointer to pointer to buffer in which = contents of file are returned. +
+ If Buffer is NULL, only type, attributes, = and size + are returned as there is no output buffer. +
+ If Buffer !=3D NULL and *Buffer =3D=3D NUL= L, the output + buffer is allocated from BS pool by ReadFi= le. +
+ If Buffer !=3D NULL and *Buffer !=3D NULL,= the output + buffer has been allocated by the caller an= d is being + passed in. + @param BufferSize On input: The buffer size. On output: The = size + required to complete the read. + @param FoundType The pointer to the type of the file whose = data + is returned. + @param FileAttributes The pointer to attributes of the file whos= e data + is returned. + @param AuthenticationStatus The pointer to the authentication status o= f the data. + + @retval EFI_SUCCESS The call completed successfully. + @retval EFI_WARN_BUFFER_TOO_SMALL The buffer is too small to contain the= requested output. + The buffer filled, and the output is t= runcated. + @retval EFI_NOT_FOUND NameGuid was not found in the firmware= volume. + @retval EFI_DEVICE_ERROR A hardware error occurred when attempt= ing to + access the firmware volume. + @retval EFI_ACCESS_DENIED The firmware volume is configured to d= isallow reads. + @retval EFI_OUT_OF_RESOURCES An allocation failure occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *FRAMEWORK_EFI_FV_READ_FILE)( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN EFI_GUID *NameGuid, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT EFI_FV_FILETYPE *FoundType, + OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes, + OUT UINT32 *AuthenticationStatus + ); + +/** + Read the requested section from the specified file and returns data in B= uffer. + + @param This Indicates the EFI_FIRMWARE_VOLUME_PROTOCOL= instance. + @param NameGuid Filename identifying the file from which t= o read. + @param SectionType The section type to retrieve. + @param SectionInstance The instance of SectionType to retrieve. + @param Buffer Pointer to pointer to buffer in which cont= ents of + a file are returned. +
+ If Buffer is NULL, only type, attributes, = and size + are returned as there is no output buffer. +
+ If Buffer !=3D NULL and *Buffer =3D=3D NUL= L, the output + buffer is allocated from BS pool by ReadFi= le. +
+ If Buffer !=3D NULL and *Buffer !=3D NULL,= the output + buffer has been allocated by the caller an= d is being + passed in. + @param BufferSize The pointer to the buffer size passed in, = and on + output the size required to complete the r= ead. + @param AuthenticationStatus The pointer to the authentication status o= f the data. + + @retval EFI_SUCCESS The call completed successfully. + @retval EFI_WARN_BUFFER_TOO_SMALL The buffer is too small to contain th= e requested output. + The buffer is filled and the output i= s truncated. + @retval EFI_OUT_OF_RESOURCES An allocation failure occurred. + @retval EFI_NOT_FOUND The name was not found in the firmwar= e volume. + @retval EFI_DEVICE_ERROR A hardware error occurred when attemp= ting to + access the firmware volume. + @retval EFI_ACCESS_DENIED The firmware volume is configured to = disallow reads. + +**/ +typedef +EFI_STATUS +(EFIAPI *FRAMEWORK_EFI_FV_READ_SECTION)( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus + ); + +typedef UINT32 FRAMEWORK_EFI_FV_WRITE_POLICY; + +#define FRAMEWORK_EFI_FV_UNRELIABLE_WRITE 0x00000000 +#define FRAMEWORK_EFI_FV_RELIABLE_WRITE 0x00000001 + +typedef struct { + EFI_GUID *NameGuid; + EFI_FV_FILETYPE Type; + EFI_FV_FILE_ATTRIBUTES FileAttributes; + VOID *Buffer; + UINT32 BufferSize; +} FRAMEWORK_EFI_FV_WRITE_FILE_DATA; + +/** + Write the supplied file (NameGuid) to the FV. + + @param This Indicates the EFI_FIRMWARE_VOLUME_PROTOCOL= instance. + @param NumberOfFiles Indicates the number of file records point= ed to + by FileData. + @param WritePolicy Indicates the level of reliability of the = write + with respect to things like power failure = events. + @param FileData A pointer to an array of EFI_FV_WRITE_FILE= _DATA + structures. Each element in the array indi= cates + a file to write, and there are NumberOfFil= es + elements in the input array. + + @retval EFI_SUCCESS The write completed successfully. + @retval EFI_OUT_OF_RESOURCES The firmware volume does not have enough f= ree + space to store file(s). + @retval EFI_DEVICE_ERROR A hardware error occurred when attempting = to + access the firmware volume. + @retval EFI_WRITE_PROTECTED The firmware volume is configured to disal= low writes. + @retval EFI_NOT_FOUND A delete was requested, but the requested = file was + not found in the firmware volume. + @retval EFI_INVALID_PARAMETER A delete was requested with a multiple fil= e write. + An unsupported WritePolicy was requested. + An unknown file type was specified. + A file system specific error has occurred. +**/ +typedef +EFI_STATUS +(EFIAPI *FRAMEWORK_EFI_FV_WRITE_FILE)( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN UINT32 NumberOfFiles, + IN FRAMEWORK_EFI_FV_WRITE_POLICY WritePolicy, + IN FRAMEWORK_EFI_FV_WRITE_FILE_DATA *FileData + ); + +/** + Given the input key, search for the next matching file in the volume. + + @param This Indicates the EFI_FIRMWARE_VOLUME_PROTOCOL= instance. + @param Key Pointer to a caller allocated buffer that = contains + an implementation-specific key that is use= d to track + where to begin searching on successive cal= ls. + @param FileType The pointer to the file type to filter for. + @param NameGuid The pointer to Guid filename of the file f= ound. + @param Attributes The pointer to Attributes of the file foun= d. + @param Size The pointer to Size in bytes of the file f= ound. + + @retval EFI_SUCCESS The output parameters are filled with data= obtained from + the first matching file that was found. + @retval EFI_NOT_FOUND No files of type FileType were found. + @retval EFI_DEVICE_ERROR A hardware error occurred when attempting = to access + the firmware volume. + @retval EFI_ACCESS_DENIED The firmware volume is configured to disal= low reads. + +**/ +typedef +EFI_STATUS +(EFIAPI *FRAMEWORK_EFI_FV_GET_NEXT_FILE)( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN OUT VOID *Key, + IN OUT EFI_FV_FILETYPE *FileType, + OUT EFI_GUID *NameGuid, + OUT EFI_FV_FILE_ATTRIBUTES *Attributes, + OUT UINTN *Size + ); + +// +// Protocol interface structure +// +struct _EFI_FIRMWARE_VOLUME_PROTOCOL { + /// + /// Retrieves volume capabilities and current settings. + /// + FRAMEWORK_EFI_FV_GET_ATTRIBUTES GetVolumeAttributes; + + /// + /// Modifies the current settings of the firmware volume. + /// + FRAMEWORK_EFI_FV_SET_ATTRIBUTES SetVolumeAttributes; + + /// + /// Reads an entire file from the firmware volume. + /// + FRAMEWORK_EFI_FV_READ_FILE ReadFile; + + /// + /// Reads a single section from a file into a buffer. + /// + FRAMEWORK_EFI_FV_READ_SECTION ReadSection; + + /// + /// Writes an entire file into the firmware volume. + /// + FRAMEWORK_EFI_FV_WRITE_FILE WriteFile; + + /// + /// Provides service to allow searching the firmware volume. + /// + FRAMEWORK_EFI_FV_GET_NEXT_FILE GetNextFile; + + /// + /// Data field that indicates the size in bytes of the Key input buffer= for + /// the GetNextFile() API. + /// + UINT32 KeySize; + + /// + /// Handle of the parent firmware volume. + /// + EFI_HANDLE ParentHandle; +}; + +extern EFI_GUID gEfiFirmwareVolumeProtocolGuid; + +#endif diff --git a/OvmfPkg/Csm/Include/Protocol/IsaAcpi.h b/OvmfPkg/Csm/Include/P= rotocol/IsaAcpi.h new file mode 100644 index 0000000000..12aeb1227c --- /dev/null +++ b/OvmfPkg/Csm/Include/Protocol/IsaAcpi.h @@ -0,0 +1,298 @@ +/** @file + EFI ISA ACPI Protocol is used to enumerate and manage all the ISA contro= llers on + the platform's ISA Bus. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __ISA_ACPI_H_ +#define __ISA_ACPI_H_ + +/// +/// Global ID for the EFI ISA ACPI Protocol. +/// +#define EFI_ISA_ACPI_PROTOCOL_GUID \ + { \ + 0x64a892dc, 0x5561, 0x4536, { 0x92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33= , 0x55 } \ + } + +/// +/// Forward declaration fo the EFI ISA ACPI Protocol +/// +typedef struct _EFI_ISA_ACPI_PROTOCOL EFI_ISA_ACPI_PROTOCOL; + +/// +/// ISA ACPI Protocol interrupt resource attributes. +/// +#define EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE 0x01 ///< Edge = triggered interrupt on a rising edge. +#define EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_EDGE_SENSITIVE 0x02 ///< Edge = triggered interrupt on a falling edge. +#define EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_LEVEL_SENSITIVE 0x04 ///< Level= sensitive interrupt active high. +#define EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_LEVEL_SENSITIVE 0x08 ///< Level= sensitive interrupt active low. + +/// +/// ISA ACPI Protocol DMA resource attributes. +/// +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_MASK 0x03 ///< Bit m= ask of supported DMA speed attributes. +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_COMPATIBILITY 0x00 ///< ISA c= ontroller supports compatibility mode DMA transfers. +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_A 0x01 ///< ISA c= ontroller supports type A DMA transfers. +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_B 0x02 ///< ISA c= ontroller supports type B DMA transfers. +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_F 0x03 ///< ISA c= ontroller supports type F DMA transfers. +#define EFI_ISA_ACPI_DMA_COUNT_BY_BYTE 0x04 ///< ISA c= ontroller increments DMA address by bytes (8-bit). +#define EFI_ISA_ACPI_DMA_COUNT_BY_WORD 0x08 ///< ISA c= ontroller increments DMA address by words (16-bit). +#define EFI_ISA_ACPI_DMA_BUS_MASTER 0x10 ///< ISA c= ontroller is a DMA bus master. +#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_8_BIT 0x20 ///< ISA c= ontroller only supports 8-bit DMA transfers. +#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_8_BIT_AND_16_BIT 0x40 ///< ISA c= ontroller both 8-bit and 16-bit DMA transfers. +#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_16_BIT 0x80 ///< ISA c= ontroller only supports 16-bit DMA transfers. + +/// +/// ISA ACPI Protocol MMIO resource attributes +/// +#define EFI_ISA_ACPI_MEMORY_WIDTH_MASK 0x03 ///< Bit m= ask of supported ISA memory width attributes. +#define EFI_ISA_ACPI_MEMORY_WIDTH_8_BIT 0x00 ///< ISA M= MIO region only supports 8-bit access. +#define EFI_ISA_ACPI_MEMORY_WIDTH_16_BIT 0x01 ///< ISA M= MIO region only supports 16-bit access. +#define EFI_ISA_ACPI_MEMORY_WIDTH_8_BIT_AND_16_BIT 0x02 ///< ISA M= MIO region supports both 8-bit and 16-bit access. +#define EFI_ISA_ACPI_MEMORY_WRITEABLE 0x04 ///< ISA M= MIO region supports write transactions. +#define EFI_ISA_ACPI_MEMORY_CACHEABLE 0x08 ///< ISA M= MIO region supports being cached. +#define EFI_ISA_ACPI_MEMORY_SHADOWABLE 0x10 ///< ISA M= MIO region may be shadowed. +#define EFI_ISA_ACPI_MEMORY_EXPANSION_ROM 0x20 ///< ISA M= MIO region is an expansion ROM. + +/// +/// ISA ACPI Protocol I/O resource attributes +/// +#define EFI_ISA_ACPI_IO_DECODE_10_BITS 0x01 ///< ISA = controllers uses a 10-bit address decoder for I/O cycles. +#define EFI_ISA_ACPI_IO_DECODE_16_BITS 0x02 ///< ISA = controllers uses a 16-bit address decoder for I/O cycles. + +/// +/// EFI ISA ACPI resource type +/// +typedef enum { + EfiIsaAcpiResourceEndOfList, ///< Marks the end if a resource list. + EfiIsaAcpiResourceIo, ///< ISA I/O port resource range. + EfiIsaAcpiResourceMemory, ///< ISA MMIO resource range. + EfiIsaAcpiResourceDma, ///< ISA DMA resource. + EfiIsaAcpiResourceInterrupt ///< ISA interrupt resource. +} EFI_ISA_ACPI_RESOURCE_TYPE; + +/// +/// EFI ISA ACPI generic resource structure +/// +typedef struct { + EFI_ISA_ACPI_RESOURCE_TYPE Type; ///< The type of resource (I/O= , MMIO, DMA, Interrupt). + UINT32 Attribute; ///< Bit mask of attributes as= sociated with this resource. See EFI_ISA_ACPI_xxx macros for valid combina= tions. + UINT32 StartRange; ///< The start of the resource= range. + UINT32 EndRange; ///< The end of the resource r= ange. +} EFI_ISA_ACPI_RESOURCE; + +/// +/// EFI ISA ACPI resource device identifier +/// +typedef struct { + UINT32 HID; ///< The ACPI Hardware Identifier value associated with a= n ISA controller. Matchs ACPI DSDT contents. + UINT32 UID; ///< The ACPI Unique Identifier value associated with an = ISA controller. Matches ACPI DSDT contents. +} EFI_ISA_ACPI_DEVICE_ID; + +/// +/// EFI ISA ACPI resource list +/// +typedef struct { + EFI_ISA_ACPI_DEVICE_ID Device; ///< The ACPI HID/UID associate= d with an ISA controller. + EFI_ISA_ACPI_RESOURCE *ResourceItem; ///< A pointer to the list of r= esources associated with an ISA controller. +} EFI_ISA_ACPI_RESOURCE_LIST; + +/** + Enumerates the ISA controllers on an ISA bus. + + This service allows all the ISA controllers on an ISA bus to be enumerat= ed. If + Device is a pointer to a NULL value, then the first ISA controller on th= e ISA + bus is returned in Device and EFI_SUCCESS is returned. If Device is a p= ointer + to a value that was returned on a prior call to DeviceEnumerate(), then = the next + ISA controller on the ISA bus is returned in Device and EFI_SUCCESS is r= eturned. + If Device is a pointer to the last ISA controller on the ISA bus, then + EFI_NOT_FOUND is returned. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. + @param[out] Device The pointer to an ISA controller named by ACPI HID/= UID. + + @retval EFI_SUCCESS The next ISA controller on the ISA bus was return= ed. + @retval EFI_NOT_FOUND No device found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_DEVICE_ENUMERATE)( + IN EFI_ISA_ACPI_PROTOCOL *This, + OUT EFI_ISA_ACPI_DEVICE_ID **Device + ); + +/** + Sets the power state of an ISA controller. + + This services sets the power state of the ISA controller specified by De= vice to + the power state specified by OnOff. TRUE denotes on, FALSE denotes off. + If the power state is sucessfully set on the ISA Controller, then + EFI_SUCCESS is returned. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. + @param[in] Device The pointer to an ISA controller named by ACPI HID/U= ID. + @param[in] OnOff TRUE denotes on, FALSE denotes off. + + @retval EFI_SUCCESS Successfully set the power state of the ISA contro= ller. + @retval Other The ISA controller could not be placed in the requ= ested power state. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_SET_DEVICE_POWER)( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN BOOLEAN OnOff + ); + +/** + Retrieves the current set of resources associated with an ISA controller. + + Retrieves the set of I/O, MMIO, DMA, and interrupt resources currently + assigned to the ISA controller specified by Device. These resources + are returned in ResourceList. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL insta= nce. + @param[in] Device The pointer to an ISA controller named by ACPI= HID/UID. + @param[out] ResourceList The pointer to the current resource list for D= evice. + + @retval EFI_SUCCESS Successfully retrieved the current resource list. + @retval EFI_NOT_FOUND The resource list could not be retrieved. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_GET_CUR_RESOURCE)( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList + ); + +/** + Retrieves the set of possible resources that may be assigned to an ISA c= ontroller + with SetResource(). + + Retrieves the possible sets of I/O, MMIO, DMA, and interrupt resources f= or the + ISA controller specified by Device. The sets are returned in ResourceLi= st. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL inst= ance. + @param[in] Device The pointer to an ISA controller named by ACP= I HID/UID. + @param[out] ResourceList The pointer to the returned list of resource = lists. + + @retval EFI_UNSUPPORTED This service is not supported. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_GET_POS_RESOURCE)( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList + ); + +/** + Assigns resources to an ISA controller. + + Assigns the I/O, MMIO, DMA, and interrupt resources specified by Resourc= eList + to the ISA controller specified by Device. ResourceList must match a re= source list returned by GetPosResource() for the same ISA controller. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL insta= nce. + @param[in] Device The pointer to an ISA controller named by ACPI= HID/UID. + @param[in] ResourceList The pointer to a resources list that must be o= ne of the + resource lists returned by GetPosResource() fo= r the + ISA controller specified by Device. + + @retval EFI_SUCCESS Successfully set resources on the ISA controller. + @retval Other The resources could not be set for the ISA controll= er. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_SET_RESOURCE)( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN EFI_ISA_ACPI_RESOURCE_LIST *ResourceList + ); + +/** + Enables or disables an ISA controller. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. + @param[in] Device The pointer to the ISA controller to enable/disable. + @param[in] Enable TRUE to enable the ISA controller. FALSE to disable= the + ISA controller. + + @retval EFI_SUCCESS Successfully enabled/disabled the ISA controller. + @retval Other The ISA controller could not be placed in the requ= ested state. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_ENABLE_DEVICE)( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN BOOLEAN Enable + ); + +/** + Initializes an ISA controller, so that it can be used. This service mus= t be called + before SetResource(), EnableDevice(), or SetPower() will behave as expec= ted. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. + @param[in] Device The pointer to an ISA controller named by ACPI HID/U= ID. + + @retval EFI_SUCCESS Successfully initialized an ISA controller. + @retval Other The ISA controller could not be initialized. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_INIT_DEVICE)( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device + ); + +/** + Initializes all the HW states required for the ISA controllers on the IS= A bus + to be enumerated and managed by the rest of the services in this proroto= l. + This service must be called before any of the other services in this + protocol will function as expected. + + @param[in] This The pointer to the EFI_ISA_ACPI_PROTOCOL instance. + + @retval EFI_SUCCESS Successfully initialized all required hardware sta= tes. + @retval Other The ISA interface could not be initialized. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_INTERFACE_INIT)( + IN EFI_ISA_ACPI_PROTOCOL *This + ); + +/// +/// The EFI_ISA_ACPI_PROTOCOL provides the services to enumerate and manage +/// ISA controllers on an ISA bus. These services include the ability to = initialize, +/// enable, disable, and manage the power state of ISA controllers. It al= so +/// includes services to query current resources, query possible resources, +/// and assign resources to an ISA controller. +/// +struct _EFI_ISA_ACPI_PROTOCOL { + EFI_ISA_ACPI_DEVICE_ENUMERATE DeviceEnumerate; + EFI_ISA_ACPI_SET_DEVICE_POWER SetPower; + EFI_ISA_ACPI_GET_CUR_RESOURCE GetCurResource; + EFI_ISA_ACPI_GET_POS_RESOURCE GetPosResource; + EFI_ISA_ACPI_SET_RESOURCE SetResource; + EFI_ISA_ACPI_ENABLE_DEVICE EnableDevice; + EFI_ISA_ACPI_INIT_DEVICE InitDevice; + EFI_ISA_ACPI_INTERFACE_INIT InterfaceInit; +}; + +extern EFI_GUID gEfiIsaAcpiProtocolGuid; + +#endif diff --git a/OvmfPkg/Csm/Include/Protocol/IsaIo.h b/OvmfPkg/Csm/Include/Pro= tocol/IsaIo.h new file mode 100644 index 0000000000..30000305fb --- /dev/null +++ b/OvmfPkg/Csm/Include/Protocol/IsaIo.h @@ -0,0 +1,356 @@ +/** @file + ISA I/O Protocol is used by ISA device drivers to perform I/O, MMIO and = DMA + operations on the ISA controllers they manage. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_ISA_IO_H_ +#define _EFI_ISA_IO_H_ + +#include + +/// +/// Global ID for the EFI_ISA_IO_PROTOCOL +/// +#define EFI_ISA_IO_PROTOCOL_GUID \ + { \ + 0x7ee2bd44, 0x3da0, 0x11d4, { 0x9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1,= 0x4d } \ + } + +/// +/// Forward declaration for the EFI_ISA_IO_PROTOCOL. +/// +typedef struct _EFI_ISA_IO_PROTOCOL EFI_ISA_IO_PROTOCOL; + +/// +/// Width of EFI_ISA_IO_PROTOCOL I/O Port and MMIO operations. +/// +typedef enum { + EfiIsaIoWidthUint8 =3D 0, ///< 8-bit operation. + EfiIsaIoWidthUint16, ///< 16-bit operation. + EfiIsaIoWidthUint32, ///< 32-bit operation + EfiIsaIoWidthReserved, + EfiIsaIoWidthFifoUint8, ///< 8-bit FIFO operation. + EfiIsaIoWidthFifoUint16, ///< 16-bit FIFO operation. + EfiIsaIoWidthFifoUint32, ///< 32-bit FIFO operation. + EfiIsaIoWidthFifoReserved, + EfiIsaIoWidthFillUint8, ///< 8-bit Fill operation. + EfiIsaIoWidthFillUint16, ///< 16-bit Fill operation. + EfiIsaIoWidthFillUint32, ///< 32-bit Fill operation. + EfiIsaIoWidthFillReserved, + EfiIsaIoWidthMaximum +} EFI_ISA_IO_PROTOCOL_WIDTH; + +/// +/// Attributes for the EFI_ISA_IO_PROTOCOL common DMA buffer allocations. +/// +#define EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x080 ///< Map a mem= ory range so write are combined. +#define EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED 0x800 ///< Map a mem= ory range so all read and write accesses are cached. +#define EFI_ISA_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000 ///< Disable a= memory range. + +/// +/// Channel attribute for EFI_ISA_IO_PROTOCOL slave DMA requests +/// +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE 0x001 ///< Set = the speed of the DMA transfer in compatible mode. +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A 0x002 ///< Not = supported. +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B 0x004 ///< Not = supported. +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C 0x008 ///< Not = supported. +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8 0x010 ///< Requ= est 8-bit DMA transfers. Only available on channels 0..3. +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16 0x020 ///< Requ= est 16-bit DMA transfers. Only available on channels 4..7. +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE 0x040 ///< Requ= est a single DMA transfer. +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE 0x080 ///< Requ= est multiple DMA transfers until TC (Terminal Count) or EOP (End of Process= ). +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE 0x100 ///< Auto= matically reload base and count at the end of the DMA transfer. + +/// +/// The DMA opreration type for EFI_ISA_IO_PROTOCOL DMA requests. +/// +typedef enum { + /// + /// A read operation from system memory by a bus master. + /// + EfiIsaIoOperationBusMasterRead, + /// + /// A write operation to system memory by a bus master. + /// + EfiIsaIoOperationBusMasterWrite, + /// + /// Provides both read and write access to system memory by both the pro= cessor + /// and a bus master. The buffer is coherent from both the processor's a= nd the + /// bus master's point of view. + /// + EfiIsaIoOperationBusMasterCommonBuffer, + /// + /// A read operation from system memory by a slave device. + /// + EfiIsaIoOperationSlaveRead, + /// + /// A write operation to system memory by a slave master. + /// + EfiIsaIoOperationSlaveWrite, + EfiIsaIoOperationMaximum +} EFI_ISA_IO_PROTOCOL_OPERATION; + +/** + Performs ISA I/O and MMIO Read/Write Cycles + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the I/O or MMIO operatio= n. + @param[in] Offset The offset into the ISA I/O or MMIO space to st= art the + operation. + @param[in] Count The number of I/O or MMIO operations to perform. + @param[in, out] Buffer For read operations, the destination buffer to = store + the results. For write operations, the source b= uffer to + write data from. + + @retval EFI_SUCCESS The data was successfully read from or w= ritten to the device. + @retval EFI_UNSUPPORTED The Offset is not valid for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due t= o a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_IO_MEM)( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +/// +/// Structure of functions for accessing ISA I/O and MMIO space. +/// +typedef struct { + /// + /// Read from ISA I/O or MMIO space. + /// + EFI_ISA_IO_PROTOCOL_IO_MEM Read; + /// + /// Write to ISA I/O or MMIO space. + /// + EFI_ISA_IO_PROTOCOL_IO_MEM Write; +} EFI_ISA_IO_PROTOCOL_ACCESS; + +/** + Copies data from one region of ISA MMIO space to another region of ISA + MMIO space. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Width Specifies the width of the MMIO copy operation. + @param[in] DestOffset The offset of the destination in ISA MMIO space. + @param[in] SrcOffset The offset of the source in ISA MMIO space. + @param[in] Count The number tranfers to perform for this copy ope= ration. + + @retval EFI_SUCCESS The data was copied sucessfully. + @retval EFI_UNSUPPORTED The DestOffset or SrcOffset is not valid= for this device. + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due t= o a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_COPY_MEM)( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 DestOffset, + IN UINT32 SrcOffset, + IN UINTN Count + ); + +/** + Maps a memory region for DMA. + + This function returns the device-specific addresses required to access s= ystem memory. + This function is used to map system memory for ISA DMA operations. All = ISA DMA + operations must be performed through their mapped addresses, and such ma= ppings must + be freed with EFI_ISA_IO_PROTOCOL.Unmap() after the DMA operation is com= pleted. + + If the DMA operation is a single read or write data transfer through an = ISA bus + master, then EfiIsaIoOperationBusMasterRead or EfiIsaIoOperationBusMaste= rWrite + is used and the range is unmapped to complete the operation. If the DMA = operation + is a single read or write data transfer through an ISA slave controller,= then + EfiIsaIoOperationSlaveRead or EfiIsaIoOperationSlaveWrite is used and th= e range + is unmapped to complete the operation. + + If performing a DMA read operation, all the data must be present in syst= em memory before the Map() is performed. Similarly, + if performing a DMA write operation, the data must not be accessed in sy= stem + memory until EFI_ISA_IO_PROTOCOL.Unmap() is performed. Bus master opera= tions that + require both read and write access or require multiple host device inter= actions + within the same mapped region must use EfiIsaIoOperationBusMasterCommonB= uffer. + However, only memory allocated via the EFI_ISA_IO_PROTOCOL.AllocateBuffe= r() interface + is guaranteed to be able to be mapped for this operation type. In all m= apping + requests the NumberOfBytes returned may be less than originally requeste= d. It is + the caller's responsibility to make additional requests to complete the = entire + transfer. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL= instance. + @param[in] Operation Indicates the type of DMA (slave or = bus master), + and if the DMA operation is going to= read or + write to system memory. + @param[in] ChannelNumber The slave channel number to use for = this DMA + operation. If Operation and Channel= Attributes + shows that this device performs bus = mastering + DMA, then this field is ignored. Th= e legal + range for this field is 0..7. + @param[in] ChannelAttributes A bitmask of the attributes used to = configure + the slave DMA channel for this DMA o= peration. + See EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_*= for the + legal bit combinations. + @param[in] HostAddress The system memory address to map to = the device. + @param[in, out] NumberOfBytes On input the number of bytes to map.= On + output the number of bytes that were= mapped. + @param[out] DeviceAddress The resulting map address for the bu= s master + device to use to access the hosts Ho= stAddress. + @param[out] Mapping A returned value that must be passed= to into + EFI_ISA_IO_PROTOCOL.Unmap() to free = all the the + resources associated with this map r= equest. + + @retval EFI_SUCCESS The range was mapped for the returned Nu= mberOfBytes. + @retval EFI_INVALID_PARAMETER The Operation is undefined. + @retval EFI_INVALID_PARAMETER The HostAddress is undefined. + @retval EFI_UNSUPPORTED The HostAddress can not be mapped as a c= ommon buffer. + @retval EFI_DEVICE_ERROR The system hardware could not map the re= quested address. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_MAP)( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Unmaps a memory region that was previously mapped with EFI_ISA_IO_PROTOC= OL.Map(). + + The EFI_ISA_IO_PROTOCOL.Map() operation is completed and any correspondi= ng + resources are released. If the operation was EfiIsaIoOperationSlaveWrite + or EfiIsaIoOperationBusMasterWrite, the data is committed to system memo= ry. + Any resources used for the mapping are freed. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Mapping The mapping value returned from EFI_ISA_IO_PRO= TOCOL.Map(). + + @retval EFI_SUCCESS The memory region was unmapped. + @retval EFI_DEVICE_ERROR The data was not committed to the target syste= m memory. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_UNMAP)( + IN EFI_ISA_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an EfiIsaIoOperationBusMasterCommo= nBuffer + mapping. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Type The type allocation to perform. + @param[in] MemoryType The type of memory to allocate. + @param[in] Pages The number of pages to allocate. + @param[out] HostAddress A pointer to store the base address of the all= ocated range. + @param[in] Attributes The requested bit mask of attributes for the a= llocated range. + + @retval EFI_SUCCESS The requested memory pages were allocate= d. + @retval EFI_INVALID_PARAMETER Type is invalid. + @retval EFI_INVALID_PARAMETER MemoryType is invalid. + @retval EFI_INVALID_PARAMETER HostAddress is NULL. + @retval EFI_UNSUPPORTED Attributes is unsupported. + @retval EFI_UNSUPPORTED The memory range specified by HostAddres= s, Pages, + and Type is not available for common buf= fer use. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_ALLOCATE_BUFFER)( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +/** + Frees a common buffer that was allocated with EFI_ISA_IO_PROTOCOL.Alloca= teBuffer(). + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + @param[in] Pages The number of pages to free from the previously= allocated common buffer. + @param[in] HostAddress The base address of the previously allocated co= mmon buffer. + + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory was not allocated with EFI_IS= A_IO.AllocateBufer(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_FREE_BUFFER)( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ); + +/** + Flushes a DMA buffer, which forces all DMA posted write transactions to = complete. + + @param[in] This A pointer to the EFI_ISA_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The DMA buffers were flushed. + @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardwa= re error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_FLUSH)( + IN EFI_ISA_IO_PROTOCOL *This + ); + +/// +/// The EFI_ISA_IO_PROTOCOL provides the basic Memory, I/O, and DMA interf= aces +/// used to abstract accesses to ISA controllers. There is one EFI_ISA_IO= _PROTOCOL +/// instance for each ISA controller on a ISA bus. A device driver that wi= shes +/// to manage an ISA controller in a system will have to retrieve the +/// ISA_PCI_IO_PROTOCOL instance associated with the ISA controller. +/// +struct _EFI_ISA_IO_PROTOCOL { + EFI_ISA_IO_PROTOCOL_ACCESS Mem; + EFI_ISA_IO_PROTOCOL_ACCESS Io; + EFI_ISA_IO_PROTOCOL_COPY_MEM CopyMem; + EFI_ISA_IO_PROTOCOL_MAP Map; + EFI_ISA_IO_PROTOCOL_UNMAP Unmap; + EFI_ISA_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; + EFI_ISA_IO_PROTOCOL_FREE_BUFFER FreeBuffer; + EFI_ISA_IO_PROTOCOL_FLUSH Flush; + /// + /// The list of I/O , MMIO, DMA, and Interrupt resources associated with= the + /// ISA controller abstracted by this instance of the EFI_ISA_IO_PROTOCO= L. + /// + EFI_ISA_ACPI_RESOURCE_LIST *ResourceList; + /// + /// The size, in bytes, of the ROM image. + /// + UINT32 RomSize; + /// + /// A pointer to the in memory copy of the ROM image. The ISA Bus Driver= is responsible + /// for allocating memory for the ROM image, and copying the contents of= the ROM to memory + /// during ISA Bus initialization. + /// + VOID *RomImage; +}; + +extern EFI_GUID gEfiIsaIoProtocolGuid; + +#endif diff --git a/OvmfPkg/Csm/Include/Protocol/LegacyBios.h b/OvmfPkg/Csm/Includ= e/Protocol/LegacyBios.h new file mode 100644 index 0000000000..36761da397 --- /dev/null +++ b/OvmfPkg/Csm/Include/Protocol/LegacyBios.h @@ -0,0 +1,1553 @@ +/** @file + The EFI Legacy BIOS Protocol is used to abstract legacy Option ROM usage + under EFI and Legacy OS boot. This file also includes all the related + COMPATIBILIY16 structures and defintions. + + Note: The names for EFI_IA32_REGISTER_SET elements were picked to follow + well known naming conventions. + + Thunk is the code that switches from 32-bit protected environment into t= he 16-bit real-mode + environment. Reverse thunk is the code that does the opposite. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Revision Reference: + This protocol is defined in Framework for EFI Compatibility Support Modu= le spec + Version 0.98. + +**/ + +#ifndef _EFI_LEGACY_BIOS_H_ +#define _EFI_LEGACY_BIOS_H_ + +/// +/// +/// +#pragma pack(1) + +typedef UINT8 SERIAL_MODE; +typedef UINT8 PARALLEL_MODE; + +#define EFI_COMPATIBILITY16_TABLE_SIGNATURE SIGNATURE_32 ('I', 'F', 'E', '= $') + +/// +/// There is a table located within the traditional BIOS in either the 0xF= 000:xxxx or 0xE000:xxxx +/// physical address range. It is located on a 16-byte boundary and provid= es the physical address of the +/// entry point for the Compatibility16 functions. These functions provide= the platform-specific +/// information that is required by the generic EfiCompatibility code. The= functions are invoked via +/// thunking by using EFI_LEGACY_BIOS_PROTOCOL.FarCall86() with the 32-bit= physical +/// entry point. +/// +typedef struct { + /// + /// The string "$EFI" denotes the start of the EfiCompatibility table. B= yte 0 is "I," byte + /// 1 is "F," byte 2 is "E," and byte 3 is "$" and is normally accessed = as a DWORD or UINT32. + /// + UINT32 Signature; + + /// + /// The value required such that byte checksum of TableLength equals zer= o. + /// + UINT8 TableChecksum; + + /// + /// The length of this table. + /// + UINT8 TableLength; + + /// + /// The major EFI revision for which this table was generated. + /// + UINT8 EfiMajorRevision; + + /// + /// The minor EFI revision for which this table was generated. + /// + UINT8 EfiMinorRevision; + + /// + /// The major revision of this table. + /// + UINT8 TableMajorRevision; + + /// + /// The minor revision of this table. + /// + UINT8 TableMinorRevision; + + /// + /// Reserved for future usage. + /// + UINT16 Reserved; + + /// + /// The segment of the entry point within the traditional BIOS for Compa= tibility16 functions. + /// + UINT16 Compatibility16CallSegment; + + /// + /// The offset of the entry point within the traditional BIOS for Compat= ibility16 functions. + /// + UINT16 Compatibility16CallOffset; + + /// + /// The segment of the entry point within the traditional BIOS for EfiCo= mpatibility + /// to invoke the PnP installation check. + /// + UINT16 PnPInstallationCheckSegment; + + /// + /// The Offset of the entry point within the traditional BIOS for EfiCom= patibility + /// to invoke the PnP installation check. + /// + UINT16 PnPInstallationCheckOffset; + + /// + /// EFI system resources table. Type EFI_SYSTEM_TABLE is defined in the = IntelPlatform + ///Innovation Framework for EFI Driver Execution Environment Core Interf= ace Specification (DXE CIS). + /// + UINT32 EfiSystemTable; + + /// + /// The address of an OEM-provided identifier string. The string is null= terminated. + /// + UINT32 OemIdStringPointer; + + /// + /// The 32-bit physical address where ACPI RSD PTR is stored within the = traditional + /// BIOS. The remained of the ACPI tables are located at their EFI addre= sses. The size + /// reserved is the maximum for ACPI 2.0. The EfiCompatibility will fill= in the ACPI + /// RSD PTR with either the ACPI 1.0b or 2.0 values. + /// + UINT32 AcpiRsdPtrPointer; + + /// + /// The OEM revision number. Usage is undefined but provided for OEM mod= ule usage. + /// + UINT16 OemRevision; + + /// + /// The 32-bit physical address where INT15 E820 data is stored within t= he traditional + /// BIOS. The EfiCompatibility code will fill in the E820Pointer value a= nd copy the + /// data to the indicated area. + /// + UINT32 E820Pointer; + + /// + /// The length of the E820 data and is filled in by the EfiCompatibility= code. + /// + UINT32 E820Length; + + /// + /// The 32-bit physical address where the $PIR table is stored in the tr= aditional BIOS. + /// The EfiCompatibility code will fill in the IrqRoutingTablePointer va= lue and + /// copy the data to the indicated area. + /// + UINT32 IrqRoutingTablePointer; + + /// + /// The length of the $PIR table and is filled in by the EfiCompatibilit= y code. + /// + UINT32 IrqRoutingTableLength; + + /// + /// The 32-bit physical address where the MP table is stored in the trad= itional BIOS. + /// The EfiCompatibility code will fill in the MpTablePtr value and copy= the data + /// to the indicated area. + /// + UINT32 MpTablePtr; + + /// + /// The length of the MP table and is filled in by the EfiCompatibility = code. + /// + UINT32 MpTableLength; + + /// + /// The segment of the OEM-specific INT table/code. + /// + UINT16 OemIntSegment; + + /// + /// The offset of the OEM-specific INT table/code. + /// + UINT16 OemIntOffset; + + /// + /// The segment of the OEM-specific 32-bit table/code. + /// + UINT16 Oem32Segment; + + /// + /// The offset of the OEM-specific 32-bit table/code. + /// + UINT16 Oem32Offset; + + /// + /// The segment of the OEM-specific 16-bit table/code. + /// + UINT16 Oem16Segment; + + /// + /// The offset of the OEM-specific 16-bit table/code. + /// + UINT16 Oem16Offset; + + /// + /// The segment of the TPM binary passed to 16-bit CSM. + /// + UINT16 TpmSegment; + + /// + /// The offset of the TPM binary passed to 16-bit CSM. + /// + UINT16 TpmOffset; + + /// + /// A pointer to a string identifying the independent BIOS vendor. + /// + UINT32 IbvPointer; + + /// + /// This field is NULL for all systems not supporting PCI Express. This = field is the base + /// value of the start of the PCI Express memory-mapped configuration re= gisters and + /// must be filled in prior to EfiCompatibility code issuing the Compati= bility16 function + /// Compatibility16InitializeYourself(). + /// Compatibility16InitializeYourself() is defined in Compatability16 + /// Functions. + /// + UINT32 PciExpressBase; + + /// + /// Maximum PCI bus number assigned. + /// + UINT8 LastPciBus; + + /// + /// Start Address of Upper Memory Area (UMA) to be set as Read/Write. If + /// UmaAddress is a valid address in the shadow RAM, it also indicates t= hat the region + /// from 0xC0000 to (UmaAddress - 1) can be used for Option ROM. + /// + UINT32 UmaAddress; + + /// + /// Upper Memory Area size in bytes to be set as Read/Write. If zero, no= UMA region + /// will be set as Read/Write (i.e. all Shadow RAM is set as Read-Only). + /// + UINT32 UmaSize; + + /// + /// Start Address of high memory that can be used for permanent allocati= on. If zero, + /// high memory is not available for permanent allocation. + /// + UINT32 HiPermanentMemoryAddress; + + /// + /// Size of high memory that can be used for permanent allocation in byt= es. If zero, + /// high memory is not available for permanent allocation. + /// + UINT32 HiPermanentMemorySize; +} EFI_COMPATIBILITY16_TABLE; + +/// +/// Functions provided by the CSM binary which communicate between the Efi= Compatibility +/// and Compatability16 code. +/// +/// Inconsistent with the specification here: +/// The member's name started with "Compatibility16" [defined in Intel Fra= mework +/// Compatibility Support Module Specification / 0.97 version] +/// has been changed to "Legacy16" since keeping backward compatible. +/// +typedef enum { + /// + /// Causes the Compatibility16 code to do any internal initialization re= quired. + /// Input: + /// AX =3D Compatibility16InitializeYourself + /// ES:BX =3D Pointer to EFI_TO_COMPATIBILITY16_INIT_TABLE + /// Return: + /// AX =3D Return Status codes + /// + Legacy16InitializeYourself =3D 0x0000, + + /// + /// Causes the Compatibility16 BIOS to perform any drive number translat= ions to match the boot sequence. + /// Input: + /// AX =3D Compatibility16UpdateBbs + /// ES:BX =3D Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE + /// Return: + /// AX =3D Returned status codes + /// + Legacy16UpdateBbs =3D 0x0001, + + /// + /// Allows the Compatibility16 code to perform any final actions before = booting. The Compatibility16 + /// code is read/write. + /// Input: + /// AX =3D Compatibility16PrepareToBoot + /// ES:BX =3D Pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE structure + /// Return: + /// AX =3D Returned status codes + /// + Legacy16PrepareToBoot =3D 0x0002, + + /// + /// Causes the Compatibility16 BIOS to boot. The Compatibility16 code is= Read/Only. + /// Input: + /// AX =3D Compatibility16Boot + /// Output: + /// AX =3D Returned status codes + /// + Legacy16Boot =3D 0x0003, + + /// + /// Allows the Compatibility16 code to get the last device from which a = boot was attempted. This is + /// stored in CMOS and is the priority number of the last attempted boot= device. + /// Input: + /// AX =3D Compatibility16RetrieveLastBootDevice + /// Output: + /// AX =3D Returned status codes + /// BX =3D Priority number of the boot device. + /// + Legacy16RetrieveLastBootDevice =3D 0x0004, + + /// + /// Allows the Compatibility16 code rehook INT13, INT18, and/or INT19 af= ter dispatching a legacy OpROM. + /// Input: + /// AX =3D Compatibility16DispatchOprom + /// ES:BX =3D Pointer to EFI_DISPATCH_OPROM_TABLE + /// Output: + /// AX =3D Returned status codes + /// BX =3D Number of non-BBS-compliant devices found. Equals 0 if BBS = compliant. + /// + Legacy16DispatchOprom =3D 0x0005, + + /// + /// Finds a free area in the 0xFxxxx or 0xExxxx region of the specified = length and returns the address + /// of that region. + /// Input: + /// AX =3D Compatibility16GetTableAddress + /// BX =3D Allocation region + /// 00 =3D Allocate from either 0xE0000 or 0xF0000 64 KB blocks. + /// Bit 0 =3D 1 Allocate from 0xF0000 64 KB block + /// Bit 1 =3D 1 Allocate from 0xE0000 64 KB block + /// CX =3D Requested length in bytes. + /// DX =3D Required address alignment. Bit mapped. First non-zero bit = from the right is the alignment. + /// Output: + /// AX =3D Returned status codes + /// DS:BX =3D Address of the region + /// + Legacy16GetTableAddress =3D 0x0006, + + /// + /// Enables the EfiCompatibility module to do any nonstandard processing= of keyboard LEDs or state. + /// Input: + /// AX =3D Compatibility16SetKeyboardLeds + /// CL =3D LED status. + /// Bit 0 Scroll Lock 0 =3D Off + /// Bit 1 NumLock + /// Bit 2 Caps Lock + /// Output: + /// AX =3D Returned status codes + /// + Legacy16SetKeyboardLeds =3D 0x0007, + + /// + /// Enables the EfiCompatibility module to install an interrupt handler = for PCI mass media devices that + /// do not have an OpROM associated with them. An example is SATA. + /// Input: + /// AX =3D Compatibility16InstallPciHandler + /// ES:BX =3D Pointer to EFI_LEGACY_INSTALL_PCI_HANDLER structure + /// Output: + /// AX =3D Returned status codes + /// + Legacy16InstallPciHandler =3D 0x0008 +} EFI_COMPATIBILITY_FUNCTIONS; + + +/// +/// EFI_DISPATCH_OPROM_TABLE +/// +typedef struct { + UINT16 PnPInstallationCheckSegment; ///< A pointer to the PnpInstallat= ionCheck data structure. + UINT16 PnPInstallationCheckOffset; ///< A pointer to the PnpInstallat= ionCheck data structure. + UINT16 OpromSegment; ///< The segment where the OpROM w= as placed. Offset is assumed to be 3. + UINT8 PciBus; ///< The PCI bus. + UINT8 PciDeviceFunction; ///< The PCI device * 0x08 | PCI f= unction. + UINT8 NumberBbsEntries; ///< The number of valid BBS table= entries upon entry and exit. The IBV code may + ///< increase this number, if BBS-= compliant devices also hook INTs in order to force the + ///< OpROM BIOS Setup to be execut= ed. + UINT32 BbsTablePointer; ///< A pointer to the BBS table. + UINT16 RuntimeSegment; ///< The segment where the OpROM c= an be relocated to. If this value is 0x0000, this + ///< means that the relocation of = this run time code is not supported. + ///< Inconsistent with specificati= on here: + ///< The member's name "OpromDesti= nationSegment" [defined in Intel Framework Compatibility Support Module Spe= cification / 0.97 version] + ///< has been changed to "RuntimeS= egment" since keeping backward compatible. + +} EFI_DISPATCH_OPROM_TABLE; + +/// +/// EFI_TO_COMPATIBILITY16_INIT_TABLE +/// +typedef struct { + /// + /// Starting address of memory under 1 MB. The ending address is assumed= to be 640 KB or 0x9FFFF. + /// + UINT32 BiosLessThan1MB; + + /// + /// The starting address of the high memory block. + /// + UINT32 HiPmmMemory; + + /// + /// The length of high memory block. + /// + UINT32 HiPmmMemorySizeInBytes; + + /// + /// The segment of the reverse thunk call code. + /// + UINT16 ReverseThunkCallSegment; + + /// + /// The offset of the reverse thunk call code. + /// + UINT16 ReverseThunkCallOffset; + + /// + /// The number of E820 entries copied to the Compatibility16 BIOS. + /// + UINT32 NumberE820Entries; + + /// + /// The amount of usable memory above 1 MB, e.g., E820 type 1 memory. + /// + UINT32 OsMemoryAbove1Mb; + + /// + /// The start of thunk code in main memory. Memory cannot be used by BIO= S or PMM. + /// + UINT32 ThunkStart; + + /// + /// The size of the thunk code. + /// + UINT32 ThunkSizeInBytes; + + /// + /// Starting address of memory under 1 MB. + /// + UINT32 LowPmmMemory; + + /// + /// The length of low Memory block. + /// + UINT32 LowPmmMemorySizeInBytes; +} EFI_TO_COMPATIBILITY16_INIT_TABLE; + +/// +/// DEVICE_PRODUCER_SERIAL. +/// +typedef struct { + UINT16 Address; ///< I/O address assigned = to the serial port. + UINT8 Irq; ///< IRQ assigned to the s= erial port. + SERIAL_MODE Mode; ///< Mode of serial port. = Values are defined below. +} DEVICE_PRODUCER_SERIAL; + +/// +/// DEVICE_PRODUCER_SERIAL's modes. +///@{ +#define DEVICE_SERIAL_MODE_NORMAL 0x00 +#define DEVICE_SERIAL_MODE_IRDA 0x01 +#define DEVICE_SERIAL_MODE_ASK_IR 0x02 +#define DEVICE_SERIAL_MODE_DUPLEX_HALF 0x00 +#define DEVICE_SERIAL_MODE_DUPLEX_FULL 0x10 +///@) + +/// +/// DEVICE_PRODUCER_PARALLEL. +/// +typedef struct { + UINT16 Address; ///< I/O address assigned to= the parallel port. + UINT8 Irq; ///< IRQ assigned to the par= allel port. + UINT8 Dma; ///< DMA assigned to the par= allel port. + PARALLEL_MODE Mode; ///< Mode of the parallel po= rt. Values are defined below. +} DEVICE_PRODUCER_PARALLEL; + +/// +/// DEVICE_PRODUCER_PARALLEL's modes. +///@{ +#define DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY 0x00 +#define DEVICE_PARALLEL_MODE_MODE_BIDIRECTIONAL 0x01 +#define DEVICE_PARALLEL_MODE_MODE_EPP 0x02 +#define DEVICE_PARALLEL_MODE_MODE_ECP 0x03 +///@} + +/// +/// DEVICE_PRODUCER_FLOPPY +/// +typedef struct { + UINT16 Address; ///< I/O address ass= igned to the floppy. + UINT8 Irq; ///< IRQ assigned to= the floppy. + UINT8 Dma; ///< DMA assigned to= the floppy. + UINT8 NumberOfFloppy; ///< Number of flopp= ies in the system. +} DEVICE_PRODUCER_FLOPPY; + +/// +/// LEGACY_DEVICE_FLAGS +/// +typedef struct { + UINT32 A20Kybd : 1; ///< A20 controller = by keyboard controller. + UINT32 A20Port90 : 1; ///< A20 controlled = by port 0x92. + UINT32 Reserved : 30; ///< Reserved for fu= ture usage. +} LEGACY_DEVICE_FLAGS; + +/// +/// DEVICE_PRODUCER_DATA_HEADER +/// +typedef struct { + DEVICE_PRODUCER_SERIAL Serial[4]; ///< Data for serial p= ort x. Type DEVICE_PRODUCER_SERIAL is defined below. + DEVICE_PRODUCER_PARALLEL Parallel[3]; ///< Data for parallel= port x. Type DEVICE_PRODUCER_PARALLEL is defined below. + DEVICE_PRODUCER_FLOPPY Floppy; ///< Data for floppy. = Type DEVICE_PRODUCER_FLOPPY is defined below. + UINT8 MousePresent; ///< Flag to indicate = if mouse is present. + LEGACY_DEVICE_FLAGS Flags; ///< Miscellaneous Boo= lean state information passed to CSM. +} DEVICE_PRODUCER_DATA_HEADER; + +/// +/// ATAPI_IDENTIFY +/// +typedef struct { + UINT16 Raw[256]; ///< Raw data from the I= DE IdentifyDrive command. +} ATAPI_IDENTIFY; + +/// +/// HDD_INFO +/// +typedef struct { + /// + /// Status of IDE device. Values are defined below. There is one HDD_INF= O structure + /// per IDE controller. The IdentifyDrive is per drive. Index 0 is maste= r and index + /// 1 is slave. + /// + UINT16 Status; + + /// + /// PCI bus of IDE controller. + /// + UINT32 Bus; + + /// + /// PCI device of IDE controller. + /// + UINT32 Device; + + /// + /// PCI function of IDE controller. + /// + UINT32 Function; + + /// + /// Command ports base address. + /// + UINT16 CommandBaseAddress; + + /// + /// Control ports base address. + /// + UINT16 ControlBaseAddress; + + /// + /// Bus master address. + /// + UINT16 BusMasterAddress; + + UINT8 HddIrq; + + /// + /// Data that identifies the drive data; one per possible attached drive. + /// + ATAPI_IDENTIFY IdentifyDrive[2]; +} HDD_INFO; + +/// +/// HDD_INFO status bits +/// +#define HDD_PRIMARY 0x01 +#define HDD_SECONDARY 0x02 +#define HDD_MASTER_ATAPI_CDROM 0x04 +#define HDD_SLAVE_ATAPI_CDROM 0x08 +#define HDD_MASTER_IDE 0x20 +#define HDD_SLAVE_IDE 0x40 +#define HDD_MASTER_ATAPI_ZIPDISK 0x10 +#define HDD_SLAVE_ATAPI_ZIPDISK 0x80 + +/// +/// BBS_STATUS_FLAGS;\. +/// +typedef struct { + UINT16 OldPosition : 4; ///< Prior priorit= y. + UINT16 Reserved1 : 4; ///< Reserved for = future use. + UINT16 Enabled : 1; ///< If 0, ignore = this entry. + UINT16 Failed : 1; ///< 0 =3D Not kno= wn if boot failure occurred. + ///< 1 =3D Boot at= tempted failed. + + /// + /// State of media present. + /// 00 =3D No bootable media is present in the device. + /// 01 =3D Unknown if a bootable media present. + /// 10 =3D Media is present and appears bootable. + /// 11 =3D Reserved. + /// + UINT16 MediaPresent : 2; + UINT16 Reserved2 : 4; ///< Reserved for = future use. +} BBS_STATUS_FLAGS; + +/// +/// BBS_TABLE, device type values & boot priority values. +/// +typedef struct { + /// + /// The boot priority for this boot device. Values are defined below. + /// + UINT16 BootPriority; + + /// + /// The PCI bus for this boot device. + /// + UINT32 Bus; + + /// + /// The PCI device for this boot device. + /// + UINT32 Device; + + /// + /// The PCI function for the boot device. + /// + UINT32 Function; + + /// + /// The PCI class for this boot device. + /// + UINT8 Class; + + /// + /// The PCI Subclass for this boot device. + /// + UINT8 SubClass; + + /// + /// Segment:offset address of an ASCIIZ description string describing th= e manufacturer. + /// + UINT16 MfgStringOffset; + + /// + /// Segment:offset address of an ASCIIZ description string describing th= e manufacturer. + /// + UINT16 MfgStringSegment; + + /// + /// BBS device type. BBS device types are defined below. + /// + UINT16 DeviceType; + + /// + /// Status of this boot device. Type BBS_STATUS_FLAGS is defined below. + /// + BBS_STATUS_FLAGS StatusFlags; + + /// + /// Segment:Offset address of boot loader for IPL devices or install INT= 13 handler for + /// BCV devices. + /// + UINT16 BootHandlerOffset; + + /// + /// Segment:Offset address of boot loader for IPL devices or install INT= 13 handler for + /// BCV devices. + /// + UINT16 BootHandlerSegment; + + /// + /// Segment:offset address of an ASCIIZ description string describing th= is device. + /// + UINT16 DescStringOffset; + + /// + /// Segment:offset address of an ASCIIZ description string describing th= is device. + /// + UINT16 DescStringSegment; + + /// + /// Reserved. + /// + UINT32 InitPerReserved; + + /// + /// The use of these fields is IBV dependent. They can be used to flag t= hat an OpROM + /// has hooked the specified IRQ. The OpROM may be BBS compliant as some= SCSI + /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIO= S Setup + /// + UINT32 AdditionalIrq13Handler; + + /// + /// The use of these fields is IBV dependent. They can be used to flag t= hat an OpROM + /// has hooked the specified IRQ. The OpROM may be BBS compliant as some= SCSI + /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIO= S Setup + /// + UINT32 AdditionalIrq18Handler; + + /// + /// The use of these fields is IBV dependent. They can be used to flag t= hat an OpROM + /// has hooked the specified IRQ. The OpROM may be BBS compliant as some= SCSI + /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIO= S Setup + /// + UINT32 AdditionalIrq19Handler; + + /// + /// The use of these fields is IBV dependent. They can be used to flag t= hat an OpROM + /// has hooked the specified IRQ. The OpROM may be BBS compliant as some= SCSI + /// BBS-compliant OpROMs also hook IRQ vectors in order to run their BIO= S Setup + /// + UINT32 AdditionalIrq40Handler; + UINT8 AssignedDriveNumber; + UINT32 AdditionalIrq41Handler; + UINT32 AdditionalIrq46Handler; + UINT32 IBV1; + UINT32 IBV2; +} BBS_TABLE; + +/// +/// BBS device type values +///@{ +#define BBS_FLOPPY 0x01 +#define BBS_HARDDISK 0x02 +#define BBS_CDROM 0x03 +#define BBS_PCMCIA 0x04 +#define BBS_USB 0x05 +#define BBS_EMBED_NETWORK 0x06 +#define BBS_BEV_DEVICE 0x80 +#define BBS_UNKNOWN 0xff +///@} + +/// +/// BBS boot priority values +///@{ +#define BBS_DO_NOT_BOOT_FROM 0xFFFC +#define BBS_LOWEST_PRIORITY 0xFFFD +#define BBS_UNPRIORITIZED_ENTRY 0xFFFE +#define BBS_IGNORE_ENTRY 0xFFFF +///@} + +/// +/// SMM_ATTRIBUTES +/// +typedef struct { + /// + /// Access mechanism used to generate the soft SMI. Defined types are be= low. The other + /// values are reserved for future usage. + /// + UINT16 Type : 3; + + /// + /// The size of "port" in bits. Defined values are below. + /// + UINT16 PortGranularity : 3; + + /// + /// The size of data in bits. Defined values are below. + /// + UINT16 DataGranularity : 3; + + /// + /// Reserved for future use. + /// + UINT16 Reserved : 7; +} SMM_ATTRIBUTES; + +/// +/// SMM_ATTRIBUTES type values. +///@{ +#define STANDARD_IO 0x00 +#define STANDARD_MEMORY 0x01 +///@} + +/// +/// SMM_ATTRIBUTES port size constants. +///@{ +#define PORT_SIZE_8 0x00 +#define PORT_SIZE_16 0x01 +#define PORT_SIZE_32 0x02 +#define PORT_SIZE_64 0x03 +///@} + +/// +/// SMM_ATTRIBUTES data size constants. +///@{ +#define DATA_SIZE_8 0x00 +#define DATA_SIZE_16 0x01 +#define DATA_SIZE_32 0x02 +#define DATA_SIZE_64 0x03 +///@} + +/// +/// SMM_FUNCTION & relating constants. +/// +typedef struct { + UINT16 Function : 15; + UINT16 Owner : 1; +} SMM_FUNCTION; + +/// +/// SMM_FUNCTION Function constants. +///@{ +#define INT15_D042 0x0000 +#define GET_USB_BOOT_INFO 0x0001 +#define DMI_PNP_50_57 0x0002 +///@} + +/// +/// SMM_FUNCTION Owner constants. +///@{ +#define STANDARD_OWNER 0x0 +#define OEM_OWNER 0x1 +///@} + +/// +/// This structure assumes both port and data sizes are 1. SmmAttribute mu= st be +/// properly to reflect that assumption. +/// +typedef struct { + /// + /// Describes the access mechanism, SmmPort, and SmmData sizes. Type + /// SMM_ATTRIBUTES is defined below. + /// + SMM_ATTRIBUTES SmmAttributes; + + /// + /// Function Soft SMI is to perform. Type SMM_FUNCTION is defined below. + /// + SMM_FUNCTION SmmFunction; + + /// + /// SmmPort size depends upon SmmAttributes and ranges from2 bytes to 16= bytes. + /// + UINT8 SmmPort; + + /// + /// SmmData size depends upon SmmAttributes and ranges from2 bytes to 16= bytes. + /// + UINT8 SmmData; +} SMM_ENTRY; + +/// +/// SMM_TABLE +/// +typedef struct { + UINT16 NumSmmEntries; ///< Number of entri= es represented by SmmEntry. + SMM_ENTRY SmmEntry; ///< One entry per f= unction. Type SMM_ENTRY is defined below. +} SMM_TABLE; + +/// +/// UDC_ATTRIBUTES +/// +typedef struct { + /// + /// This bit set indicates that the ServiceAreaData is valid. + /// + UINT8 DirectoryServiceValidity : 1; + + /// + /// This bit set indicates to use the Reserve Area Boot Code Address (RA= CBA) only if + /// DirectoryServiceValidity is 0. + /// + UINT8 RabcaUsedFlag : 1; + + /// + /// This bit set indicates to execute hard disk diagnostics. + /// + UINT8 ExecuteHddDiagnosticsFlag : 1; + + /// + /// Reserved for future use. Set to 0. + /// + UINT8 Reserved : 5; +} UDC_ATTRIBUTES; + +/// +/// UD_TABLE +/// +typedef struct { + /// + /// This field contains the bit-mapped attributes of the PARTIES informa= tion. Type + /// UDC_ATTRIBUTES is defined below. + /// + UDC_ATTRIBUTES Attributes; + + /// + /// This field contains the zero-based device on which the selected + /// ServiceDataArea is present. It is 0 for master and 1 for the slave d= evice. + /// + UINT8 DeviceNumber; + + /// + /// This field contains the zero-based index into the BbsTable for the p= arent device. + /// This index allows the user to reference the parent device informatio= n such as PCI + /// bus, device function. + /// + UINT8 BbsTableEntryNumberForParentDevice; + + /// + /// This field contains the zero-based index into the BbsTable for the b= oot entry. + /// + UINT8 BbsTableEntryNumberForBoot; + + /// + /// This field contains the zero-based index into the BbsTable for the H= DD diagnostics entry. + /// + UINT8 BbsTableEntryNumberForHddDiag; + + /// + /// The raw Beer data. + /// + UINT8 BeerData[128]; + + /// + /// The raw data of selected service area. + /// + UINT8 ServiceAreaData[64]; +} UD_TABLE; + +#define EFI_TO_LEGACY_MAJOR_VERSION 0x02 +#define EFI_TO_LEGACY_MINOR_VERSION 0x00 +#define MAX_IDE_CONTROLLER 8 + +/// +/// EFI_TO_COMPATIBILITY16_BOOT_TABLE +/// +typedef struct { + UINT16 MajorVersion; ///< The= EfiCompatibility major version number. + UINT16 MinorVersion; ///< The= EfiCompatibility minor version number. + UINT32 AcpiTable; ///< The= location of the RSDT ACPI table. < 4G range. + UINT32 SmbiosTable; ///< The= location of the SMBIOS table in EFI memory. < 4G range. + UINT32 SmbiosTableLength; + // + // Legacy SIO state + // + DEVICE_PRODUCER_DATA_HEADER SioData; ///< Sta= ndard traditional device information. + UINT16 DevicePathType; ///< The= default boot type. + UINT16 PciIrqMask; ///< Mas= k of which IRQs have been assigned to PCI. + UINT32 NumberE820Entries; ///< Num= ber of E820 entries. The number can change from the + ///< Com= patibility16InitializeYourself() function. + // + // Controller & Drive Identify[2] per controller information + // + HDD_INFO HddInfo[MAX_IDE_CONTROLLER]; ///< Har= d disk drive information, including raw Identify Drive data. + UINT32 NumberBbsEntries; ///< Num= ber of entries in the BBS table + UINT32 BbsTable; ///< A p= ointer to the BBS table. Type BBS_TABLE is defined below. + UINT32 SmmTable; ///< A p= ointer to the SMM table. Type SMM_TABLE is defined below. + UINT32 OsMemoryAbove1Mb; ///< The= amount of usable memory above 1 MB, i.e. E820 type 1 memory. This value can + ///< dif= fer from the value in EFI_TO_COMPATIBILITY16_INIT_TABLE as more + ///< mem= ory may have been discovered. + UINT32 UnconventionalDeviceTable; ///< Inf= ormation to boot off an unconventional device like a PARTIES partition. Type + ///< UD_= TABLE is defined below. +} EFI_TO_COMPATIBILITY16_BOOT_TABLE; + +/// +/// EFI_LEGACY_INSTALL_PCI_HANDLER +/// +typedef struct { + UINT8 PciBus; ///< The PCI bus o= f the device. + UINT8 PciDeviceFun; ///< The PCI devic= e in bits 7:3 and function in bits 2:0. + UINT8 PciSegment; ///< The PCI segme= nt of the device. + UINT8 PciClass; ///< The PCI class= code of the device. + UINT8 PciSubclass; ///< The PCI subcl= ass code of the device. + UINT8 PciInterface; ///< The PCI inter= face code of the device. + // + // Primary section + // + UINT8 PrimaryIrq; ///< The primary d= evice IRQ. + UINT8 PrimaryReserved; ///< Reserved. + UINT16 PrimaryControl; ///< The primary d= evice control I/O base. + UINT16 PrimaryBase; ///< The primary d= evice I/O base. + UINT16 PrimaryBusMaster; ///< The primary d= evice bus master I/O base. + // + // Secondary Section + // + UINT8 SecondaryIrq; ///< The secondary= device IRQ. + UINT8 SecondaryReserved; ///< Reserved. + UINT16 SecondaryControl; ///< The secondary= device control I/O base. + UINT16 SecondaryBase; ///< The secondary= device I/O base. + UINT16 SecondaryBusMaster; ///< The secondary= device bus master I/O base. +} EFI_LEGACY_INSTALL_PCI_HANDLER; + +// +// Restore default pack value +// +#pragma pack() + +#define EFI_LEGACY_BIOS_PROTOCOL_GUID \ + { \ + 0xdb9a1e3d, 0x45cb, 0x4abb, {0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e,= 0x2d } \ + } + +typedef struct _EFI_LEGACY_BIOS_PROTOCOL EFI_LEGACY_BIOS_PROTOCOL; + +/// +/// Flags returned by CheckPciRom(). +/// +#define NO_ROM 0x00 +#define ROM_FOUND 0x01 +#define VALID_LEGACY_ROM 0x02 +#define ROM_WITH_CONFIG 0x04 ///< Not defined in the Framework CSM S= pecification. + +/// +/// The following macros do not appear in the Framework CSM Specification = and +/// are kept for backward compatibility only. They convert 32-bit address= (_Adr) +/// to Segment:Offset 16-bit form. +/// +///@{ +#define EFI_SEGMENT(_Adr) (UINT16) ((UINT16) (((UINTN) (_Adr)) >> 4) &= 0xf000) +#define EFI_OFFSET(_Adr) (UINT16) (((UINT16) ((UINTN) (_Adr))) & 0xff= ff) +///@} + +#define CARRY_FLAG 0x01 + +/// +/// EFI_EFLAGS_REG +/// +typedef struct { + UINT32 CF:1; + UINT32 Reserved1:1; + UINT32 PF:1; + UINT32 Reserved2:1; + UINT32 AF:1; + UINT32 Reserved3:1; + UINT32 ZF:1; + UINT32 SF:1; + UINT32 TF:1; + UINT32 IF:1; + UINT32 DF:1; + UINT32 OF:1; + UINT32 IOPL:2; + UINT32 NT:1; + UINT32 Reserved4:2; + UINT32 VM:1; + UINT32 Reserved5:14; +} EFI_EFLAGS_REG; + +/// +/// EFI_DWORD_REGS +/// +typedef struct { + UINT32 EAX; + UINT32 EBX; + UINT32 ECX; + UINT32 EDX; + UINT32 ESI; + UINT32 EDI; + EFI_EFLAGS_REG EFlags; + UINT16 ES; + UINT16 CS; + UINT16 SS; + UINT16 DS; + UINT16 FS; + UINT16 GS; + UINT32 EBP; + UINT32 ESP; +} EFI_DWORD_REGS; + +/// +/// EFI_FLAGS_REG +/// +typedef struct { + UINT16 CF:1; + UINT16 Reserved1:1; + UINT16 PF:1; + UINT16 Reserved2:1; + UINT16 AF:1; + UINT16 Reserved3:1; + UINT16 ZF:1; + UINT16 SF:1; + UINT16 TF:1; + UINT16 IF:1; + UINT16 DF:1; + UINT16 OF:1; + UINT16 IOPL:2; + UINT16 NT:1; + UINT16 Reserved4:1; +} EFI_FLAGS_REG; + +/// +/// EFI_WORD_REGS +/// +typedef struct { + UINT16 AX; + UINT16 ReservedAX; + UINT16 BX; + UINT16 ReservedBX; + UINT16 CX; + UINT16 ReservedCX; + UINT16 DX; + UINT16 ReservedDX; + UINT16 SI; + UINT16 ReservedSI; + UINT16 DI; + UINT16 ReservedDI; + EFI_FLAGS_REG Flags; + UINT16 ReservedFlags; + UINT16 ES; + UINT16 CS; + UINT16 SS; + UINT16 DS; + UINT16 FS; + UINT16 GS; + UINT16 BP; + UINT16 ReservedBP; + UINT16 SP; + UINT16 ReservedSP; +} EFI_WORD_REGS; + +/// +/// EFI_BYTE_REGS +/// +typedef struct { + UINT8 AL, AH; + UINT16 ReservedAX; + UINT8 BL, BH; + UINT16 ReservedBX; + UINT8 CL, CH; + UINT16 ReservedCX; + UINT8 DL, DH; + UINT16 ReservedDX; +} EFI_BYTE_REGS; + +/// +/// EFI_IA32_REGISTER_SET +/// +typedef union { + EFI_DWORD_REGS E; + EFI_WORD_REGS X; + EFI_BYTE_REGS H; +} EFI_IA32_REGISTER_SET; + +/** + Thunk to 16-bit real mode and execute a software interrupt with a vector + of BiosInt. Regs will contain the 16-bit register context on entry and + exit. + + @param[in] This The protocol instance pointer. + @param[in] BiosInt The processor interrupt vector to invoke. + @param[in,out] Reg Register contexted passed into (and returned) f= rom thunk to + 16-bit mode. + + @retval TRUE Thunk completed with no BIOS errors in the t= arget code. See Regs for status. + @retval FALSE There was a BIOS error in the target code. +**/ +typedef +BOOLEAN +(EFIAPI *EFI_LEGACY_BIOS_INT86)( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 BiosInt, + IN OUT EFI_IA32_REGISTER_SET *Regs + ); + +/** + Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the + 16-bit register context on entry and exit. Arguments can be passed on + the Stack argument + + @param[in] This The protocol instance pointer. + @param[in] Segment The segemnt of 16-bit mode call. + @param[in] Offset The offset of 16-bit mdoe call. + @param[in] Reg Register contexted passed into (and returned) fro= m thunk to + 16-bit mode. + @param[in] Stack The caller allocated stack used to pass arguments. + @param[in] StackSize The size of Stack in bytes. + + @retval FALSE Thunk completed with no BIOS errors in the= target code. See Regs for status. @retval = TRUE There was a BIOS error in the target code. +**/ +typedef +BOOLEAN +(EFIAPI *EFI_LEGACY_BIOS_FARCALL86)( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT16 Segment, + IN UINT16 Offset, + IN EFI_IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize + ); + +/** + Test to see if a legacy PCI ROM exists for this device. Optionally return + the Legacy ROM instance for this PCI device. + + @param[in] This The protocol instance pointer. + @param[in] PciHandle The PCI PC-AT OPROM from this devices ROM BAR wi= ll be loaded + @param[out] RomImage Return the legacy PCI ROM for this device. + @param[out] RomSize The size of ROM Image. + @param[out] Flags Indicates if ROM found and if PC-AT. Multiple bi= ts can be set as follows: + - 00 =3D No ROM. + - 01 =3D ROM Found. + - 02 =3D ROM is a valid legacy ROM. + + @retval EFI_SUCCESS The Legacy Option ROM available for this device + @retval EFI_UNSUPPORTED The Legacy Option ROM is not supported. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_CHECK_ROM)( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, OPTIONAL + OUT UINTN *RomSize, OPTIONAL + OUT UINTN *Flags + ); + +/** + Load a legacy PC-AT OPROM on the PciHandle device. Return information + about how many disks were added by the OPROM and the shadow address and + size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C: + + @param[in] This The protocol instance pointer. + @param[in] PciHandle The PCI PC-AT OPROM from this devices ROM= BAR will be loaded. + This value is NULL if RomImage is non-NUL= L. This is the normal + case. + @param[in] RomImage A PCI PC-AT ROM image. This argument is n= on-NULL if there is + no hardware associated with the ROM and t= hus no PciHandle, + otherwise is must be NULL. + Example is PXE base code. + @param[out] Flags The type of ROM discovered. Multiple bits= can be set, as follows: + - 00 =3D No ROM. + - 01 =3D ROM found. + - 02 =3D ROM is a valid legacy ROM. + @param[out] DiskStart The disk number of first device hooked by= the ROM. If DiskStart + is the same as DiskEnd no disked were hoo= ked. + @param[out] DiskEnd disk number of the last device hooked by = the ROM. + @param[out] RomShadowAddress Shadow address of PC-AT ROM. + @param[out] RomShadowSize Size of RomShadowAddress in bytes. + + @retval EFI_SUCCESS Thunk completed, see Regs for status. + @retval EFI_INVALID_PARAMETER PciHandle not found + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_INSTALL_ROM)( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + IN VOID **RomImage, + OUT UINTN *Flags, + OUT UINT8 *DiskStart, OPTIONAL + OUT UINT8 *DiskEnd, OPTIONAL + OUT VOID **RomShadowAddress, OPTIONAL + OUT UINT32 *ShadowedRomSize OPTIONAL + ); + +/** + This function attempts to traditionally boot the specified BootOption. I= f the EFI context has + been compromised, this function will not return. This procedure is not u= sed for loading an EFI-aware + OS off a traditional device. The following actions occur: + - Get EFI SMBIOS data structures, convert them to a traditional format, = and copy to + Compatibility16. + - Get a pointer to ACPI data structures and copy the Compatibility16 RSD= PTR to F0000 block. + - Find the traditional SMI handler from a firmware volume and register t= he traditional SMI + handler with the EFI SMI handler. + - Build onboard IDE information and pass this information to the Compati= bility16 code. + - Make sure all PCI Interrupt Line registers are programmed to match 825= 9. + - Reconfigure SIO devices from EFI mode (polled) into traditional mode (= interrupt driven). + - Shadow all PCI ROMs. + - Set up BDA and EBDA standard areas before the legacy boot. + - Construct the Compatibility16 boot memory map and pass it to the Compa= tibility16 code. + - Invoke the Compatibility16 table function Compatibility16PrepareToBoot= (). This + invocation causes a thunk into the Compatibility16 code, which sets al= l appropriate internal + data structures. The boot device list is a parameter. + - Invoke the Compatibility16 Table function Compatibility16Boot(). This = invocation + causes a thunk into the Compatibility16 code, which does an INT19. + - If the Compatibility16Boot() function returns, then the boot failed in= a graceful + manner--meaning that the EFI code is still valid. An ungraceful boot f= ailure causes a reset because the state + of EFI code is unknown. + + @param[in] This The protocol instance pointer. + @param[in] BootOption The EFI Device Path from BootXXXX variable. + @param[in] LoadOptionSize The size of LoadOption in size. + @param[in] LoadOption LThe oadOption from BootXXXX variable. + + @retval EFI_DEVICE_ERROR Failed to boot from any boot device and me= mory is uncorrupted. Note: This function nor= mally does not returns. It will either boot the = OS or reset the system if memory has been "corrupted" by loading = a boot sector and passing control to it. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_BOOT)( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN BBS_BBS_DEVICE_PATH *BootOption, + IN UINT32 LoadOptionsSize, + IN VOID *LoadOptions + ); + +/** + This function takes the Leds input parameter and sets/resets the BDA acc= ordingly. + Leds is also passed to Compatibility16 code, in case any special process= ing is required. + This function is normally called from EFI Setup drivers that handle user= -selectable + keyboard options such as boot with NUM LOCK on/off. This function does n= ot + touch the keyboard or keyboard LEDs but only the BDA. + + @param[in] This The protocol instance pointer. + @param[in] Leds The status of current Scroll, Num & Cap lock LEDS: + - Bit 0 is Scroll Lock 0 =3D Not locked. + - Bit 1 is Num Lock. + - Bit 2 is Caps Lock. + + @retval EFI_SUCCESS The BDA was updated successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_UPDATE_KEYBOARD_LED_STATUS)( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 Leds + ); + +/** + Retrieve legacy BBS info and assign boot priority. + + @param[in] This The protocol instance pointer. + @param[out] HddCount The number of HDD_INFO structures. + @param[out] HddInfo Onboard IDE controller information. + @param[out] BbsCount The number of BBS_TABLE structures. + @param[in,out] BbsTable Points to List of BBS_TABLE. + + @retval EFI_SUCCESS Tables were returned. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_GET_BBS_INFO)( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *HddCount, + OUT HDD_INFO **HddInfo, + OUT UINT16 *BbsCount, + IN OUT BBS_TABLE **BbsTable + ); + +/** + Assign drive number to legacy HDD drives prior to booting an EFI + aware OS so the OS can access drives without an EFI driver. + + @param[in] This The protocol instance pointer. + @param[out] BbsCount The number of BBS_TABLE structures + @param[out] BbsTable List of BBS entries + + @retval EFI_SUCCESS Drive numbers assigned. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PREPARE_TO_BOOT_EFI)( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *BbsCount, + OUT BBS_TABLE **BbsTable + ); + +/** + To boot from an unconventional device like parties and/or execute + HDD diagnostics. + + @param[in] This The protocol instance pointer. + @param[in] Attributes How to interpret the other input parameter= s. + @param[in] BbsEntry The 0-based index into the BbsTable for th= e parent + device. + @param[in] BeerData A pointer to the 128 bytes of ram BEER dat= a. + @param[in] ServiceAreaData A pointer to the 64 bytes of raw Service A= rea data. The + caller must provide a pointer to the speci= fic Service + Area and not the start all Service Areas. + + @retval EFI_INVALID_PARAMETER If error. Does NOT return if no error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_BOOT_UNCONVENTIONAL_DEVICE)( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UDC_ATTRIBUTES Attributes, + IN UINTN BbsEntry, + IN VOID *BeerData, + IN VOID *ServiceAreaData + ); + +/** + Shadow all legacy16 OPROMs that haven't been shadowed. + Warning: Use this with caution. This routine disconnects all EFI + drivers. If used externally, then the caller must re-connect EFI + drivers. + + @param[in] This The protocol instance pointer. + + @retval EFI_SUCCESS OPROMs were shadowed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_SHADOW_ALL_LEGACY_OPROMS)( + IN EFI_LEGACY_BIOS_PROTOCOL *This + ); + +/** + Get a region from the LegacyBios for S3 usage. + + @param[in] This The protocol instance pointer. + @param[in] LegacyMemorySize The size of required region. + @param[in] Region The region to use. + 00 =3D Either 0xE0000 or 0xF0000 block. + - Bit0 =3D 1 0xF0000 block. + - Bit1 =3D 1 0xE0000 block. + @param[in] Alignment Address alignment. Bit mapped. The fir= st non-zero + bit from right is alignment. + @param[out] LegacyMemoryAddress The Region Assigned + + @retval EFI_SUCCESS The Region was assigned. + @retval EFI_ACCESS_DENIED The function was previously invoked. + @retval Other The Region was not assigned. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_GET_LEGACY_REGION)( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN UINTN Region, + IN UINTN Alignment, + OUT VOID **LegacyMemoryAddress + ); + +/** + Get a region from the LegacyBios for Tiano usage. Can only be invoked on= ce. + + @param[in] This The protocol instance pointer. + @param[in] LegacyMemorySize The size of data to copy. + @param[in] LegacyMemoryAddress The Legacy Region destination ad= dress. + Note: must be in region assigned= by + LegacyBiosGetLegacyRegion. + @param[in] LegacyMemorySourceAddress The source of the data to copy. + + @retval EFI_SUCCESS The Region assigned. + @retval EFI_ACCESS_DENIED Destination was outside an assigned region. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_COPY_LEGACY_REGION)( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN VOID *LegacyMemoryAddress, + IN VOID *LegacyMemorySourceAddress + ); + +/// +/// Abstracts the traditional BIOS from the rest of EFI. The LegacyBoot() +/// member function allows the BDS to support booting a traditional OS. +/// EFI thunks drivers that make EFI bindings for BIOS INT services use +/// all the other member functions. +/// +struct _EFI_LEGACY_BIOS_PROTOCOL { + /// + /// Performs traditional software INT. See the Int86() function descript= ion. + /// + EFI_LEGACY_BIOS_INT86 Int86; + + /// + /// Performs a far call into Compatibility16 or traditional OpROM code. + /// + EFI_LEGACY_BIOS_FARCALL86 FarCall86; + + /// + /// Checks if a traditional OpROM exists for this device. + /// + EFI_LEGACY_BIOS_CHECK_ROM CheckPciRom; + + /// + /// Loads a traditional OpROM in traditional OpROM address space. + /// + EFI_LEGACY_BIOS_INSTALL_ROM InstallPciRom; + + /// + /// Boots a traditional OS. + /// + EFI_LEGACY_BIOS_BOOT LegacyBoot; + + /// + /// Updates BDA to reflect the current EFI keyboard LED status. + /// + EFI_LEGACY_BIOS_UPDATE_KEYBOARD_LED_STATUS UpdateKeyboardLedStatus; + + /// + /// Allows an external agent, such as BIOS Setup, to get the BBS data. + /// + EFI_LEGACY_BIOS_GET_BBS_INFO GetBbsInfo; + + /// + /// Causes all legacy OpROMs to be shadowed. + /// + EFI_LEGACY_BIOS_SHADOW_ALL_LEGACY_OPROMS ShadowAllLegacyOproms; + + /// + /// Performs all actions prior to boot. Used when booting an EFI-aware OS + /// rather than a legacy OS. + /// + EFI_LEGACY_BIOS_PREPARE_TO_BOOT_EFI PrepareToBootEfi; + + /// + /// Allows EFI to reserve an area in the 0xE0000 or 0xF0000 block. + /// + EFI_LEGACY_BIOS_GET_LEGACY_REGION GetLegacyRegion; + + /// + /// Allows EFI to copy data to the area specified by GetLegacyRegion. + /// + EFI_LEGACY_BIOS_COPY_LEGACY_REGION CopyLegacyRegion; + + /// + /// Allows the user to boot off an unconventional device such as a PARTI= ES partition. + /// + EFI_LEGACY_BIOS_BOOT_UNCONVENTIONAL_DEVICE BootUnconventionalDevice; +}; + +// +// Legacy BIOS needs to access memory in page 0 (0-4095), which is disable= d if +// NULL pointer detection feature is enabled. Following macro can be used = to +// enable/disable page 0 before/after accessing it. +// +#define ACCESS_PAGE0_CODE(statements) \ + do { \ + EFI_STATUS Status_; \ + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Desc_; \ + \ + Desc_.Attributes =3D 0; \ + Status_ =3D gDS->GetMemorySpaceDescriptor (0, &Desc_); \ + ASSERT_EFI_ERROR (Status_); \ + if ((Desc_.Attributes & EFI_MEMORY_RP) !=3D 0) { \ + Status_ =3D gDS->SetMemorySpaceAttributes ( \ + 0, \ + EFI_PAGES_TO_SIZE(1), \ + Desc_.Attributes & ~(UINT64)EFI_MEMORY_RP \ + ); \ + ASSERT_EFI_ERROR (Status_); \ + } \ + \ + { \ + statements; \ + } \ + \ + if ((Desc_.Attributes & EFI_MEMORY_RP) !=3D 0) { \ + Status_ =3D gDS->SetMemorySpaceAttributes ( \ + 0, \ + EFI_PAGES_TO_SIZE(1), \ + Desc_.Attributes \ + ); \ + ASSERT_EFI_ERROR (Status_); \ + } \ + } while (FALSE) + +extern EFI_GUID gEfiLegacyBiosProtocolGuid; + +#endif diff --git a/OvmfPkg/Csm/Include/Protocol/LegacyBiosPlatform.h b/OvmfPkg/Cs= m/Include/Protocol/LegacyBiosPlatform.h new file mode 100644 index 0000000000..0a164dad3b --- /dev/null +++ b/OvmfPkg/Csm/Include/Protocol/LegacyBiosPlatform.h @@ -0,0 +1,755 @@ +/** @file + The EFI Legacy BIOS Patform Protocol is used to mate a Legacy16 + implementation with this EFI code. The EFI driver that produces + the Legacy BIOS protocol is generic and consumes this protocol. + A driver that matches the Legacy16 produces this protocol + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Revision Reference: + This protocol is defined in Framework for EFI Compatibility Support Modu= le spec + Version 0.97. + +**/ + +#ifndef _EFI_LEGACY_BIOS_PLATFORM_H_ +#define _EFI_LEGACY_BIOS_PLATFORM_H_ + +/// +/// Legacy BIOS Platform depends on HDD_INFO and EFI_COMPATIBILITY16_TABLE= that +/// are defined with the Legacy BIOS Protocol +/// +#include + +#define EFI_LEGACY_BIOS_PLATFORM_PROTOCOL_GUID \ + { \ + 0x783658a3, 0x4172, 0x4421, {0xa2, 0x99, 0xe0, 0x9, 0x7, 0x9c, 0xc, 0x= b4 } \ + } + +typedef struct _EFI_LEGACY_BIOS_PLATFORM_PROTOCOL EFI_LEGACY_BIOS_PLATFORM= _PROTOCOL; + +/** + This enum specifies the Mode param values for GetPlatformInfo() +**/ +typedef enum { + /// + /// This mode is invoked twice. The first invocation has LegacySegment a= nd + /// LegacyOffset set to 0. The mode returns the MP table address in EFI = memory, along with its size. + /// The second invocation has LegacySegment and LegacyOffset set to the = location + /// in the 0xF0000 or 0xE0000 block to which the MP table is to be copie= d. The second + /// invocation allows any MP table address fixes to occur in the EFI mem= ory copy of the + /// MP table. The caller, not EfiGetPlatformBinaryMpTable, copies the mo= dified MP + /// table to the allocated region in 0xF0000 or 0xE0000 block after the = second invocation. + /// + /// The function parameters associated with this mode are: + /// + /// Table Pointer to the MP table. + /// + /// TableSize Size in bytes of the MP table. + /// + /// Location Location to place table. 0x00. Either 0xE0000 or 0xF0000 = 64 KB blocks. + /// Bit 0 =3D 1 0xF0000 64 KB block. + /// Bit 1 =3D 1 0xE0000 64 KB block. + /// Multiple bits can be set. + /// + /// Alignment Bit-mapped address alignment granularity. + /// The first nonzero bit from the right is the address granularity. + /// + // LegacySegment Segment in which EfiCompatibility code will place th= e MP table. + /// + /// LegacyOffset Offset in which EfiCompatibility code will place the = MP table. + /// + /// The return values associated with this mode are: + /// + /// EFI_SUCCESS The MP table was returned. + /// + /// EFI_UNSUPPORTED The MP table is not supported on this platform. + /// + EfiGetPlatformBinaryMpTable =3D 0, + /// + /// This mode returns a block of data. The content and usage is IBV or O= EM defined. + /// OEMs or IBVs normally use this function for nonstandard Compatibilit= y16 runtime soft + /// INTs. It is the responsibility of this routine to coalesce multiple = OEM 16 bit functions, if + /// they exist, into one coherent package that is understandable by the = Compatibility16 code. + /// This function is invoked twice. The first invocation has LegacySegme= nt and + /// LegacyOffset set to 0. The function returns the table address in EFI= memory, as well as its size. + /// The second invocation has LegacySegment and LegacyOffset set to the = location + /// in the 0xF0000 or 0xE0000 block to which the data (table) is to be c= opied. The second + /// invocation allows any data (table) address fixes to occur in the EFI= memory copy of + /// the table. The caller, not GetOemIntData(), copies the modified data= (table) to the + /// allocated region in 0xF0000 or 0xE0000 block after the second invoca= tion. + /// + /// The function parameters associated with this mode are: + /// + /// Table Pointer to OEM legacy 16 bit code or data. + /// + /// TableSize Size of data. + /// + /// Location Location to place table. 0x00. Either 0xE0000 or 0xF0000 = 64 KB blocks. + /// Bit 0 =3D 1 0xF0000 64 KB block. + /// Bit 1 =3D 1 0xE0000 64 KB block. + /// Multiple bits can be set. + /// + /// Alignment Bit mapped address alignment granularity. + /// The first nonzero bit from the right is the address granularity. + /// + /// LegacySegment Segment in which EfiCompatibility code will place th= e table or data. + /// + /// LegacyOffset Offset in which EfiCompatibility code will place the = table or data. + /// + /// The return values associated with this mode are: + /// + /// EFI_SUCCESS The data was returned successfully. + /// + /// EFI_UNSUPPORTED Oem INT is not supported on this platform. + /// + EfiGetPlatformBinaryOemIntData =3D 1, + /// + /// This mode returns a block of data. The content and usage is IBV defi= ned. OEMs or + /// IBVs normally use this mode for nonstandard Compatibility16 runtime = 16 bit routines. It + /// is the responsibility of this routine to coalesce multiple OEM 16 bi= t functions, if they + /// exist, into one coherent package that is understandable by the Compa= tibility16 code. + /// + /// Example usage: A legacy mobile BIOS that has a pre-existing runtime + /// interface to return the battery status to calling applications. + /// + /// This mode is invoked twice. The first invocation has LegacySegment a= nd + /// LegacyOffset set to 0. The mode returns the table address in EFI mem= ory and its size. + /// The second invocation has LegacySegment and LegacyOffset set to the = location + /// in the 0xF0000 or 0xE0000 block to which the table is to be copied. = The second + /// invocation allows any table address fixes to occur in the EFI memory= copy of the table. + /// The caller, not EfiGetPlatformBinaryOem16Data, copies the modified t= able to + /// the allocated region in 0xF0000 or 0xE0000 block after the second in= vocation. + /// + /// The function parameters associated with this mode are: + /// + /// Table Pointer to OEM legacy 16 bit code or data. + /// + /// TableSize Size of data. + /// + /// Location Location to place the table. 0x00. Either 0xE0000 or 0xF0= 000 64 KB blocks. + /// Bit 0 =3D 1 0xF0000 64 KB block. + /// Bit 1 =3D 1 0xE0000 64 KB block. + /// Multiple bits can be set. + /// + /// Alignment Bit mapped address alignment granularity. + /// The first nonzero bit from the right is the address granularity. + /// + /// LegacySegment Segment in which EfiCompatibility code will place th= e table or data. + /// + /// LegacyOffset Offset in which EfiCompatibility code will place the = table or data. + /// + /// The return values associated with this mode are: + /// + /// EFI_SUCCESS The data was returned successfully. + /// + /// EFI_UNSUPPORTED Oem16 is not supported on this platform. + /// + EfiGetPlatformBinaryOem16Data =3D 2, +/// +/// This mode returns a block of data. The content and usage are IBV defin= ed. OEMs or +/// IBVs normally use this mode for nonstandard Compatibility16 runtime 32= bit routines. It +/// is the responsibility of this routine to coalesce multiple OEM 32 bit = functions, if they +/// exist, into one coherent package that is understandable by the Compati= bility16 code. +/// +/// Example usage: A legacy mobile BIOS that has a pre existing runtime +/// interface to return the battery status to calling applications. +/// +/// This mode is invoked twice. The first invocation has LegacySegment and +/// LegacyOffset set to 0. The mode returns the table address in EFI memor= y and its size. +/// +/// The second invocation has LegacySegment and LegacyOffset set to the lo= cation +/// in the 0xF0000 or 0xE0000 block to which the table is to be copied. Th= e second +/// invocation allows any table address fix ups to occur in the EFI memory= copy of the table. +/// The caller, not EfiGetPlatformBinaryOem32Data, copies the modified tab= le to +/// the allocated region in 0xF0000 or 0xE0000 block after the second invo= cation.. +/// +/// Note: There are two generic mechanisms by which this mode can be used. +/// Mechanism 1: This mode returns the data and the Legacy BIOS Protocol c= opies +/// the data into the F0000 or E0000 block in the Compatibility16 code. The +/// EFI_COMPATIBILITY16_TABLE entries Oem32Segment and Oem32Offset can +/// be viewed as two UINT16 entries. +/// Mechanism 2: This mode directly fills in the EFI_COMPATIBILITY16_TABLE= with +/// a pointer to the INT15 E820 region containing the 32 bit code. It retu= rns +/// EFI_UNSUPPORTED. The EFI_COMPATIBILITY16_TABLE entries, +/// Oem32Segment and Oem32Offset, can be viewed as two UINT16 entries or +/// as a single UINT32 entry as determined by the IBV. +/// +/// The function parameters associated with this mode are: +/// +/// TableSize Size of data. +/// +/// Location Location to place the table. 0x00 or 0xE0000 or 0xF0000 64 = KB blocks. +/// Bit 0 =3D 1 0xF0000 64 KB block. +/// Bit 1 =3D 1 0xE0000 64 KB block. +/// Multiple bits can be set. +/// +/// Alignment Bit mapped address alignment granularity. +/// The first nonzero bit from the right is the address granularity. +/// +/// LegacySegment Segment in which EfiCompatibility code will place the = table or data. +/// +/// LegacyOffset Offset in which EfiCompatibility code will place the ta= ble or data. +/// +/// The return values associated with this mode are: +/// EFI_SUCCESS The data was returned successfully. +/// EFI_UNSUPPORTED Oem32 is not supported on this platform. +/// +EfiGetPlatformBinaryOem32Data =3D 3, + /// + /// This mode returns a TPM binary image for the onboard TPM device. + /// + /// The function parameters associated with this mode are: + /// + /// Table TPM binary image for the onboard TPM device. + /// + /// TableSize Size of BinaryImage in bytes. + /// + /// Location Location to place the table. 0x00. Either 0xE0000 or 0xF0= 000 64 KB blocks. + /// Bit 0 =3D 1 0xF0000 64 KB block. + /// Bit 1 =3D 1 0xE0000 64 KB block. + /// Multiple bits can be set. + /// + /// Alignment Bit mapped address alignment granularity. + /// The first nonzero bit from the right is the address granularity. + /// + /// LegacySegment Segment in which EfiCompatibility code will place th= e table or data. + /// + /// LegacyOffset Offset in which EfiCompatibility code will place the = table or data. + /// + /// The return values associated with this mode are: + /// + /// EFI_SUCCESS BinaryImage is valid. + /// + /// EFI_UNSUPPORTED Mode is not supported on this platform. + /// + /// EFI_NOT_FOUND No BinaryImage was found. + /// + EfiGetPlatformBinaryTpmBinary =3D 4, + /// + /// The mode finds the Compatibility16 Rom Image. + /// + /// The function parameters associated with this mode are: + /// + /// System ROM image for the platform. + /// + /// TableSize Size of Table in bytes. + /// + /// Location Ignored. + /// + /// Alignment Ignored. + /// + /// LegacySegment Ignored. + /// + /// LegacyOffset Ignored. + /// + /// The return values associated with this mode are: + /// + /// EFI_SUCCESS ROM image found. + /// + /// EFI_NOT_FOUND ROM not found. + /// + EfiGetPlatformBinarySystemRom =3D 5, + /// + /// This mode returns the Base address of PciExpress memory mapped confi= guration + /// address space. + /// + /// The function parameters associated with this mode are: + /// + /// Table System ROM image for the platform. + /// + /// TableSize Size of Table in bytes. + /// + /// Location Ignored. + /// + /// Alignment Ignored. + /// + /// LegacySegment Ignored. + /// + /// LegacyOffset Ignored. + /// + /// The return values associated with this mode are: + /// + /// EFI_SUCCESS Address is valid. + /// + /// EFI_UNSUPPORTED System does not PciExpress. + /// + EfiGetPlatformPciExpressBase =3D 6, + /// + EfiGetPlatformPmmSize =3D 7, + /// + EfiGetPlatformEndOpromShadowAddr =3D 8, + /// +} EFI_GET_PLATFORM_INFO_MODE; + +/** + This enum specifies the Mode param values for GetPlatformHandle(). +**/ +typedef enum { + /// + /// This mode returns the Compatibility16 policy for the device that sho= uld be the VGA + /// controller used during a Compatibility16 boot. + /// + /// The function parameters associated with this mode are: + /// + /// Type 0x00. + /// + /// HandleBuffer Buffer of all VGA handles found. + /// + /// HandleCount Number of VGA handles found. + /// + /// AdditionalData NULL. + /// + EfiGetPlatformVgaHandle =3D 0, + /// + /// This mode returns the Compatibility16 policy for the device that sho= uld be the IDE + /// controller used during a Compatibility16 boot. + /// + /// The function parameters associated with this mode are: + /// + /// Type 0x00. + /// + /// HandleBuffer Buffer of all IDE handles found. + /// + /// HandleCount Number of IDE handles found. + /// + /// AdditionalData Pointer to HddInfo. + /// Information about all onboard IDE controllers. + /// + EfiGetPlatformIdeHandle =3D 1, + /// + /// This mode returns the Compatibility16 policy for the device that sho= uld be the ISA bus + /// controller used during a Compatibility16 boot. + /// + /// The function parameters associated with this mode are: + /// + /// Type 0x00. + /// + /// HandleBuffer Buffer of all ISA bus handles found. + /// + /// HandleCount Number of ISA bus handles found. + /// + /// AdditionalData NULL. + /// + EfiGetPlatformIsaBusHandle =3D 2, + /// + /// This mode returns the Compatibility16 policy for the device that sho= uld be the USB + /// device used during a Compatibility16 boot. + /// + /// The function parameters associated with this mode are: + /// + /// Type 0x00. + /// + /// HandleBuffer Buffer of all USB handles found. + /// + /// HandleCount Number of USB bus handles found. + /// + /// AdditionalData NULL. + /// + EfiGetPlatformUsbHandle =3D 3 +} EFI_GET_PLATFORM_HANDLE_MODE; + +/** + This enum specifies the Mode param values for PlatformHooks(). + Note: Any OEM defined hooks start with 0x8000. +**/ +typedef enum { + /// + /// This mode allows any preprocessing before scanning OpROMs. + /// + /// The function parameters associated with this mode are: + /// + /// Type 0. + /// + /// DeviceHandle Handle of device OpROM is associated with. + /// + /// ShadowAddress Address where OpROM is shadowed. + /// + /// Compatibility16Table NULL. + /// + /// AdditionalData NULL. + /// + EfiPlatformHookPrepareToScanRom =3D 0, + /// + /// This mode shadows legacy OpROMS that may not have a physical device = associated with + /// them. It returns EFI_SUCCESS if the ROM was shadowed. + /// + /// The function parameters associated with this mode are: + /// + /// Type 0. + /// + /// DeviceHandle 0. + /// + /// ShadowAddress First free OpROM area, after other OpROMs have bee= n dispatched.. + /// + /// Compatibility16Table Pointer to the Compatability16 Table. + /// + /// AdditionalData NULL. + /// + EfiPlatformHookShadowServiceRoms=3D 1, + /// + /// This mode allows platform to perform any required operation after an= OpROM has + /// completed its initialization. + /// + /// The function parameters associated with this mode are: + /// + /// Type 0. + /// + /// DeviceHandle Handle of device OpROM is associated with. + /// + /// ShadowAddress Address where OpROM is shadowed. + /// + /// Compatibility16Table NULL. + /// + /// AdditionalData NULL. + /// + EfiPlatformHookAfterRomInit =3D 2 +} EFI_GET_PLATFORM_HOOK_MODE; + +/// +/// This IRQ has not been assigned to PCI. +/// +#define PCI_UNUSED 0x00 +/// +/// This IRQ has been assigned to PCI. +/// +#define PCI_USED 0xFF +/// +/// This IRQ has been used by an SIO legacy device and cannot be used by P= CI. +/// +#define LEGACY_USED 0xFE + +#pragma pack(1) + +typedef struct { + /// + /// IRQ for this entry. + /// + UINT8 Irq; + /// + /// Status of this IRQ. + /// + /// PCI_UNUSED 0x00. This IRQ has not been assigned to PCI. + /// + /// PCI_USED 0xFF. This IRQ has been assigned to PCI. + /// + /// LEGACY_USED 0xFE. This IRQ has been used by an SIO legacy + /// device and cannot be used by PCI. + /// + UINT8 Used; +} EFI_LEGACY_IRQ_PRIORITY_TABLE_ENTRY; + +// +// Define PIR table structures +// +#define EFI_LEGACY_PIRQ_TABLE_SIGNATURE SIGNATURE_32 ('$', 'P', 'I', 'R') + +typedef struct { + /// + /// $PIR. + /// + UINT32 Signature; + /// + /// 0x00. + /// + UINT8 MinorVersion; + /// + /// 0x01 for table version 1.0. + /// + UINT8 MajorVersion; + /// + /// 0x20 + RoutingTableEntries * 0x10. + /// + UINT16 TableSize; + /// + /// PCI interrupt router bus. + /// + UINT8 Bus; + /// + /// PCI interrupt router device/function. + /// + UINT8 DevFun; + /// + /// If nonzero, bit map of IRQs reserved for PCI. + /// + UINT16 PciOnlyIrq; + /// + /// Vendor ID of a compatible PCI interrupt router. + /// + UINT16 CompatibleVid; + /// + /// Device ID of a compatible PCI interrupt router. + /// + UINT16 CompatibleDid; + /// + /// If nonzero, a value passed directly to the IRQ miniport's Initialize= function. + /// + UINT32 Miniport; + /// + /// Reserved for future usage. + /// + UINT8 Reserved[11]; + /// + /// This byte plus the sum of all other bytes in the LocalPirqTable equa= l 0x00. + /// + UINT8 Checksum; +} EFI_LEGACY_PIRQ_TABLE_HEADER; + + +typedef struct { + /// + /// If nonzero, a value assigned by the IBV. + /// + UINT8 Pirq; + /// + /// If nonzero, the IRQs that can be assigned to this device. + /// + UINT16 IrqMask; +} EFI_LEGACY_PIRQ_ENTRY; + +typedef struct { + /// + /// PCI bus of the entry. + /// + UINT8 Bus; + /// + /// PCI device of this entry. + /// + UINT8 Device; + /// + /// An IBV value and IRQ mask for PIRQ pins A through D. + /// + EFI_LEGACY_PIRQ_ENTRY PirqEntry[4]; + /// + /// If nonzero, the slot number assigned by the board manufacturer. + /// + UINT8 Slot; + /// + /// Reserved for future use. + /// + UINT8 Reserved; +} EFI_LEGACY_IRQ_ROUTING_ENTRY; + +#pragma pack() + + +/** + Finds the binary data or other platform information. + + @param This The protocol instance pointer. + @param Mode Specifies what data to return. See See EFI= _GET_PLATFORM_INFO_MODE enum. + @param Table Mode specific. See EFI_GET_PLATFORM_INFO_= MODE enum. + @param TableSize Mode specific. See EFI_GET_PLATFORM_INFO= _MODE enum. + @param Location Mode specific. See EFI_GET_PLATFORM_INFO= _MODE enum. + @param Alignment Mode specific. See EFI_GET_PLATFORM_INFO_= MODE enum. + @param LegacySegment Mode specific. See EFI_GET_PLATFORM_INFO_= MODE enum. + @param LegacyOffset Mode specific. See EFI_GET_PLATFORM_INFO_= MODE enum. + + @retval EFI_SUCCESS Data returned successfully. + @retval EFI_UNSUPPORTED Mode is not supported on the platform. + @retval EFI_NOT_FOUND Binary image or table not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PLATFORM_GET_PLATFORM_INFO)( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN EFI_GET_PLATFORM_INFO_MODE Mode, + OUT VOID **Table, + OUT UINTN *TableSize, + OUT UINTN *Location, + OUT UINTN *Alignment, + IN UINT16 LegacySegment, + IN UINT16 LegacyOffset + ); + +/** + Returns a buffer of handles for the requested subfunction. + + @param This The protocol instance pointer. + @param Mode Specifies what handle to return. See EFI_G= ET_PLATFORM_HANDLE_MODE enum. + @param Type Mode specific. See EFI_GET_PLATFORM_HANDLE= _MODE enum. + @param HandleBuffer Mode specific. See EFI_GET_PLATFORM_HANDLE= _MODE enum. + @param HandleCount Mode specific. See EFI_GET_PLATFORM_HANDLE= _MODE enum. + @param AdditionalData Mode specific. See EFI_GET_PLATFORM_HANDLE= _MODE enum. + + @retval EFI_SUCCESS Handle is valid. + @retval EFI_UNSUPPORTED Mode is not supported on the platform. + @retval EFI_NOT_FOUND Handle is not known. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PLATFORM_GET_PLATFORM_HANDLE)( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN EFI_GET_PLATFORM_HANDLE_MODE Mode, + IN UINT16 Type, + OUT EFI_HANDLE **HandleBuffer, + OUT UINTN *HandleCount, + IN VOID **AdditionalData OPTIONAL + ); + +/** + Load and initialize the Legacy BIOS SMM handler. + + @param This The protocol instance pointer. + @param EfiToLegacy16BootTable A pointer to Legacy16 boot table. + + @retval EFI_SUCCESS SMM code loaded. + @retval EFI_DEVICE_ERROR SMM code failed to load + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PLATFORM_SMM_INIT)( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN VOID *EfiToLegacy16BootTable + ); + +/** + Allows platform to perform any required action after a LegacyBios operat= ion. + Invokes the specific sub function specified by Mode. + + @param This The protocol instance pointer. + @param Mode Specifies what handle to return. See EFI_G= ET_PLATFORM_HOOK_MODE enum. + @param Type Mode specific. See EFI_GET_PLATFORM_HOOK_= MODE enum. + @param DeviceHandle Mode specific. See EFI_GET_PLATFORM_HOOK_= MODE enum. + @param ShadowAddress Mode specific. See EFI_GET_PLATFORM_HOOK_= MODE enum. + @param Compatibility16Table Mode specific. See EFI_GET_PLATFORM_HOOK_= MODE enum. + @param AdditionalData Mode specific. See EFI_GET_PLATFORM_HOOK_= MODE enum. + + @retval EFI_SUCCESS The operation performed successfully. Mode= specific. + @retval EFI_UNSUPPORTED Mode is not supported on the platform. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PLATFORM_HOOKS)( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN EFI_GET_PLATFORM_HOOK_MODE Mode, + IN UINT16 Type, + IN EFI_HANDLE DeviceHandle, OPTIONAL + IN OUT UINTN *ShadowAddress, OPTIONAL + IN EFI_COMPATIBILITY16_TABLE *Compatibility16Table, OPTIONAL + OUT VOID **AdditionalData OPTIONAL + ); + +/** + Returns information associated with PCI IRQ routing. + This function returns the following information associated with PCI IRQ = routing: + * An IRQ routing table and number of entries in the table. + * The $PIR table and its size. + * A list of PCI IRQs and the priority order to assign them. + + @param This The protocol instance pointer. + @param RoutingTable The pointer to PCI IRQ Routing table. + This location is the $PIR table minus th= e header. + @param RoutingTableEntries The number of entries in table. + @param LocalPirqTable $PIR table. + @param PirqTableSize $PIR table size. + @param LocalIrqPriorityTable A list of interrupts in priority order t= o assign. + @param IrqPriorityTableEntries The number of entries in the priority ta= ble. + + @retval EFI_SUCCESS Data was successfully returned. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PLATFORM_GET_ROUTING_TABLE)( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + OUT VOID **RoutingTable, + OUT UINTN *RoutingTableEntries, + OUT VOID **LocalPirqTable, OPTIONAL + OUT UINTN *PirqTableSize, OPTIONAL + OUT VOID **LocalIrqPriorityTable, OPTIONAL + OUT UINTN *IrqPriorityTableEntries OPTIONAL + ); + +/** + Translates the given PIRQ accounting for bridge. + This function translates the given PIRQ back through all buses, if requi= red, + and returns the true PIRQ and associated IRQ. + + @param This The protocol instance pointer. + @param PciBus The PCI bus number for this device. + @param PciDevice The PCI device number for this device. + @param PciFunction The PCI function number for this device. + @param Pirq Input is PIRQ reported by device, and outp= ut is true PIRQ. + @param PciIrq The IRQ already assigned to the PIRQ, or t= he IRQ to be + assigned to the PIRQ. + + @retval EFI_SUCCESS The PIRQ was translated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PLATFORM_TRANSLATE_PIRQ)( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN UINTN PciBus, + IN UINTN PciDevice, + IN UINTN PciFunction, + IN OUT UINT8 *Pirq, + OUT UINT8 *PciIrq + ); + +/** + Attempt to legacy boot the BootOption. If the EFI contexted has been + compromised this function will not return. + + @param This The protocol instance pointer. + @param BbsDevicePath The EFI Device Path from BootXXXX variabl= e. + @param BbsTable The Internal BBS table. + @param LoadOptionSize The size of LoadOption in size. + @param LoadOption The LoadOption from BootXXXX variable + @param EfiToLegacy16BootTable A pointer to BootTable structure + + @retval EFI_SUCCESS Ready to boot. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PLATFORM_PREPARE_TO_BOOT)( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN BBS_BBS_DEVICE_PATH *BbsDevicePath, + IN VOID *BbsTable, + IN UINT32 LoadOptionsSize, + IN VOID *LoadOptions, + IN VOID *EfiToLegacy16BootTable + ); + +/** + This protocol abstracts the platform portion of the traditional BIOS. +**/ +struct _EFI_LEGACY_BIOS_PLATFORM_PROTOCOL { + /// + /// Gets binary data or other platform information. + /// + EFI_LEGACY_BIOS_PLATFORM_GET_PLATFORM_INFO GetPlatformInfo; + /// + /// Returns a buffer of all handles matching the requested subfunction. + /// + EFI_LEGACY_BIOS_PLATFORM_GET_PLATFORM_HANDLE GetPlatformHandle; + /// + /// Loads and initializes the traditional BIOS SMM handler. + EFI_LEGACY_BIOS_PLATFORM_SMM_INIT SmmInit; + /// + /// Allows platform to perform any required actions after a LegacyBios = operation. + /// + EFI_LEGACY_BIOS_PLATFORM_HOOKS PlatformHooks; + /// + /// Gets $PIR table. + EFI_LEGACY_BIOS_PLATFORM_GET_ROUTING_TABLE GetRoutingTable; + /// + /// Translates the given PIRQ to the final value after traversing any P= CI bridges. + /// + EFI_LEGACY_BIOS_PLATFORM_TRANSLATE_PIRQ TranslatePirq; + /// + /// Final platform function before the system attempts to boot to a tra= ditional OS. + /// + EFI_LEGACY_BIOS_PLATFORM_PREPARE_TO_BOOT PrepareToBoot; +}; + +extern EFI_GUID gEfiLegacyBiosPlatformProtocolGuid; + +#endif diff --git a/OvmfPkg/Csm/Include/Protocol/LegacyInterrupt.h b/OvmfPkg/Csm/I= nclude/Protocol/LegacyInterrupt.h new file mode 100644 index 0000000000..b3ad2ffb3c --- /dev/null +++ b/OvmfPkg/Csm/Include/Protocol/LegacyInterrupt.h @@ -0,0 +1,122 @@ +/** @file + This protocol abstracts the PIRQ programming from the generic EFI Compat= ibility Support Modules (CSMs). + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Revision Reference: + This protocol is defined in Framework for the EFI Compatibility Support = Module specification. + Version 0.97. + +**/ + +#ifndef _EFI_LEGACY_INTERRUPT_H_ +#define _EFI_LEGACY_INTERRUPT_H_ + + +#define EFI_LEGACY_INTERRUPT_PROTOCOL_GUID \ + { \ + 0x31ce593d, 0x108a, 0x485d, {0xad, 0xb2, 0x78, 0xf2, 0x1f, 0x29, 0x66,= 0xbe } \ + } + +typedef struct _EFI_LEGACY_INTERRUPT_PROTOCOL EFI_LEGACY_INTERRUPT_PROTOCO= L; + +/** + Get the number of PIRQs this hardware supports. + + @param This The protocol instance pointer. + @param NumberPirsq The number of PIRQs that are supported. + + @retval EFI_SUCCESS The number of PIRQs was returned successfu= lly. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_INTERRUPT_GET_NUMBER_PIRQS)( + IN EFI_LEGACY_INTERRUPT_PROTOCOL *This, + OUT UINT8 *NumberPirqs + ); + +/** + Gets the PCI location associated with this protocol. + + @param This The Protocol instance pointer. + @param Bus The PCI Bus. + @param Device The PCI Device. + @param Function The PCI Function. + + @retval EFI_SUCCESS The Bus, Device, and Function were returne= d successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_INTERRUPT_GET_LOCATION)( + IN EFI_LEGACY_INTERRUPT_PROTOCOL *This, + OUT UINT8 *Bus, + OUT UINT8 *Device, + OUT UINT8 *Function + ); + +/** + Read the PIRQ register and return the data + + @param This The protocol instance pointer. + @param PirqNumber The PIRQ register to read. + @param PirqData The data read. + + @retval EFI_SUCCESS The data was read. + @retval EFI_INVALID_PARAMETER Invalid PIRQ number. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_INTERRUPT_READ_PIRQ)( + IN EFI_LEGACY_INTERRUPT_PROTOCOL *This, + IN UINT8 PirqNumber, + OUT UINT8 *PirqData + ); + +/** + Write the specified PIRQ register with the given data. + + @param This The protocol instance pointer. + @param PirqNumber A PIRQ register to read. + @param PirqData The data to write. + + @retval EFI_SUCCESS The PIRQ was programmed. + @retval EFI_INVALID_PARAMETER Invalid PIRQ number. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_INTERRUPT_WRITE_PIRQ)( + IN EFI_LEGACY_INTERRUPT_PROTOCOL *This, + IN UINT8 PirqNumber, + IN UINT8 PirqData + ); + +struct _EFI_LEGACY_INTERRUPT_PROTOCOL { + /// + /// Gets the number of PIRQs supported. + /// + EFI_LEGACY_INTERRUPT_GET_NUMBER_PIRQS GetNumberPirqs; + + /// + /// Gets the PCI bus, device, and function that is associated with this = protocol. + /// + EFI_LEGACY_INTERRUPT_GET_LOCATION GetLocation; + + /// + /// Reads the indicated PIRQ register. + /// + EFI_LEGACY_INTERRUPT_READ_PIRQ ReadPirq; + + /// + /// Writes to the indicated PIRQ register. + /// + EFI_LEGACY_INTERRUPT_WRITE_PIRQ WritePirq; +}; + +extern EFI_GUID gEfiLegacyInterruptProtocolGuid; + +#endif diff --git a/OvmfPkg/Csm/Include/Protocol/VgaMiniPort.h b/OvmfPkg/Csm/Inclu= de/Protocol/VgaMiniPort.h new file mode 100644 index 0000000000..41ff58e14c --- /dev/null +++ b/OvmfPkg/Csm/Include/Protocol/VgaMiniPort.h @@ -0,0 +1,88 @@ +/** @file + The VGA Mini Port Protocol used to set the text display mode of a VGA co= ntroller. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __VGA_MINI_PORT_H_ +#define __VGA_MINI_PORT_H_ + +/// +/// Global ID for the EFI_VGA_MINI_PORT_PROTOCOL. +/// +#define EFI_VGA_MINI_PORT_PROTOCOL_GUID \ + { \ + 0xc7735a2f, 0x88f5, 0x4882, {0xae, 0x63, 0xfa, 0xac, 0x8c, 0x8b, 0x86,= 0xb3 } \ + } + +/// +/// Forward declaration for the EFI_VGA_MINI_PORT_PROTOCOL. +/// +typedef struct _EFI_VGA_MINI_PORT_PROTOCOL EFI_VGA_MINI_PORT_PROTOCOL; + +/** + Sets the text display mode of a VGA controller. + + Sets the text display mode of the VGA controller to the mode specified by + ModeNumber. A ModeNumber of 0 is a request for an 80x25 text mode. A + ModeNumber of 1 is a request for an 80x50 text mode. If ModeNumber is g= reater + than MaxModeNumber, then EFI_UNSUPPORTED is returned. If the VGA contro= ller + is not functioning properly, then EFI_DEVICE_ERROR is returned. If the = VGA + controller is sucessfully set to the mode number specified by ModeNumber= , then + EFI_SUCCESS is returned. + + @param[in] This A pointer to the EFI_VGA_MINI_PORT_PROTOCOL inst= ance. + @param[in] ModeNumber The requested mode number. 0 for 80x25. 1 for = 80x5. + + @retval EFI_SUCCESS The mode number was set. + @retval EFI_UNSUPPORTED The mode number specified by ModeNumber is no= t supported. + @retval EFI_DEVICE_ERROR The device is not functioning properly. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_VGA_MINI_PORT_SET_MODE)( + IN EFI_VGA_MINI_PORT_PROTOCOL *This, + IN UINTN ModeNumber + ); + +struct _EFI_VGA_MINI_PORT_PROTOCOL { + EFI_VGA_MINI_PORT_SET_MODE SetMode; + /// + /// MMIO base address of the VGA text mode framebuffer. Typically set t= o 0xB8000. + /// + UINT64 VgaMemoryOffset; + /// + /// I/O Port address for the VGA CRTC address register. Typically set to= 0x3D4. + /// + UINT64 CrtcAddressRegisterOffset; + /// + /// I/O Port address for the VGA CRTC data register. Typically set to 0= x3D5. + /// + UINT64 CrtcDataRegisterOffset; + /// + /// PCI Controller MMIO BAR index of the VGA text mode frame buffer. Ty= pically + /// set to EFI_PCI_IO_PASS_THROUGH_BAR + /// + UINT8 VgaMemoryBar; + /// + /// PCI Controller I/O BAR index of the VGA CRTC address register. Typi= cally + /// set to EFI_PCI_IO_PASS_THROUGH_BAR + /// + UINT8 CrtcAddressRegisterBar; + /// + /// PCI Controller I/O BAR index of the VGA CRTC data register. Typical= ly set + /// to EFI_PCI_IO_PASS_THROUGH_BAR + /// + UINT8 CrtcDataRegisterBar; + /// + /// The maximum number of text modes that this VGA controller supports. + /// + UINT8 MaxMode; +}; + +extern EFI_GUID gEfiVgaMiniPortProtocolGuid; + +#endif diff --git a/OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h b/OvmfPkg/Csm/= LegacyBiosDxe/LegacyBiosInterface.h new file mode 100644 index 0000000000..a72c8470f6 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h @@ -0,0 +1,1460 @@ +/** @file + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _LEGACY_BIOS_INTERFACE_ +#define _LEGACY_BIOS_INTERFACE_ + + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// BUGBUG: This entry maybe changed to PCD in future and wait for +// redesign of BDS library +// +#define MAX_BBS_ENTRIES 0x100 + +// +// Thunk Status Codes +// (These apply only to errors with the thunk and not to the code that w= as +// thunked to.) +// +#define THUNK_OK 0x00 +#define THUNK_ERR_A20_UNSUP 0x01 +#define THUNK_ERR_A20_FAILED 0x02 + +// +// Vector base definitions +// +// +// 8259 Hardware definitions +// +#define LEGACY_MODE_BASE_VECTOR_MASTER 0x08 +#define LEGACY_MODE_BASE_VECTOR_SLAVE 0x70 + +// +// The original PC used INT8-F for master PIC. Since these mapped over +// processor exceptions TIANO moved the master PIC to INT68-6F. +// +// The vector base for slave PIC is set as 0x70 for PC-AT compatibility. +// +#define PROTECTED_MODE_BASE_VECTOR_MASTER 0x68 +#define PROTECTED_MODE_BASE_VECTOR_SLAVE 0x70 + +// +// When we call CSM16 functions, some CSM16 use es:[offset + 0xabcd] to ge= t data passed from CSM32, +// offset + 0xabcd could overflow which exceeds 0xFFFF which is invalid in= real mode. +// So this will keep offset as small as possible to avoid offset overflow = in real mode. +// +#define NORMALIZE_EFI_SEGMENT(_Adr) (UINT16) (((UINTN) (_Adr)) >> 4) +#define NORMALIZE_EFI_OFFSET(_Adr) (UINT16) (((UINT16) ((UINTN) (_Ad= r))) & 0xf) + +// +// Trace defines +// +// +#define LEGACY_BDA_TRACE 0x000 +#define LEGACY_BIOS_TRACE 0x040 +#define LEGACY_BOOT_TRACE 0x080 +#define LEGACY_CMOS_TRACE 0x0C0 +#define LEGACY_IDE_TRACE 0x100 +#define LEGACY_MP_TRACE 0x140 +#define LEGACY_PCI_TRACE 0x180 +#define LEGACY_SIO_TRACE 0x1C0 + +#define LEGACY_PCI_TRACE_000 LEGACY_PCI_TRACE + 0x00 +#define LEGACY_PCI_TRACE_001 LEGACY_PCI_TRACE + 0x01 +#define LEGACY_PCI_TRACE_002 LEGACY_PCI_TRACE + 0x02 +#define LEGACY_PCI_TRACE_003 LEGACY_PCI_TRACE + 0x03 +#define LEGACY_PCI_TRACE_004 LEGACY_PCI_TRACE + 0x04 +#define LEGACY_PCI_TRACE_005 LEGACY_PCI_TRACE + 0x05 +#define LEGACY_PCI_TRACE_006 LEGACY_PCI_TRACE + 0x06 +#define LEGACY_PCI_TRACE_007 LEGACY_PCI_TRACE + 0x07 +#define LEGACY_PCI_TRACE_008 LEGACY_PCI_TRACE + 0x08 +#define LEGACY_PCI_TRACE_009 LEGACY_PCI_TRACE + 0x09 +#define LEGACY_PCI_TRACE_00A LEGACY_PCI_TRACE + 0x0A +#define LEGACY_PCI_TRACE_00B LEGACY_PCI_TRACE + 0x0B +#define LEGACY_PCI_TRACE_00C LEGACY_PCI_TRACE + 0x0C +#define LEGACY_PCI_TRACE_00D LEGACY_PCI_TRACE + 0x0D +#define LEGACY_PCI_TRACE_00E LEGACY_PCI_TRACE + 0x0E +#define LEGACY_PCI_TRACE_00F LEGACY_PCI_TRACE + 0x0F + +#define BDA_VIDEO_MODE 0x49 + +#define IDE_PI_REGISTER_PNE BIT0 +#define IDE_PI_REGISTER_SNE BIT2 + +typedef struct { + UINTN PciSegment; + UINTN PciBus; + UINTN PciDevice; + UINTN PciFunction; + UINT32 ShadowAddress; + UINT32 ShadowedSize; + UINT8 DiskStart; + UINT8 DiskEnd; +} ROM_INSTANCE_ENTRY; + +// +// Values for RealModeGdt +// +#if defined (MDE_CPU_IA32) + +#define NUM_REAL_GDT_ENTRIES 3 +#define CONVENTIONAL_MEMORY_TOP 0xA0000 // 640 KB +#define INITIAL_VALUE_BELOW_1K 0x0 + +#elif defined (MDE_CPU_X64) + +#define NUM_REAL_GDT_ENTRIES 8 +#define CONVENTIONAL_MEMORY_TOP 0xA0000 // 640 KB +#define INITIAL_VALUE_BELOW_1K 0x0 + +#endif + +#pragma pack(1) + +// +// Define what a processor GDT looks like +// +typedef struct { + UINT32 LimitLo : 16; + UINT32 BaseLo : 16; + UINT32 BaseMid : 8; + UINT32 Type : 4; + UINT32 System : 1; + UINT32 Dpl : 2; + UINT32 Present : 1; + UINT32 LimitHi : 4; + UINT32 Software : 1; + UINT32 Reserved : 1; + UINT32 DefaultSize : 1; + UINT32 Granularity : 1; + UINT32 BaseHi : 8; +} GDT32; + +typedef struct { + UINT16 LimitLow; + UINT16 BaseLow; + UINT8 BaseMid; + UINT8 Attribute; + UINT8 LimitHi; + UINT8 BaseHi; +} GDT64; + +// +// Define what a processor descriptor looks like +// This data structure must be kept in sync with ASM STRUCT in Thunk.inc +// +typedef struct { + UINT16 Limit; + UINT64 Base; +} DESCRIPTOR64; + +typedef struct { + UINT16 Limit; + UINT32 Base; +} DESCRIPTOR32; + +// +// Low stub lay out +// +#define LOW_STACK_SIZE (8 * 1024) // 8k? +#define EFI_MAX_E820_ENTRY 100 +#define FIRST_INSTANCE 1 +#define NOT_FIRST_INSTANCE 0 + +#if defined (MDE_CPU_IA32) +typedef struct { + // + // Space for the code + // The address of Code is also the beginning of the relocated Thunk code + // + CHAR8 Code[4096]; // ? + // + // The address of the Reverse Thunk code + // Note that this member CONTAINS the address of the relocated reverse = thunk + // code unlike the member variable 'Code', which IS the address of the = Thunk + // code. + // + UINT32 LowReverseThunkStart; + + // + // Data for the code (cs releative) + // + DESCRIPTOR32 GdtDesc; // Protected mode GDT + DESCRIPTOR32 IdtDesc; // Protected mode IDT + UINT32 FlatSs; + UINT32 FlatEsp; + + UINT32 LowCodeSelector; // Low code selector= in GDT + UINT32 LowDataSelector; // Low data selector= in GDT + UINT32 LowStack; + DESCRIPTOR32 RealModeIdtDesc; + + // + // real-mode GDT (temporary GDT with two real mode segment descriptors) + // + GDT32 RealModeGdt[NUM_REAL_GDT_ENTRIES]; + DESCRIPTOR32 RealModeGdtDesc; + + // + // Members specifically for the reverse thunk + // The RevReal* members are used to store the current state of real mode + // before performing the reverse thunk. The RevFlat* members must be s= et + // before calling the reverse thunk assembly code. + // + UINT16 RevRealDs; + UINT16 RevRealSs; + UINT32 RevRealEsp; + DESCRIPTOR32 RevRealIdtDesc; + UINT16 RevFlatDataSelector; // Flat data sel= ector in GDT + UINT32 RevFlatStack; + + // + // A low memory stack + // + CHAR8 Stack[LOW_STACK_SIZE]; + + // + // Stack for flat mode after reverse thunk + // @bug - This may no longer be necessary if the reverse thunk interf= ace + // is changed to have the flat stack in a different location. + // + CHAR8 RevThunkStack[LOW_STACK_SIZE]; + + // + // Legacy16 Init memory map info + // + EFI_TO_COMPATIBILITY16_INIT_TABLE EfiToLegacy16InitTable; + + EFI_TO_COMPATIBILITY16_BOOT_TABLE EfiToLegacy16BootTable; + + CHAR8 InterruptRedirectionCode[32]; + EFI_LEGACY_INSTALL_PCI_HANDLER PciHandler; + EFI_DISPATCH_OPROM_TABLE DispatchOpromTable; + BBS_TABLE BbsTable[MAX_BBS_ENTRIES]; +} LOW_MEMORY_THUNK; + +#elif defined (MDE_CPU_X64) + +typedef struct { + // + // Space for the code + // The address of Code is also the beginning of the relocated Thunk code + // + CHAR8 Code[4096]; // ? + + // + // Data for the code (cs releative) + // + DESCRIPTOR64 X64GdtDesc; // Protected mode= GDT + DESCRIPTOR64 X64IdtDesc; // Protected mode= IDT + UINTN X64Ss; + UINTN X64Esp; + + UINTN RealStack; + DESCRIPTOR32 RealModeIdtDesc; + DESCRIPTOR32 RealModeGdtDesc; + + // + // real-mode GDT (temporary GDT with two real mode segment descriptors) + // + GDT64 RealModeGdt[NUM_REAL_GDT_ENTRIES]; + UINT64 PageMapLevel4; + + // + // A low memory stack + // + CHAR8 Stack[LOW_STACK_SIZE]; + + // + // Legacy16 Init memory map info + // + EFI_TO_COMPATIBILITY16_INIT_TABLE EfiToLegacy16InitTable; + + EFI_TO_COMPATIBILITY16_BOOT_TABLE EfiToLegacy16BootTable; + + CHAR8 InterruptRedirectionCode[32]; + EFI_LEGACY_INSTALL_PCI_HANDLER PciHandler; + EFI_DISPATCH_OPROM_TABLE DispatchOpromTable; + BBS_TABLE BbsTable[MAX_BBS_ENTRIES]; +} LOW_MEMORY_THUNK; + +#endif + +// +// PnP Expansion Header +// +typedef struct { + UINT32 PnpSignature; + UINT8 Revision; + UINT8 Length; + UINT16 NextHeader; + UINT8 Reserved1; + UINT8 Checksum; + UINT32 DeviceId; + UINT16 MfgPointer; + UINT16 ProductNamePointer; + UINT8 Class; + UINT8 SubClass; + UINT8 Interface; + UINT8 DeviceIndicators; + UINT16 Bcv; + UINT16 DisconnectVector; + UINT16 Bev; + UINT16 Reserved2; + UINT16 StaticResourceVector; +} LEGACY_PNP_EXPANSION_HEADER; + +typedef struct { + UINT8 PciSegment; + UINT8 PciBus; + UINT8 PciDevice; + UINT8 PciFunction; + UINT16 Vid; + UINT16 Did; + UINT16 SysSid; + UINT16 SVid; + UINT8 Class; + UINT8 SubClass; + UINT8 Interface; + UINT8 Reserved; + UINTN RomStart; + UINTN ManufacturerString; + UINTN ProductNameString; +} LEGACY_ROM_AND_BBS_TABLE; + +// +// Structure how EFI has mapped a devices HDD drive numbers. +// Boot to EFI aware OS or shell requires this mapping when +// 16-bit CSM assigns drive numbers. +// This mapping is ignored booting to a legacy OS. +// +typedef struct { + UINT8 PciSegment; + UINT8 PciBus; + UINT8 PciDevice; + UINT8 PciFunction; + UINT8 StartDriveNumber; + UINT8 EndDriveNumber; +} LEGACY_EFI_HDD_TABLE; + +// +// This data is passed to Leacy16Boot +// +typedef enum { + EfiAcpiAddressRangeMemory =3D 1, + EfiAcpiAddressRangeReserved =3D 2, + EfiAcpiAddressRangeACPI =3D 3, + EfiAcpiAddressRangeNVS =3D 4, + EfiAddressRangePersistentMemory =3D 7 +} EFI_ACPI_MEMORY_TYPE; + +typedef struct { + UINT64 BaseAddr; + UINT64 Length; + EFI_ACPI_MEMORY_TYPE Type; +} EFI_E820_ENTRY64; + +typedef struct { + UINT32 BassAddrLow; + UINT32 BaseAddrHigh; + UINT32 LengthLow; + UINT32 LengthHigh; + EFI_ACPI_MEMORY_TYPE Type; +} EFI_E820_ENTRY; + +#pragma pack() + +extern BBS_TABLE *mBbsTable; + +extern EFI_GENERIC_MEMORY_TEST_PROTOCOL *gGenMemoryTest; + +extern BOOLEAN mEndOfDxe; + +#define PORT_70 0x70 +#define PORT_71 0x71 + +#define CMOS_0A 0x0a ///< Status register A +#define CMOS_0D 0x0d ///< Status register D +#define CMOS_0E 0x0e ///< Diagnostic Status +#define CMOS_0F 0x0f ///< Shutdown status +#define CMOS_10 0x10 ///< Floppy type +#define CMOS_12 0x12 ///< IDE type +#define CMOS_14 0x14 ///< Same as BDA 40:10 +#define CMOS_15 0x15 ///< Low byte of base memory in 1k increments +#define CMOS_16 0x16 ///< High byte of base memory in 1k increments +#define CMOS_17 0x17 ///< Low byte of 1MB+ memory in 1k increments - = max 15 MB +#define CMOS_18 0x18 ///< High byte of 1MB+ memory in 1k increments -= max 15 MB +#define CMOS_19 0x19 ///< C: extended drive type +#define CMOS_1A 0x1a ///< D: extended drive type +#define CMOS_2E 0x2e ///< Most significient byte of standard checksum +#define CMOS_2F 0x2f ///< Least significient byte of standard checksum +#define CMOS_30 0x30 ///< CMOS 0x17 +#define CMOS_31 0x31 ///< CMOS 0x18 +#define CMOS_32 0x32 ///< Century byte + +// +// 8254 Timer registers +// +#define TIMER0_COUNT_PORT 0x40 +#define TIMER1_COUNT_PORT 0x41 +#define TIMER2_COUNT_PORT 0x42 +#define TIMER_CONTROL_PORT 0x43 + +// +// Timer 0, Read/Write LSB then MSB, Square wave output, binary count use. +// +#define TIMER0_CONTROL_WORD 0x36 + +#define LEGACY_BIOS_INSTANCE_SIGNATURE SIGNATURE_32 ('L', 'B', 'I', 'T') +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + EFI_LEGACY_BIOS_PROTOCOL LegacyBios; + + EFI_HANDLE ImageHandle; + + // + // CPU Architectural Protocol + // + EFI_CPU_ARCH_PROTOCOL *Cpu; + + // + // Timer Architectural Protocol + // + EFI_TIMER_ARCH_PROTOCOL *Timer; + BOOLEAN TimerUses8254; + + // + // Protocol to Lock and Unlock 0xc0000 - 0xfffff + // + EFI_LEGACY_REGION2_PROTOCOL *LegacyRegion; + + EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; + + // + // Interrupt control for thunk and PCI IRQ + // + EFI_LEGACY_8259_PROTOCOL *Legacy8259; + + // + // PCI Interrupt PIRQ control + // + EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt; + + // + // Generic Memory Test + // + EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenericMemoryTest; + + // + // TRUE if PCI Interupt Line registers have been programmed. + // + BOOLEAN PciInterruptLine; + + // + // Code space below 1MB needed by thunker to transition to real mode. + // Contains stack and real mode code fragments + // + LOW_MEMORY_THUNK *IntThunk; + + // + // Starting shadow address of the Legacy BIOS + // + UINT32 BiosStart; + UINT32 LegacyBiosImageSize; + + // + // Start of variables used by CsmItp.mac ITP macro file and/os LegacyBios + // + UINT8 Dump[4]; + + // + // $EFI Legacy16 code entry info in memory < 1 MB; + // + EFI_COMPATIBILITY16_TABLE *Legacy16Table; + VOID *Legacy16InitPtr; + VOID *Legacy16BootPtr; + VOID *InternalIrqRoutingTable; + UINT32 NumberIrqRoutingEntries; + VOID *BbsTablePtr; + VOID *HddTablePtr; + UINT32 NumberHddControllers; + + // + // Cached copy of Legacy16 entry point + // + UINT16 Legacy16CallSegment; + UINT16 Legacy16CallOffset; + + // + // Returned from $EFI and passed in to OPROMS + // + UINT16 PnPInstallationCheckSegment; + UINT16 PnPInstallationCheckOffset; + + // + // E820 table + // + EFI_E820_ENTRY E820Table[EFI_MAX_E820_ENTRY]; + UINT32 NumberE820Entries; + + // + // True if legacy VGA INT 10h handler installed + // + BOOLEAN VgaInstalled; + + // + // Number of IDE drives + // + UINT8 IdeDriveCount; + + // + // Current Free Option ROM space. An option ROM must NOT go past + // BiosStart. + // + UINT32 OptionRom; + + // + // Save Legacy16 unexpected interrupt vector. Reprogram INT 68-6F from + // EFI values to legacy value just before boot. + // + UINT32 BiosUnexpectedInt; + UINT32 ThunkSavedInt[8]; + UINT16 ThunkSeg; + LEGACY_EFI_HDD_TABLE *LegacyEfiHddTable; + UINT16 LegacyEfiHddTableIndex; + UINT8 DiskEnd; + UINT8 Disk4075; + UINT16 TraceIndex; + UINT16 Trace[0x200]; + + // + // Indicate that whether GenericLegacyBoot is entered or not + // + BOOLEAN LegacyBootEntered; + + // + // CSM16 PCI Interface Version + // + UINT16 Csm16PciInterfaceVersion; + +} LEGACY_BIOS_INSTANCE; + + +#pragma pack(1) + +/* + 40:00-01 Com1 + 40:02-03 Com2 + 40:04-05 Com3 + 40:06-07 Com4 + 40:08-09 Lpt1 + 40:0A-0B Lpt2 + 40:0C-0D Lpt3 + 40:0E-0E Ebda segment + 40:10-11 MachineConfig + 40:12 Bda12 - skip + 40:13-14 MemSize below 1MB + 40:15-16 Bda15_16 - skip + 40:17 Keyboard Shift status + 40:18-19 Bda18_19 - skip + 40:1A-1B Key buffer head + 40:1C-1D Key buffer tail + 40:1E-3D Bda1E_3D- key buffer -skip + 40:3E-3F FloppyData 3E =3D Calibration status 3F =3D Motor status + 40:40 FloppyTimeout + 40:41-74 Bda41_74 - skip + 40:75 Number of HDD drives + 40:76-77 Bda76_77 - skip + 40:78-79 78 =3D Lpt1 timeout, 79 =3D Lpt2 timeout + 40:7A-7B 7A =3D Lpt3 timeout, 7B =3D Lpt4 timeout + 40:7C-7D 7C =3D Com1 timeout, 7D =3D Com2 timeout + 40:7E-7F 7E =3D Com3 timeout, 7F =3D Com4 timeout + 40:80-81 Pointer to start of key buffer + 40:82-83 Pointer to end of key buffer + 40:84-87 Bda84_87 - skip + 40:88 HDD Data Xmit rate + 40:89-8f skip + 40:90 Floppy data rate + 40:91-95 skip + 40:96 Keyboard Status + 40:97 LED Status + 40:98-101 skip +*/ +typedef struct { + UINT16 Com1; + UINT16 Com2; + UINT16 Com3; + UINT16 Com4; + UINT16 Lpt1; + UINT16 Lpt2; + UINT16 Lpt3; + UINT16 Ebda; + UINT16 MachineConfig; + UINT8 Bda12; + UINT16 MemSize; + UINT8 Bda15_16[0x02]; + UINT8 ShiftStatus; + UINT8 Bda18_19[0x02]; + UINT16 KeyHead; + UINT16 KeyTail; + UINT16 Bda1E_3D[0x10]; + UINT16 FloppyData; + UINT8 FloppyTimeout; + UINT8 Bda41_74[0x34]; + UINT8 NumberOfDrives; + UINT8 Bda76_77[0x02]; + UINT16 Lpt1_2Timeout; + UINT16 Lpt3_4Timeout; + UINT16 Com1_2Timeout; + UINT16 Com3_4Timeout; + UINT16 KeyStart; + UINT16 KeyEnd; + UINT8 Bda84_87[0x4]; + UINT8 DataXmit; + UINT8 Bda89_8F[0x07]; + UINT8 FloppyXRate; + UINT8 Bda91_95[0x05]; + UINT8 KeyboardStatus; + UINT8 LedStatus; +} BDA_STRUC; +#pragma pack() + +#define LEGACY_BIOS_INSTANCE_FROM_THIS(this) CR (this, LEGACY_BIOS_INSTAN= CE, LegacyBios, LEGACY_BIOS_INSTANCE_SIGNATURE) + +/** + Thunk to 16-bit real mode and execute a software interrupt with a vector + of BiosInt. Regs will contain the 16-bit register context on entry and + exit. + + @param This Protocol instance pointer. + @param BiosInt Processor interrupt vector to invoke + @param Regs Register contexted passed into (and returned) from thunk= to + 16-bit mode + + @retval FALSE Thunk completed, and there were no BIOS errors in the ta= rget code. + See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +BOOLEAN +EFIAPI +LegacyBiosInt86 ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 BiosInt, + IN EFI_IA32_REGISTER_SET *Regs + ); + + +/** + Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the + 16-bit register context on entry and exit. Arguments can be passed on + the Stack argument + + @param This Protocol instance pointer. + @param Segment Segemnt of 16-bit mode call + @param Offset Offset of 16-bit mdoe call + @param Regs Register contexted passed into (and retur= ned) from + thunk to 16-bit mode + @param Stack Caller allocated stack used to pass argum= ents + @param StackSize Size of Stack in bytes + + @retval FALSE Thunk completed, and there were no BIOS e= rrors in + the target code. See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +BOOLEAN +EFIAPI +LegacyBiosFarCall86 ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT16 Segment, + IN UINT16 Offset, + IN EFI_IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize + ); + + +/** + Test to see if a legacy PCI ROM exists for this device. Optionally return + the Legacy ROM instance for this PCI device. + + @param This Protocol instance pointer. + @param PciHandle The PCI PC-AT OPROM from this devices ROM= BAR will + be loaded + @param RomImage Return the legacy PCI ROM for this device + @param RomSize Size of ROM Image + @param Flags Indicates if ROM found and if PC-AT. + + @retval EFI_SUCCESS Legacy Option ROM available for this devi= ce + @retval EFI_UNSUPPORTED Legacy Option ROM not supported. + +**/ +EFI_STATUS +EFIAPI +LegacyBiosCheckPciRom ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, OPTIONAL + OUT UINTN *RomSize, OPTIONAL + OUT UINTN *Flags + ); + + +/** + Assign drive number to legacy HDD drives prior to booting an EFI + aware OS so the OS can access drives without an EFI driver. + Note: BBS compliant drives ARE NOT available until this call by + either shell or EFI. + + @param This Protocol instance pointer. + @param BbsCount Number of BBS_TABLE structures + @param BbsTable List BBS entries + + @retval EFI_SUCCESS Drive numbers assigned + +**/ +EFI_STATUS +EFIAPI +LegacyBiosPrepareToBootEfi ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *BbsCount, + OUT BBS_TABLE **BbsTable + ); + + +/** + To boot from an unconventional device like parties and/or execute + HDD diagnostics. + + @param This Protocol instance pointer. + @param Attributes How to interpret the other input paramete= rs + @param BbsEntry The 0-based index into the BbsTable for t= he parent + device. + @param BeerData Pointer to the 128 bytes of ram BEER data. + @param ServiceAreaData Pointer to the 64 bytes of raw Service Ar= ea data. + The caller must provide a pointer to the = specific + Service Area and not the start all Servic= e Areas. + EFI_INVALID_PARAMETER if error. Does NOT return if no error. + +**/ +EFI_STATUS +EFIAPI +LegacyBiosBootUnconventionalDevice ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UDC_ATTRIBUTES Attributes, + IN UINTN BbsEntry, + IN VOID *BeerData, + IN VOID *ServiceAreaData + ); + + +/** + Load a legacy PC-AT OPROM on the PciHandle device. Return information + about how many disks were added by the OPROM and the shadow address and + size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C: + + @param This Protocol instance pointer. + @param PciHandle The PCI PC-AT OPROM from this devices ROM= BAR will + be loaded. This value is NULL if RomImage= is + non-NULL. This is the normal case. + @param RomImage A PCI PC-AT ROM image. This argument is n= on-NULL + if there is no hardware associated with t= he ROM + and thus no PciHandle, otherwise is must = be NULL. + Example is PXE base code. + @param Flags Indicates if ROM found and if PC-AT. + @param DiskStart Disk number of first device hooked by the= ROM. If + DiskStart is the same as DiskEnd no diske= d were + hooked. + @param DiskEnd Disk number of the last device hooked by = the ROM. + @param RomShadowAddress Shadow address of PC-AT ROM + @param RomShadowedSize Size of RomShadowAddress in bytes + + @retval EFI_SUCCESS Legacy ROM loaded for this device + @retval EFI_INVALID_PARAMETER PciHandle not found + @retval EFI_UNSUPPORTED There is no PCI ROM in the ROM BAR or no = onboard + ROM + +**/ +EFI_STATUS +EFIAPI +LegacyBiosInstallPciRom ( + IN EFI_LEGACY_BIOS_PROTOCOL * This, + IN EFI_HANDLE PciHandle, + IN VOID **RomImage, + OUT UINTN *Flags, + OUT UINT8 *DiskStart, OPTIONAL + OUT UINT8 *DiskEnd, OPTIONAL + OUT VOID **RomShadowAddress, OPTIONAL + OUT UINT32 *RomShadowedSize OPTIONAL + ); + + +/** + Fill in the standard BDA for Keyboard LEDs + + @param This Protocol instance pointer. + @param Leds Current LED status + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +EFIAPI +LegacyBiosUpdateKeyboardLedStatus ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 Leds + ); + + +/** + Get all BBS info + + @param This Protocol instance pointer. + @param HddCount Number of HDD_INFO structures + @param HddInfo Onboard IDE controller information + @param BbsCount Number of BBS_TABLE structures + @param BbsTable List BBS entries + + @retval EFI_SUCCESS Tables returned + @retval EFI_NOT_FOUND resource not found + @retval EFI_DEVICE_ERROR can not get BBS table + +**/ +EFI_STATUS +EFIAPI +LegacyBiosGetBbsInfo ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *HddCount, + OUT HDD_INFO **HddInfo, + OUT UINT16 *BbsCount, + OUT BBS_TABLE **BbsTable + ); + + +/** + Shadow all legacy16 OPROMs that haven't been shadowed. + Warning: Use this with caution. This routine disconnects all EFI + drivers. If used externally then caller must re-connect EFI + drivers. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS OPROMs shadowed + +**/ +EFI_STATUS +EFIAPI +LegacyBiosShadowAllLegacyOproms ( + IN EFI_LEGACY_BIOS_PROTOCOL *This + ); + + +/** + Attempt to legacy boot the BootOption. If the EFI contexted has been + compromised this function will not return. + + @param This Protocol instance pointer. + @param BbsDevicePath EFI Device Path from BootXXXX variable. + @param LoadOptionsSize Size of LoadOption in size. + @param LoadOptions LoadOption from BootXXXX variable + + @retval EFI_SUCCESS Removable media not present + +**/ +EFI_STATUS +EFIAPI +LegacyBiosLegacyBoot ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN BBS_BBS_DEVICE_PATH *BbsDevicePath, + IN UINT32 LoadOptionsSize, + IN VOID *LoadOptions + ); + + +/** + Allocate memory < 1 MB and copy the thunker code into low memory. Se up + all the descriptors. + + @param Private Private context for Legacy BIOS + + @retval EFI_SUCCESS Should only pass. + +**/ +EFI_STATUS +LegacyBiosInitializeThunk ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Fill in the standard BDA and EBDA stuff before Legacy16 load + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosInitBda ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Collect IDE Inquiry data from the IDE disks + + @param Private Legacy BIOS Instance data + @param HddInfo Hdd Information + @param Flag Reconnect IdeController or not + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosBuildIdeData ( + IN LEGACY_BIOS_INSTANCE *Private, + IN HDD_INFO **HddInfo, + IN UINT16 Flag + ); + + +/** + Enable ide controller. This gets disabled when LegacyBoot.c is about + to run the Option ROMs. + + @param Private Legacy BIOS Instance data + + +**/ +VOID +EnableIdeController ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + If the IDE channel is in compatibility (legacy) mode, remove all + PCI I/O BAR addresses from the controller. + + @param IdeController The handle of target IDE controller + + +**/ +VOID +InitLegacyIdeController ( + IN EFI_HANDLE IdeController + ); + + +/** + Program the interrupt routing register in all the PCI devices. On a PC A= T system + this register contains the 8259 IRQ vector that matches it's PCI interru= pt. + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS Succeed. + @retval EFI_ALREADY_STARTED All PCI devices have been processed. + +**/ +EFI_STATUS +PciProgramAllInterruptLineRegisters ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Collect EFI Info about legacy devices. + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosBuildSioData ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Shadow all the PCI legacy ROMs. Use data from the Legacy BIOS Protocol + to chose the order. Skip any devices that have already have legacy + BIOS run. + + @param Private Protocol instance pointer. + + @retval EFI_SUCCESS Succeed. + @retval EFI_UNSUPPORTED Cannot get VGA device handle. + +**/ +EFI_STATUS +PciShadowRoms ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Fill in the standard BDA and EBDA stuff prior to legacy Boot + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosCompleteBdaBeforeBoot ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Fill in the standard CMOS stuff before Legacy16 load + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosInitCmos ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Fill in the standard CMOS stuff prior to legacy Boot + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosCompleteStandardCmosBeforeBoot ( + IN LEGACY_BIOS_INSTANCE *Private + ); + + +/** + Contains the code that is copied into low memory (below 640K). + This code reflects interrupts 0x68-0x6f to interrupts 0x08-0x0f. + This template must be copied into low memory, and the IDT entries + 0x68-0x6F must be point to the low memory copy of this code. Each + entry is 4 bytes long, so IDT entries 0x68-0x6F can be easily + computed. + +**/ +VOID +InterruptRedirectionTemplate ( + VOID + ); + + +/** + Build the E820 table. + + @param Private Legacy BIOS Instance data + @param Size Size of E820 Table + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosBuildE820 ( + IN LEGACY_BIOS_INSTANCE *Private, + OUT UINTN *Size + ); + +/** + This function is to put all AP in halt state. + + @param Private Legacy BIOS Instance data + +**/ +VOID +ShutdownAPs ( + IN LEGACY_BIOS_INSTANCE *Private + ); + +/** + Worker function for LegacyBiosGetFlatDescs, retrieving content of + specific registers. + + @param IntThunk Pointer to IntThunk of Legacy BIOS context. + +**/ +VOID +GetRegisters ( + LOW_MEMORY_THUNK *IntThunk + ); + +/** + Routine for calling real thunk code. + + @param RealCode The address of thunk code. + @param BiosInt The Bios interrupt vector number. + @param CallAddress The address of 16-bit mode call. + + @return Status returned by real thunk code + +**/ +UINTN +CallRealThunkCode ( + UINT8 *RealCode, + UINT8 BiosInt, + UINT32 CallAddress + ); + +/** + Routine for generating soft interrupt. + + @param Vector The interrupt vector number. + +**/ +VOID +GenerateSoftInit ( + UINT8 Vector + ); + +/** + Allocate memory for legacy usage. + + @param AllocateType The type of allocation to perform. + @param MemoryType The type of memory to allocate. + @param StartPageAddress Start address of range + @param Pages Number of pages to allocate + @param Result Result of allocation + + @retval EFI_SUCCESS Legacy16 code loaded + @retval Other No protocol installed, unload driver. + +**/ +EFI_STATUS +AllocateLegacyMemory ( + IN EFI_ALLOCATE_TYPE AllocateType, + IN EFI_MEMORY_TYPE MemoryType, + IN EFI_PHYSICAL_ADDRESS StartPageAddress, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Result + ); + +/** + Get a region from the LegacyBios for Tiano usage. Can only be invoked on= ce. + + @param This Protocol instance pointer. + @param LegacyMemorySize Size of required region + @param Region Region to use. 00 =3D Either 0xE0000 = or 0xF0000 + block Bit0 =3D 1 0xF0000 block Bit1 = =3D 1 0xE0000 + block + @param Alignment Address alignment. Bit mapped. First = non-zero + bit from right is alignment. + @param LegacyMemoryAddress Region Assigned + + @retval EFI_SUCCESS Region assigned + @retval EFI_ACCESS_DENIED Procedure previously invoked + @retval Other Region not assigned + +**/ +EFI_STATUS +EFIAPI +LegacyBiosGetLegacyRegion ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN UINTN Region, + IN UINTN Alignment, + OUT VOID **LegacyMemoryAddress + ); + +/** + Get a region from the LegacyBios for Tiano usage. Can only be invoked on= ce. + + @param This Protocol instance pointer. + @param LegacyMemorySize Size of data to copy + @param LegacyMemoryAddress Legacy Region destination address Not= e: must + be in region assigned by + LegacyBiosGetLegacyRegion + @param LegacyMemorySourceAddress Source of data + + @retval EFI_SUCCESS Region assigned + @retval EFI_ACCESS_DENIED Destination outside assigned region + +**/ +EFI_STATUS +EFIAPI +LegacyBiosCopyLegacyRegion ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN VOID *LegacyMemoryAddress, + IN VOID *LegacyMemorySourceAddress + ); + +/** + Find Legacy16 BIOS image in the FLASH device and shadow it into memory. = Find + the $EFI table in the shadow area. Thunk into the Legacy16 code after it= had + been shadowed. + + @param Private Legacy BIOS context data + + @retval EFI_SUCCESS Legacy16 code loaded + @retval Other No protocol installed, unload driver. + +**/ +EFI_STATUS +ShadowAndStartLegacy16 ( + IN LEGACY_BIOS_INSTANCE *Private + ); + +/** + Checks the state of the floppy and if media is inserted. + + This routine checks the state of the floppy and if media is inserted. + There are 3 cases: + No floppy present - Set BBS entry to ignore + Floppy present & no media - Set BBS entry to lowest priority. We cannot + set it to ignore since 16-bit CSM will + indicate no floppy and thus drive A: is + unusable. CSM-16 will not try floppy since + lowest priority and thus not incur boot + time penality. + Floppy present & media - Set BBS entry to some priority. + + @return State of floppy media + +**/ +UINT8 +HasMediaInFloppy ( + VOID + ); + +/** + Identify drive data must be updated to actual parameters before boot. + This requires updating the checksum, if it exists. + + @param IdentifyDriveData ATA Identify Data + @param Checksum checksum of the ATA Identify Data + + @retval EFI_SUCCESS checksum calculated + @retval EFI_SECURITY_VIOLATION IdentifyData invalid + +**/ +EFI_STATUS +CalculateIdentifyDriveChecksum ( + IN UINT8 *IdentifyDriveData, + OUT UINT8 *Checksum + ); + +/** + Identify drive data must be updated to actual parameters before boot. + + @param IdentifyDriveData ATA Identify Data + +**/ +VOID +UpdateIdentifyDriveData ( + IN UINT8 *IdentifyDriveData + ); + +/** + Complete build of BBS TABLE. + + @param Private Legacy BIOS Instance data + @param BbsTable BBS Table passed to 16-bit code + + @retval EFI_SUCCESS Removable media not present + +**/ +EFI_STATUS +LegacyBiosBuildBbs ( + IN LEGACY_BIOS_INSTANCE *Private, + IN BBS_TABLE *BbsTable + ); + +/** + Read CMOS register through index/data port. + + @param[in] Index The index of the CMOS register to read. + + @return The data value from the CMOS register specified by Index. + +**/ +UINT8 +LegacyReadStandardCmos ( + IN UINT8 Index + ); + +/** + Write CMOS register through index/data port. + + @param[in] Index The index of the CMOS register to write. + @param[in] Value The value of CMOS register to write. + + @return The value written to the CMOS register specified by Index. + +**/ +UINT8 +LegacyWriteStandardCmos ( + IN UINT8 Index, + IN UINT8 Value + ); + +/** + Calculate the new standard CMOS checksum and write it. + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS Calculate 16-bit checksum successfully + +**/ +EFI_STATUS +LegacyCalculateWriteStandardCmosChecksum ( + VOID + ); + +/** + Test to see if a legacy PCI ROM exists for this device. Optionally return + the Legacy ROM instance for this PCI device. + + @param[in] This Protocol instance pointer. + @param[in] PciHandle The PCI PC-AT OPROM from this devices= ROM BAR will be loaded + @param[out] RomImage Return the legacy PCI ROM for this de= vice + @param[out] RomSize Size of ROM Image + @param[out] RuntimeImageLength Runtime size of ROM Image + @param[out] Flags Indicates if ROM found and if PC-AT. + @param[out] OpromRevision Revision of the PCI Rom + @param[out] ConfigUtilityCodeHeaderPointer of Configuration Utility Code= Header + + @return EFI_SUCCESS Legacy Option ROM available for this devi= ce + @return EFI_ALREADY_STARTED This device is already managed by its Opr= om + @return EFI_UNSUPPORTED Legacy Option ROM not supported. + +**/ +EFI_STATUS +LegacyBiosCheckPciRomEx ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, OPTIONAL + OUT UINTN *RomSize, OPTIONAL + OUT UINTN *RuntimeImageLength, OPTIONAL + OUT UINTN *Flags, OPTIONAL + OUT UINT8 *OpromRevision, OPTIONAL + OUT VOID **ConfigUtilityCodeHeader OPTIONAL + ); + +/** + Relocate this image under 4G memory for IPF. + + @param ImageHandle Handle of driver image. + @param SystemTable Pointer to system table. + + @retval EFI_SUCCESS Image successfully relocated. + @retval EFI_ABORTED Failed to relocate image. + +**/ +EFI_STATUS +RelocateImageUnder4GIfNeeded ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the + 16-bit register context on entry and exit. Arguments can be passed on + the Stack argument + + @param This Protocol instance pointer. + @param Segment Segemnt of 16-bit mode call + @param Offset Offset of 16-bit mdoe call + @param Regs Register contexted passed into (and returned) from th= unk to + 16-bit mode + @param Stack Caller allocated stack used to pass arguments + @param StackSize Size of Stack in bytes + + @retval FALSE Thunk completed, and there were no BIOS errors in the= target code. + See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +BOOLEAN +EFIAPI +InternalLegacyBiosFarCall ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT16 Segment, + IN UINT16 Offset, + IN EFI_IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize + ); + +/** + Load a legacy PC-AT OpROM for VGA controller. + + @param Private Driver private data. + + @retval EFI_SUCCESS Legacy ROM successfully installed for thi= s device. + @retval EFI_DEVICE_ERROR No VGA device handle found, or native EFI= video + driver cannot be successfully disconnecte= d, or VGA + thunk driver cannot be successfully conne= cted. + +**/ +EFI_STATUS +LegacyBiosInstallVgaRom ( + IN LEGACY_BIOS_INSTANCE *Private + ); + +#endif diff --git a/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUi.h b/OvmfPkg= /Csm/LegacyBootMaintUiLib/LegacyBootMaintUi.h new file mode 100644 index 0000000000..0c491318c2 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUi.h @@ -0,0 +1,249 @@ +/** @file + Legacy boot maintainence Ui definition. + +Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#ifndef _EFI_LEGACY_BOOT_OPTION_H_ +#define _EFI_LEGACY_BOOT_OPTION_H_ + +#include + + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "LegacyBootMaintUiVfr.h" + +#define CONFIG_OPTION_OFFSET 0x1200 + +// +// VarOffset that will be used to create question +// all these values are computed from the structure +// defined below +// +#define VAR_OFFSET(Field) ((UINT16) ((UINTN) &(((LEGACY_BOOT_= NV_DATA *) 0)->Field))) + +// +// Question Id of Zero is invalid, so add an offset to it +// +#define QUESTION_ID(Field) (VAR_OFFSET (Field) + CONFIG_OPTION= _OFFSET) + + +#define LEGACY_FD_QUESTION_ID QUESTION_ID (LegacyFD) +#define LEGACY_HD_QUESTION_ID QUESTION_ID (LegacyHD) +#define LEGACY_CD_QUESTION_ID QUESTION_ID (LegacyCD) +#define LEGACY_NET_QUESTION_ID QUESTION_ID (LegacyNET) +#define LEGACY_BEV_QUESTION_ID QUESTION_ID (LegacyBEV) + + +// +// String Contant +// +#define STR_FLOPPY L"Floppy Drive #%02x" +#define STR_HARDDISK L"HardDisk Drive #%02x" +#define STR_CDROM L"ATAPI CDROM Drive #%02x" +#define STR_NET L"NET Drive #%02x" +#define STR_BEV L"BEV Drive #%02x" + +#define STR_FLOPPY_HELP L"Select Floppy Drive #%02x" +#define STR_HARDDISK_HELP L"Select HardDisk Drive #%02x" +#define STR_CDROM_HELP L"Select ATAPI CDROM Drive #%02x" +#define STR_NET_HELP L"NET Drive #%02x" +#define STR_BEV_HELP L"BEV Drive #%02x" + +#define STR_FLOPPY_TITLE L"Set Legacy Floppy Drive Order" +#define STR_HARDDISK_TITLE L"Set Legacy HardDisk Drive Order" +#define STR_CDROM_TITLE L"Set Legacy CDROM Drive Order" +#define STR_NET_TITLE L"Set Legacy NET Drive Order" +#define STR_BEV_TITLE L"Set Legacy BEV Drive Order" + +// +// These are the VFR compiler generated data representing our VFR data. +// +extern UINT8 LegacyBootMaintUiVfrBin[]; + +#pragma pack(1) + +/// +/// HII specific Vendor Device Path definition. +/// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + + + +// +// Variable created with this flag will be "Efi:...." +// +#define VAR_FLAG EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_A= CCESS | EFI_VARIABLE_NON_VOLATILE + + +#define LEGACY_BOOT_OPTION_CALLBACK_DATA_SIGNATURE SIGNATURE_32 ('L', 'G'= , 'C', 'B') + +typedef struct { + UINTN Signature; + + // + // HII relative handles + // + EFI_HII_HANDLE HiiHandle; + EFI_HANDLE DriverHandle; + + // + // Produced protocols + // + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; + + // + // Maintain the data. + // + LEGACY_BOOT_MAINTAIN_DATA *MaintainMapData; +} LEGACY_BOOT_OPTION_CALLBACK_DATA; + +// +// All of the signatures that will be used in list structure +// +#define LEGACY_MENU_OPTION_SIGNATURE SIGNATURE_32 ('m', 'e', 'n', 'u') +#define LEGACY_MENU_ENTRY_SIGNATURE SIGNATURE_32 ('e', 'n', 't', 'r') + +#define LEGACY_LEGACY_DEV_CONTEXT_SELECT 0x9 + +typedef struct { + UINTN Signature; + LIST_ENTRY Head; + UINTN MenuNumber; +} LEGACY_MENU_OPTION; + +typedef struct { + UINT16 BbsIndex; + CHAR16 *Description; +} LEGACY_DEVICE_CONTEXT; + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + UINTN OptionNumber; + UINT16 *DisplayString; + UINT16 *HelpString; + EFI_STRING_ID DisplayStringToken; + EFI_STRING_ID HelpStringToken; + VOID *VariableContext; +} LEGACY_MENU_ENTRY; + +typedef struct { + UINT16 BbsIndex; +} LEGACY_BOOT_OPTION_BBS_DATA; + +#pragma pack() + +/** + This call back function is registered with Boot Manager formset. + When user selects a boot option, this call back function will + be triggered. The boot option is saved for later processing. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original expo= rting driver + so that it can identify the type of data to expec= t. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original = exporting driver. + @param ActionRequest On return, points to the action requested by the = callback function. + + @retval EFI_SUCCESS The callback successfully handled the act= ion. + @retval EFI_INVALID_PARAMETER The setup browser call this function with= invalid parameters. + +**/ +EFI_STATUS +EFIAPI +LegacyBootOptionCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ); + +/** + This function allows a caller to extract the current configuration for o= ne + or more named elements from the target driver. + + + @param This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request - A null-terminated Unicode string in format. + @param Progress - On return, points to a character in the Request= string. + Points to the string's null terminator if request= was successful. + Points to the most recent '&' before the first fa= iling name/value + pair (or the beginning of the string if the failu= re is in the + first name/value pair) if the request was not suc= cessful. + @param Results - A null-terminated Unicode string in format which + has all values filled in for the names in the Req= uest string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested= values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unkn= own name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage i= n this driver. + +**/ +EFI_STATUS +EFIAPI +LegacyBootOptionExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ); + +/** + This function processes the results of changes in configuration. + + + @param This - Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration - A null-terminated Unicode string in format. + @param Progress - A pointer to a string filled in with the offset= of the most + recent '&' before the first failing name/value pa= ir (or the + beginning of the string if the failure is in the = first + name/value pair) or the terminating NULL if all w= as successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage i= n this driver. + +**/ +EFI_STATUS +EFIAPI +LegacyBootOptionRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ); + +#endif diff --git a/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.h b/Ovmf= Pkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.h new file mode 100644 index 0000000000..e16fc39415 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.h @@ -0,0 +1,79 @@ +/** @file + Legacy Boot Maintainence UI definition. + +Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#ifndef _EFI_LEGACY_BOOT_OPTION_VFR_H_ +#define _EFI_LEGACY_BOOT_OPTION_VFR_H_ + +#include + +#define MAX_MENU_NUMBER 100 + +#define LEGACY_BOOT_OPTION_FORMSET_GUID { 0x6bc75598, 0x89b4, 0x483d, { 0= x91, 0x60, 0x7f, 0x46, 0x9a, 0x96, 0x35, 0x31 } } + +#define VARSTORE_ID_LEGACY_BOOT 0x0001 + + +#define LEGACY_BOOT_FORM_ID 0x1000 +#define LEGACY_ORDER_CHANGE_FORM_ID 0x1001 + + +#define FORM_FLOPPY_BOOT_ID 0x2000 +#define FORM_HARDDISK_BOOT_ID 0x2001 +#define FORM_CDROM_BOOT_ID 0x2002 +#define FORM_NET_BOOT_ID 0x2003 +#define FORM_BEV_BOOT_ID 0x2004 + + + +#define FORM_BOOT_LEGACY_DEVICE_ID 0x9000 +#define FORM_BOOT_LEGACY_LABEL_END 0x9001 + + +#pragma pack(1) + +/// +/// This is the structure that will be used to store the +/// question's current value. Use it at initialize time to +/// set default value for each question. When using at run +/// time, this map is returned by the callback function, +/// so dynamically changing the question's value will be +/// possible through this mechanism +/// +typedef struct { + // + // Legacy Device Order Selection Storage + // + UINT16 LegacyFD[MAX_MENU_NUMBER]; + UINT16 LegacyHD[MAX_MENU_NUMBER]; + UINT16 LegacyCD[MAX_MENU_NUMBER]; + UINT16 LegacyNET[MAX_MENU_NUMBER]; + UINT16 LegacyBEV[MAX_MENU_NUMBER]; +} LEGACY_BOOT_NV_DATA; + +/// +/// This is the structure that will be used to store the +/// question's current value. Use it at initialize time to +/// set default value for each question. When using at run +/// time, this map is returned by the callback function, +/// so dynamically changing the question's value will be +/// possible through this mechanism +/// +typedef struct { + // + // Legacy Device Order Selection Storage + // + LEGACY_BOOT_NV_DATA InitialNvData; + LEGACY_BOOT_NV_DATA CurrentNvData; + LEGACY_BOOT_NV_DATA LastTimeNvData; + UINT8 DisableMap[32]; +} LEGACY_BOOT_MAINTAIN_DATA; + +#pragma pack() + +#endif diff --git a/OvmfPkg/Csm/LegacyBootManagerLib/InternalLegacyBm.h b/OvmfPkg/= Csm/LegacyBootManagerLib/InternalLegacyBm.h new file mode 100644 index 0000000000..292e2c1e7a --- /dev/null +++ b/OvmfPkg/Csm/LegacyBootManagerLib/InternalLegacyBm.h @@ -0,0 +1,60 @@ +/** @file + +Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _INTERNAL_LEGACY_BM_H_ +#define _INTERNAL_LEGACY_BM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma pack(1) +typedef struct { + UINT16 BbsIndex; +} LEGACY_BM_BOOT_OPTION_BBS_DATA; +#pragma pack() + +/** + Boot the legacy system with the boot option. + + @param BootOption The legacy boot option which have BBS device path + On return, BootOption->Status contains the boot statu= s. + EFI_UNSUPPORTED There is no legacybios protocol, d= o not support + legacy boot. + EFI_STATUS The status of LegacyBios->LegacyBo= ot (). +**/ +VOID +EFIAPI +LegacyBmBoot ( + IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption + ); + +/** + Refresh all legacy boot options. + +**/ +VOID +EFIAPI +LegacyBmRefreshAllBootOption ( + VOID + ); + +#endif // _INTERNAL_LEGACY_BM_H_ diff --git a/OvmfPkg/Csm/BiosThunk/VideoDxe/BiosVideo.c b/OvmfPkg/Csm/BiosT= hunk/VideoDxe/BiosVideo.c new file mode 100644 index 0000000000..0640656dba --- /dev/null +++ b/OvmfPkg/Csm/BiosThunk/VideoDxe/BiosVideo.c @@ -0,0 +1,3289 @@ +/** @file + ConsoleOut Routines that speak VGA. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BiosVideo.h" + +// +// EFI Driver Binding Protocol Instance +// +EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding =3D { + BiosVideoDriverBindingSupported, + BiosVideoDriverBindingStart, + BiosVideoDriverBindingStop, + 0x3, + NULL, + NULL +}; + +// +// Global lookup tables for VGA graphics modes +// +UINT8 mVgaLeftMaskTable[] =3D { 0xff, 0x7f, 0x3= f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; + +UINT8 mVgaRightMaskTable[] =3D { 0x80, 0xc0, 0xe= 0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; + +UINT8 mVgaBitMaskTable[] =3D { 0x80, 0x40, 0x2= 0, 0x10, 0x08, 0x04, 0x02, 0x01 }; + +// +// Save controller attributes during first start +// +UINT64 mOriginalPciAttributes; +BOOLEAN mPciAttributesSaved =3D FALSE; + +EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor[] =3D { + { 0x00, 0x00, 0x00, 0x00 }, + { 0x98, 0x00, 0x00, 0x00 }, + { 0x00, 0x98, 0x00, 0x00 }, + { 0x98, 0x98, 0x00, 0x00 }, + { 0x00, 0x00, 0x98, 0x00 }, + { 0x98, 0x00, 0x98, 0x00 }, + { 0x00, 0x98, 0x98, 0x00 }, + { 0x98, 0x98, 0x98, 0x00 }, + { 0x10, 0x10, 0x10, 0x00 }, + { 0xff, 0x10, 0x10, 0x00 }, + { 0x10, 0xff, 0x10, 0x00 }, + { 0xff, 0xff, 0x10, 0x00 }, + { 0x10, 0x10, 0xff, 0x00 }, + { 0xf0, 0x10, 0xff, 0x00 }, + { 0x10, 0xff, 0xff, 0x00 }, + { 0xff, 0xff, 0xff, 0x00 } +}; + +// +// Standard timing defined by VESA EDID +// +VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming[] =3D { + // + // Established Timing I + // + {800, 600, 60}, + {800, 600, 56}, + {640, 480, 75}, + {640, 480, 72}, + {640, 480, 67}, + {640, 480, 60}, + {720, 400, 88}, + {720, 400, 70}, + // + // Established Timing II + // + {1280, 1024, 75}, + {1024, 768, 75}, + {1024, 768, 70}, + {1024, 768, 60}, + {1024, 768, 87}, + {832, 624, 75}, + {800, 600, 75}, + {800, 600, 72}, + // + // Established Timing III + // + {1152, 870, 75} +}; + +/** + Supported. + + @param This Pointer to driver binding protocol + @param Controller Controller handle to connect + @param RemainingDevicePath A pointer to the remaining portion of a d= evice + path + + @retval EFI_STATUS EFI_SUCCESS:This controller can be manage= d by this + driver, Otherwise, this controller cannot= be + managed by this driver + +**/ +EFI_STATUS +EFIAPI +BiosVideoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + EFI_DEV_PATH *Node; + + // + // See if the Legacy BIOS Protocol is available + // + Status =3D gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID= **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && (Status !=3D EFI_ALREADY_STARTED)) { + return Status; + } + + if (Status =3D=3D EFI_ALREADY_STARTED) { + // + // If VgaMiniPort protocol is installed, EFI_ALREADY_STARTED indicates= failure, + // because VgaMiniPort protocol is installed on controller handle dire= ctly. + // + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiVgaMiniPortProtocolGuid, + NULL, + NULL, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + return EFI_ALREADY_STARTED; + } + } + // + // See if this is a PCI Graphics Controller by looking at the Command re= gister and + // Class Code Register + // + Status =3D PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + Status =3D EFI_UNSUPPORTED; + goto Done; + } + + Status =3D EFI_UNSUPPORTED; + if (Pci.Hdr.ClassCode[2] =3D=3D 0x03 || (Pci.Hdr.ClassCode[2] =3D=3D 0x0= 0 && Pci.Hdr.ClassCode[1] =3D=3D 0x01)) { + + Status =3D EFI_SUCCESS; + // + // If this is a graphics controller, + // go further check RemainingDevicePath validation + // + if (RemainingDevicePath !=3D NULL) { + Node =3D (EFI_DEV_PATH *) RemainingDevicePath; + // + // Check if RemainingDevicePath is the End of Device Path Node, + // if yes, return EFI_SUCCESS + // + if (!IsDevicePathEnd (Node)) { + // + // If RemainingDevicePath isn't the End of Device Path Node, + // check its validation + // + if (Node->DevPath.Type !=3D ACPI_DEVICE_PATH || + Node->DevPath.SubType !=3D ACPI_ADR_DP || + DevicePathNodeLength(&Node->DevPath) < sizeof(ACPI_ADR_DEVICE_= PATH)) { + Status =3D EFI_UNSUPPORTED; + } + } + } + } + +Done: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + + +/** + Install Graphics Output Protocol onto VGA device handles. + + @param This Pointer to driver binding protocol + @param Controller Controller handle to connect + @param RemainingDevicePath A pointer to the remaining portion of a d= evice + path + + @return EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +BiosVideoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN Flags; + UINT64 Supports; + + // + // Initialize local variables + // + PciIo =3D NULL; + ParentDevicePath =3D NULL; + + // + // + // See if the Legacy BIOS Protocol is available + // + Status =3D gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID= **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Prepare for status code + // + Status =3D gBS->HandleProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Open the IO Abstraction(s) needed + // + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && (Status !=3D EFI_ALREADY_STARTED)) { + return Status; + } + + // + // Save original PCI attributes + // + if (!mPciAttributesSaved) { + Status =3D PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationGet, + 0, + &mOriginalPciAttributes + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + mPciAttributesSaved =3D TRUE; + } + + // + // Get supported PCI attributes + // + Status =3D PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Supports &=3D (UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUT= E_VGA_IO_16); + if (Supports =3D=3D 0 || Supports =3D=3D (EFI_PCI_IO_ATTRIBUTE_VGA_IO | = EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) { + Status =3D EFI_UNSUPPORTED; + goto Done; + } + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE, + ParentDevicePath + ); + // + // Enable the device and make sure VGA cycles are being forwarded to thi= s VGA device + // + Status =3D PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | Sup= ports, + NULL + ); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT, + ParentDevicePath + ); + goto Done; + } + // + // Check to see if there is a legacy option ROM image associated with th= is PCI device + // + Status =3D LegacyBios->CheckPciRom ( + LegacyBios, + Controller, + NULL, + NULL, + &Flags + ); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Post the legacy option ROM if it is available. + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_P_PC_RESET, + ParentDevicePath + ); + Status =3D LegacyBios->InstallPciRom ( + LegacyBios, + Controller, + NULL, + &Flags, + NULL, + NULL, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, + ParentDevicePath + ); + goto Done; + } + + if (RemainingDevicePath !=3D NULL) { + if (IsDevicePathEnd (RemainingDevicePath) && + (FeaturePcdGet (PcdBiosVideoCheckVbeEnable) || FeaturePcdGet (PcdB= iosVideoCheckVgaEnable))) { + // + // If RemainingDevicePath is the End of Device Path Node, + // don't create any child device and return EFI_SUCESS + Status =3D EFI_SUCCESS; + goto Done; + } + } + + // + // Create child handle and install GraphicsOutputProtocol on it + // + Status =3D BiosVideoChildHandleInstall ( + This, + Controller, + PciIo, + LegacyBios, + ParentDevicePath, + RemainingDevicePath + ); + +Done: + if ((EFI_ERROR (Status)) && (Status !=3D EFI_ALREADY_STARTED)) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE, + ParentDevicePath + ); + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED, + ParentDevicePath + ); + if (!HasChildHandle (Controller)) { + if (mPciAttributesSaved) { + // + // Restore original PCI attributes + // + PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSet, + mOriginalPciAttributes, + NULL + ); + } + } + // + // Release PCI I/O Protocols on the controller handle. + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + + return Status; +} + + +/** + Stop. + + @param This Pointer to driver binding protocol + @param Controller Controller handle to connect + @param NumberOfChildren Number of children handle created by this= driver + @param ChildHandleBuffer Buffer containing child handle created + + @retval EFI_SUCCESS Driver disconnected successfully from con= troller + @retval EFI_UNSUPPORTED Cannot find BIOS_VIDEO_DEV structure + +**/ +EFI_STATUS +EFIAPI +BiosVideoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + BOOLEAN AllChildrenStopped; + UINTN Index; + EFI_PCI_IO_PROTOCOL *PciIo; + + AllChildrenStopped =3D TRUE; + + if (NumberOfChildren =3D=3D 0) { + // + // Close PCI I/O protocol on the controller handle + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; + } + + for (Index =3D 0; Index < NumberOfChildren; Index++) { + Status =3D BiosVideoChildHandleUninstall (This, Controller, ChildHandl= eBuffer[Index]); + + if (EFI_ERROR (Status)) { + AllChildrenStopped =3D FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + if (!HasChildHandle (Controller)) { + if (mPciAttributesSaved) { + Status =3D gBS->HandleProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + ASSERT_EFI_ERROR (Status); + + // + // Restore original PCI attributes + // + Status =3D PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSet, + mOriginalPciAttributes, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + } + + + return EFI_SUCCESS; +} + + +/** + Install child handles if the Handle supports MBR format. + + @param This Calling context. + @param ParentHandle Parent Handle + @param ParentPciIo Parent PciIo interface + @param ParentLegacyBios Parent LegacyBios interface + @param ParentDevicePath Parent Device Path + @param RemainingDevicePath Remaining Device Path + + @retval EFI_SUCCESS If a child handle was added + @retval other A child handle was not added + +**/ +EFI_STATUS +BiosVideoChildHandleInstall ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ParentHandle, + IN EFI_PCI_IO_PROTOCOL *ParentPciIo, + IN EFI_LEGACY_BIOS_PROTOCOL *ParentLegacyBios, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + BIOS_VIDEO_DEV *BiosVideoPrivate; + PCI_TYPE00 Pci; + ACPI_ADR_DEVICE_PATH AcpiDeviceNode; + BOOLEAN ProtocolInstalled; + + // + // Allocate the private device structure for video device + // + BiosVideoPrivate =3D (BIOS_VIDEO_DEV *) AllocateZeroPool ( + sizeof (BIOS_VIDEO_DEV) + ); + if (NULL =3D=3D BiosVideoPrivate) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // See if this is a VGA compatible controller or not + // + Status =3D ParentPciIo->Pci.Read ( + ParentPciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, + ParentDevicePath + ); + goto Done; + } + BiosVideoPrivate->VgaCompatible =3D FALSE; + if (Pci.Hdr.ClassCode[2] =3D=3D 0x00 && Pci.Hdr.ClassCode[1] =3D=3D 0x01= ) { + BiosVideoPrivate->VgaCompatible =3D TRUE; + } + + if (Pci.Hdr.ClassCode[2] =3D=3D 0x03 && Pci.Hdr.ClassCode[1] =3D=3D 0x00= && Pci.Hdr.ClassCode[0] =3D=3D 0x00) { + BiosVideoPrivate->VgaCompatible =3D TRUE; + } + + if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) { + // + // Create EXIT_BOOT_SERIVES Event + // + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + BiosVideoNotifyExitBootServices, + BiosVideoPrivate, + &gEfiEventExitBootServicesGuid, + &BiosVideoPrivate->ExitBootServicesEvent + ); + if (EFI_ERROR (Status)) { + goto Done; + } + } + + // + // Initialize the child private structure + // + BiosVideoPrivate->Signature =3D BIOS_VIDEO_DEV_SIGNATURE; + + // + // Fill in Graphics Output specific mode structures + // + BiosVideoPrivate->HardwareNeedsStarting =3D TRUE; + BiosVideoPrivate->ModeData =3D NULL; + BiosVideoPrivate->LineBuffer =3D NULL; + BiosVideoPrivate->VgaFrameBuffer =3D NULL; + BiosVideoPrivate->VbeFrameBuffer =3D NULL; + + // + // Fill in the Graphics Output Protocol + // + BiosVideoPrivate->GraphicsOutput.QueryMode =3D BiosVideoGraphicsOutputQu= eryMode; + BiosVideoPrivate->GraphicsOutput.SetMode =3D BiosVideoGraphicsOutputSe= tMode; + + + // + // Allocate buffer for Graphics Output Protocol mode information + // + BiosVideoPrivate->GraphicsOutput.Mode =3D (EFI_GRAPHICS_OUTPUT_PROTOCOL_= MODE *) AllocatePool ( + sizeof (EFI_GRAPHICS_OUTPUT_P= ROTOCOL_MODE) + ); + if (NULL =3D=3D BiosVideoPrivate->GraphicsOutput.Mode) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Done; + } + + BiosVideoPrivate->GraphicsOutput.Mode->Info =3D (EFI_GRAPHICS_OUTPUT_MOD= E_INFORMATION *) AllocatePool ( + sizeof (EFI_GRAPHICS_OUTPUT_M= ODE_INFORMATION) + ); + if (NULL =3D=3D BiosVideoPrivate->GraphicsOutput.Mode->Info) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Assume that Graphics Output Protocol will be produced until proven ot= herwise + // + BiosVideoPrivate->ProduceGraphicsOutput =3D TRUE; + + // + // Set Gop Device Path, here RemainingDevicePath will not be one End of = Device Path Node. + // + if ((RemainingDevicePath =3D=3D NULL) || (!IsDevicePathEnd (RemainingDev= icePath))) { + if (RemainingDevicePath =3D=3D NULL) { + ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH)); + AcpiDeviceNode.Header.Type =3D ACPI_DEVICE_PATH; + AcpiDeviceNode.Header.SubType =3D ACPI_ADR_DP; + AcpiDeviceNode.ADR =3D ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DIS= PLAY_TYPE_VGA, 0, 0); + SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DE= VICE_PATH)); + + BiosVideoPrivate->GopDevicePath =3D AppendDevicePathNode ( + ParentDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &Ac= piDeviceNode + ); + } else { + BiosVideoPrivate->GopDevicePath =3D AppendDevicePathNode (ParentDevi= cePath, RemainingDevicePath); + } + + // + // Creat child handle and device path protocol firstly + // + BiosVideoPrivate->Handle =3D NULL; + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &BiosVideoPrivate->Handle, + &gEfiDevicePathProtocolGuid, + BiosVideoPrivate->GopDevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + goto Done; + } + } + + // + // Fill in the VGA Mini Port Protocol fields + // + BiosVideoPrivate->VgaMiniPort.SetMode =3D BiosVideoVga= MiniPortSetMode; + BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset =3D 0xb8000; + BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset =3D 0x3d4; + BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset =3D 0x3d5; + BiosVideoPrivate->VgaMiniPort.VgaMemoryBar =3D EFI_PCI_IO_P= ASS_THROUGH_BAR; + BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar =3D EFI_PCI_IO_P= ASS_THROUGH_BAR; + BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar =3D EFI_PCI_IO_P= ASS_THROUGH_BAR; + + // + // Child handle need to consume the Legacy Bios protocol + // + BiosVideoPrivate->LegacyBios =3D ParentLegacyBios; + + // + // When check for VBE, PCI I/O protocol is needed, so use parent's proto= col interface temporally + // + BiosVideoPrivate->PciIo =3D ParentPciIo; + + // + // Check for VESA BIOS Extensions for modes that are compatible with Gra= phics Output + // + if (FeaturePcdGet (PcdBiosVideoCheckVbeEnable)) { + Status =3D BiosVideoCheckForVbe (BiosVideoPrivate); + DEBUG ((EFI_D_INFO, "BiosVideoCheckForVbe - %r\n", Status)); + } else { + Status =3D EFI_UNSUPPORTED; + } + if (EFI_ERROR (Status)) { + // + // The VESA BIOS Extensions are not compatible with Graphics Output, s= o check for support + // for the standard 640x480 16 color VGA mode + // + DEBUG ((EFI_D_INFO, "VgaCompatible - %x\n", BiosVideoPrivate->VgaCompa= tible)); + if (BiosVideoPrivate->VgaCompatible) { + if (FeaturePcdGet (PcdBiosVideoCheckVgaEnable)) { + Status =3D BiosVideoCheckForVga (BiosVideoPrivate); + DEBUG ((EFI_D_INFO, "BiosVideoCheckForVga - %r\n", Status)); + } else { + Status =3D EFI_UNSUPPORTED; + } + } + + if (EFI_ERROR (Status)) { + // + // Free GOP mode structure if it is not freed before + // VgaMiniPort does not need this structure any more + // + if (BiosVideoPrivate->GraphicsOutput.Mode !=3D NULL) { + if (BiosVideoPrivate->GraphicsOutput.Mode->Info !=3D NULL) { + FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); + BiosVideoPrivate->GraphicsOutput.Mode->Info =3D NULL; + } + FreePool (BiosVideoPrivate->GraphicsOutput.Mode); + BiosVideoPrivate->GraphicsOutput.Mode =3D NULL; + } + + // + // Neither VBE nor the standard 640x480 16 color VGA mode are suppor= ted, so do + // not produce the Graphics Output protocol. Instead, produce the V= GA MiniPort Protocol. + // + BiosVideoPrivate->ProduceGraphicsOutput =3D FALSE; + + // + // INT services are available, so on the 80x25 and 80x50 text mode a= re supported + // + BiosVideoPrivate->VgaMiniPort.MaxMode =3D 2; + } + } + + ProtocolInstalled =3D FALSE; + + if (BiosVideoPrivate->ProduceGraphicsOutput) { + // + // Creat child handle and install Graphics Output Protocol,EDID Discov= ered/Active Protocol + // + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &BiosVideoPrivate->Handle, + &gEfiGraphicsOutputProtocolGuid, + &BiosVideoPrivate->GraphicsOutput, + &gEfiEdidDiscoveredProtocolGuid, + &BiosVideoPrivate->EdidDiscovered, + &gEfiEdidActiveProtocolGuid, + &BiosVideoPrivate->EdidActive, + NULL + ); + + if (!EFI_ERROR (Status)) { + // + // Open the Parent Handle for the child + // + Status =3D gBS->OpenProtocol ( + ParentHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &BiosVideoPrivate->PciIo, + This->DriverBindingHandle, + BiosVideoPrivate->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + goto Done; + } + ProtocolInstalled =3D TRUE; + } + } + + if (!ProtocolInstalled) { + // + // Install VGA Mini Port Protocol + // + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &ParentHandle, + &gEfiVgaMiniPortProtocolGuid, + &BiosVideoPrivate->VgaMiniPort, + NULL + ); + } + +Done: + if (EFI_ERROR (Status)) { + if ((BiosVideoPrivate !=3D NULL) && (BiosVideoPrivate->ExitBootService= sEvent !=3D NULL)) { + gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent); + } + // + // Free private data structure + // + BiosVideoDeviceReleaseResource (BiosVideoPrivate); + } + + return Status; +} + + +/** + Deregister an video child handle and free resources. + + @param This Protocol instance pointer. + @param Controller Video controller handle + @param Handle Video child handle + + @return EFI_STATUS + +**/ +EFI_STATUS +BiosVideoChildHandleUninstall ( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + EFI_IA32_REGISTER_SET Regs; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_VGA_MINI_PORT_PROTOCOL *VgaMiniPort; + BIOS_VIDEO_DEV *BiosVideoPrivate; + EFI_PCI_IO_PROTOCOL *PciIo; + + BiosVideoPrivate =3D NULL; + GraphicsOutput =3D NULL; + PciIo =3D NULL; + Status =3D EFI_UNSUPPORTED; + + Status =3D gBS->OpenProtocol ( + Handle, + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &GraphicsOutput, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + BiosVideoPrivate =3D BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (Graph= icsOutput); + } + + if (EFI_ERROR (Status)) { + Status =3D gBS->OpenProtocol ( + Handle, + &gEfiVgaMiniPortProtocolGuid, + (VOID **) &VgaMiniPort, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + BiosVideoPrivate =3D BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMini= Port); + } + } + + if (BiosVideoPrivate =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + // + // Set the 80x25 Text VGA Mode + // + Regs.H.AH =3D 0x00; + Regs.H.AL =3D 0x03; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10,= &Regs); + + Regs.H.AH =3D 0x11; + Regs.H.AL =3D 0x14; + Regs.H.BL =3D 0; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10,= &Regs); + + // + // Close PCI I/O protocol that opened by child handle + // + Status =3D gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + // + // Uninstall protocols on child handle + // + if (BiosVideoPrivate->ProduceGraphicsOutput) { + Status =3D gBS->UninstallMultipleProtocolInterfaces ( + BiosVideoPrivate->Handle, + &gEfiDevicePathProtocolGuid, + BiosVideoPrivate->GopDevicePath, + &gEfiGraphicsOutputProtocolGuid, + &BiosVideoPrivate->GraphicsOutput, + &gEfiEdidDiscoveredProtocolGuid, + &BiosVideoPrivate->EdidDiscovered, + &gEfiEdidActiveProtocolGuid, + &BiosVideoPrivate->EdidActive, + NULL + ); + } + if (!BiosVideoPrivate->ProduceGraphicsOutput) { + Status =3D gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiVgaMiniPortProtocolGuid, + &BiosVideoPrivate->VgaMiniPort, + NULL + ); + } + + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + return Status; + } + + if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable)) { + // + // Close EXIT_BOOT_SERIVES Event + // + gBS->CloseEvent (BiosVideoPrivate->ExitBootServicesEvent); + } + + // + // Release all allocated resources + // + BiosVideoDeviceReleaseResource (BiosVideoPrivate); + + return EFI_SUCCESS; +} + + +/** + Release resource for biso video instance. + + @param BiosVideoPrivate Video child device private data structure + +**/ +VOID +BiosVideoDeviceReleaseResource ( + BIOS_VIDEO_DEV *BiosVideoPrivate + ) +{ + if (BiosVideoPrivate =3D=3D NULL) { + return ; + } + + // + // Release all the resourses occupied by the BIOS_VIDEO_DEV + // + + // + // Free VGA Frame Buffer + // + if (BiosVideoPrivate->VgaFrameBuffer !=3D NULL) { + FreePool (BiosVideoPrivate->VgaFrameBuffer); + } + // + // Free VBE Frame Buffer + // + if (BiosVideoPrivate->VbeFrameBuffer !=3D NULL) { + FreePool (BiosVideoPrivate->VbeFrameBuffer); + } + // + // Free line buffer + // + if (BiosVideoPrivate->LineBuffer !=3D NULL) { + FreePool (BiosVideoPrivate->LineBuffer); + } + // + // Free mode data + // + if (BiosVideoPrivate->ModeData !=3D NULL) { + FreePool (BiosVideoPrivate->ModeData); + } + // + // Free memory allocated below 1MB + // + if (BiosVideoPrivate->PagesBelow1MB !=3D 0) { + gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->Num= berOfPagesBelow1MB); + } + + if (BiosVideoPrivate->VbeSaveRestorePages !=3D 0) { + gBS->FreePages (BiosVideoPrivate->VbeSaveRestoreBuffer, BiosVideoPriva= te->VbeSaveRestorePages); + } + + // + // Free graphics output protocol occupied resource + // + if (BiosVideoPrivate->GraphicsOutput.Mode !=3D NULL) { + if (BiosVideoPrivate->GraphicsOutput.Mode->Info !=3D NULL) { + FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); + BiosVideoPrivate->GraphicsOutput.Mode->Info =3D NULL; + } + FreePool (BiosVideoPrivate->GraphicsOutput.Mode); + BiosVideoPrivate->GraphicsOutput.Mode =3D NULL; + } + // + // Free EDID discovered protocol occupied resource + // + if (BiosVideoPrivate->EdidDiscovered.Edid !=3D NULL) { + FreePool (BiosVideoPrivate->EdidDiscovered.Edid); + } + // + // Free EDID active protocol occupied resource + // + if (BiosVideoPrivate->EdidActive.Edid !=3D NULL) { + FreePool (BiosVideoPrivate->EdidActive.Edid); + } + + if (BiosVideoPrivate->GopDevicePath!=3D NULL) { + FreePool (BiosVideoPrivate->GopDevicePath); + } + + FreePool (BiosVideoPrivate); + + return ; +} + + +/** + Generate a search key for a specified timing data. + + @param EdidTiming Pointer to EDID timing + + @return The 32 bit unique key for search. + +**/ +UINT32 +CalculateEdidKey ( + VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming + ) +{ + UINT32 Key; + + // + // Be sure no conflicts for all standard timing defined by VESA. + // + Key =3D (EdidTiming->HorizontalResolution * 2) + EdidTiming->VerticalRes= olution; + return Key; +} + + +/** + Parse the Established Timing and Standard Timing in EDID data block. + + @param EdidBuffer Pointer to EDID data block + @param ValidEdidTiming Valid EDID timing information + + @retval TRUE The EDID data is valid. + @retval FALSE The EDID data is invalid. + +**/ +BOOLEAN +ParseEdidData ( + UINT8 *EdidBuffer, + VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming + ) +{ + UINT8 CheckSum; + UINT32 Index; + UINT32 ValidNumber; + UINT32 TimingBits; + UINT8 *BufferIndex; + UINT16 HorizontalResolution; + UINT16 VerticalResolution; + UINT8 AspectRatio; + UINT8 RefreshRate; + VESA_BIOS_EXTENSIONS_EDID_TIMING TempTiming; + VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *EdidDataBlock; + + EdidDataBlock =3D (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) EdidBuffer; + + // + // Check the checksum of EDID data + // + CheckSum =3D 0; + for (Index =3D 0; Index < VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; Index ++= ) { + CheckSum =3D (UINT8) (CheckSum + EdidBuffer[Index]); + } + if (CheckSum !=3D 0) { + return FALSE; + } + + ValidNumber =3D 0; + gBS->SetMem (ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TI= MING), 0); + + if ((EdidDataBlock->EstablishedTimings[0] !=3D 0) || + (EdidDataBlock->EstablishedTimings[1] !=3D 0) || + (EdidDataBlock->EstablishedTimings[2] !=3D 0) + ) { + // + // Established timing data + // + TimingBits =3D EdidDataBlock->EstablishedTimings[0] | + (EdidDataBlock->EstablishedTimings[1] << 8) | + ((EdidDataBlock->EstablishedTimings[2] & 0x80) << 9) ; + for (Index =3D 0; Index < VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING= _MAX_NUMBER; Index ++) { + if ((TimingBits & 0x1) !=3D 0) { + DEBUG ((EFI_D_INFO, "Established Timing: %d x %d\n", + mEstablishedEdidTiming[Index].HorizontalResolution, mEstablishedEd= idTiming[Index].VerticalResolution)); + ValidEdidTiming->Key[ValidNumber] =3D CalculateEdidKey (&mEstablis= hedEdidTiming[Index]); + ValidNumber ++; + } + TimingBits =3D TimingBits >> 1; + } + } + + // + // Parse the standard timing data + // + BufferIndex =3D &EdidDataBlock->StandardTimingIdentification[0]; + for (Index =3D 0; Index < 8; Index ++) { + // + // Check if this is a valid Standard Timing entry + // VESA documents unused fields should be set to 01h + // + if ((BufferIndex[0] !=3D 0x1) && (BufferIndex[1] !=3D 0x1)){ + // + // A valid Standard Timing + // + HorizontalResolution =3D (UINT16) (BufferIndex[0] * 8 + 248); + AspectRatio =3D (UINT8) (BufferIndex[1] >> 6); + switch (AspectRatio) { + case 0: + VerticalResolution =3D (UINT16) (HorizontalResolution / 16 * 10); + break; + case 1: + VerticalResolution =3D (UINT16) (HorizontalResolution / 4 * 3); + break; + case 2: + VerticalResolution =3D (UINT16) (HorizontalResolution / 5 * 4); + break; + case 3: + VerticalResolution =3D (UINT16) (HorizontalResolution / 16 * 9); + break; + default: + VerticalResolution =3D (UINT16) (HorizontalResolution / 4 * 3); + break; + } + RefreshRate =3D (UINT8) ((BufferIndex[1] & 0x1f) + 60); + DEBUG ((EFI_D_INFO, "Standard Timing: %d x %d\n", HorizontalResoluti= on, VerticalResolution)); + TempTiming.HorizontalResolution =3D HorizontalResolution; + TempTiming.VerticalResolution =3D VerticalResolution; + TempTiming.RefreshRate =3D RefreshRate; + ValidEdidTiming->Key[ValidNumber] =3D CalculateEdidKey (&TempTiming); + ValidNumber ++; + } + BufferIndex +=3D 2; + } + + // + // Parse the Detailed Timing data + // + BufferIndex =3D &EdidDataBlock->DetailedTimingDescriptions[0]; + for (Index =3D 0; Index < 4; Index ++, BufferIndex +=3D VESA_BIOS_EXTENS= IONS_DETAILED_TIMING_EACH_DESCRIPTOR_SIZE) { + if ((BufferIndex[0] =3D=3D 0x0) && (BufferIndex[1] =3D=3D 0x0)) { + // + // Check if this is a valid Detailed Timing Descriptor + // If first 2 bytes are zero, it is monitor descriptor other than de= tailed timing descriptor + // + continue; + } + // + // Calculate Horizontal and Vertical resolution + // + TempTiming.HorizontalResolution =3D ((UINT16)(BufferIndex[4] & 0xF0) <= < 4) | (BufferIndex[2]); + TempTiming.VerticalResolution =3D ((UINT16)(BufferIndex[7] & 0xF0) << = 4) | (BufferIndex[5]); + DEBUG ((EFI_D_INFO, "Detailed Timing %d: %d x %d\n", + Index, TempTiming.HorizontalResolution, TempTiming.VerticalRes= olution)); + ValidEdidTiming->Key[ValidNumber] =3D CalculateEdidKey (&TempTiming); + ValidNumber ++; + } + + ValidEdidTiming->ValidNumber =3D ValidNumber; + return TRUE; +} + + +/** + Search a specified Timing in all the valid EDID timings. + + @param ValidEdidTiming All valid EDID timing information. + @param EdidTiming The Timing to search for. + + @retval TRUE Found. + @retval FALSE Not found. + +**/ +BOOLEAN +SearchEdidTiming ( + VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming, + VESA_BIOS_EXTENSIONS_EDID_TIMING *EdidTiming + ) +{ + UINT32 Index; + UINT32 Key; + + Key =3D CalculateEdidKey (EdidTiming); + + for (Index =3D 0; Index < ValidEdidTiming->ValidNumber; Index ++) { + if (Key =3D=3D ValidEdidTiming->Key[Index]) { + return TRUE; + } + } + + return FALSE; +} + +/** + Check if all video child handles have been uninstalled. + + @param Controller Video controller handle + + @return TRUE Child handles exist. + @return FALSE All video child handles have been uninsta= lled. + +**/ +BOOLEAN +HasChildHandle ( + IN EFI_HANDLE Controller + ) +{ + UINTN Index; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + UINTN EntryCount; + BOOLEAN HasChild; + + EntryCount =3D 0; + HasChild =3D FALSE; + gBS->OpenProtocolInformation ( + Controller, + &gEfiPciIoProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + for (Index =3D 0; Index < EntryCount; Index++) { + if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CON= TROLLER) !=3D 0) { + HasChild =3D TRUE; + } + } + + return HasChild; +} + +/** + Check for VBE device. + + @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure + + @retval EFI_SUCCESS VBE device found + +**/ +EFI_STATUS +BiosVideoCheckForVbe ( + IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate + ) +{ + EFI_STATUS Status; + EFI_IA32_REGISTER_SET Regs; + UINT16 *ModeNumberPtr; + UINT16 VbeModeNumber; + BOOLEAN ModeFound; + BOOLEAN EdidFound; + BIOS_VIDEO_MODE_DATA *ModeBuffer; + BIOS_VIDEO_MODE_DATA *CurrentModeData; + UINTN PreferMode; + UINTN ModeNumber; + VESA_BIOS_EXTENSIONS_EDID_TIMING Timing; + VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming; + EFI_EDID_OVERRIDE_PROTOCOL *EdidOverride; + UINT32 EdidAttributes; + BOOLEAN EdidOverrideFound; + UINTN EdidOverrideDataSize; + UINT8 *EdidOverrideDataBlock; + UINTN EdidActiveDataSize; + UINT8 *EdidActiveDataBlock; + UINT32 HighestHorizontalResolution; + UINT32 HighestVerticalResolution; + UINTN HighestResolutionMode; + + EdidFound =3D TRUE; + EdidOverrideFound =3D FALSE; + EdidOverrideDataBlock =3D NULL; + EdidActiveDataSize =3D 0; + EdidActiveDataBlock =3D NULL; + HighestHorizontalResolution =3D 0; + HighestVerticalResolution =3D 0; + HighestResolutionMode =3D 0; + + // + // Allocate buffer under 1MB for VBE data structures + // + BiosVideoPrivate->NumberOfPagesBelow1MB =3D EFI_SIZE_TO_PAGES ( + sizeof (VESA_BIOS_EXTENSIONS= _INFORMATION_BLOCK) + + sizeof (VESA_BIOS_EXTENSIONS= _MODE_INFORMATION_BLOCK) + + sizeof (VESA_BIOS_EXTENSIONS= _EDID_DATA_BLOCK) + + sizeof (VESA_BIOS_EXTENSIONS= _CRTC_INFORMATION_BLOCK) + ); + + BiosVideoPrivate->PagesBelow1MB =3D 0x00100000 - 1; + + Status =3D gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + BiosVideoPrivate->NumberOfPagesBelow1MB, + &BiosVideoPrivate->PagesBelow1MB + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (&ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMIN= G)); + + // + // Fill in the VBE related data structures + // + BiosVideoPrivate->VbeInformationBlock =3D (VESA_BIOS_EXTENSIONS_INFORMAT= ION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB); + BiosVideoPrivate->VbeModeInformationBlock =3D (VESA_BIOS_EXTENSIONS_MODE= _INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1); + BiosVideoPrivate->VbeEdidDataBlock =3D (VESA_BIOS_EXTENSIONS_EDID_DATA_B= LOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1); + BiosVideoPrivate->VbeCrtcInformationBlock =3D (VESA_BIOS_EXTENSIONS_CRTC= _INFORMATION_BLOCK *) (BiosVideoPrivate->VbeEdidDataBlock + 1); + BiosVideoPrivate->VbeSaveRestorePages =3D 0; + BiosVideoPrivate->VbeSaveRestoreBuffer =3D 0; + + // + // Test to see if the Video Adapter is compliant with VBE 3.0 + // + gBS->SetMem (&Regs, sizeof (Regs), 0); + Regs.X.AX =3D VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION; + gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EX= TENSIONS_INFORMATION_BLOCK), 0); + BiosVideoPrivate->VbeInformationBlock->VESASignature =3D VESA_BIOS_EXTE= NSIONS_VBE2_SIGNATURE; + Regs.X.ES =3D EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock= ); + Regs.X.DI =3D EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock); + + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10,= &Regs); + + Status =3D EFI_DEVICE_ERROR; + + // + // See if the VESA call succeeded + // + if (Regs.X.AX !=3D VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + return Status; + } + // + // Check for 'VESA' signature + // + if (BiosVideoPrivate->VbeInformationBlock->VESASignature !=3D VESA_BIOS_= EXTENSIONS_VESA_SIGNATURE) { + return Status; + } + // + // Check to see if this is VBE 2.0 or higher + // + if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTEN= SIONS_VERSION_2_0) { + return Status; + } + + EdidFound =3D FALSE; + EdidAttributes =3D 0xff; + EdidOverrideDataSize =3D 0; + + // + // Find EDID Override protocol firstly, this protocol is installed by pl= atform if needed. + // + Status =3D gBS->LocateProtocol ( + &gEfiEdidOverrideProtocolGuid, + NULL, + (VOID **) &EdidOverride + ); + if (!EFI_ERROR (Status)) { + // + // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avo= id overflow + // + EdidOverrideDataBlock =3D AllocatePool (VESA_BIOS_EXTENSIONS_EDID_BLOC= K_SIZE * 2); + if (NULL =3D=3D EdidOverrideDataBlock) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Done; + } + + Status =3D EdidOverride->GetEdid ( + EdidOverride, + BiosVideoPrivate->Handle, + &EdidAttributes, + &EdidOverrideDataSize, + (UINT8 **) &EdidOverrideDataBlock + ); + if (!EFI_ERROR (Status) && + EdidAttributes =3D=3D 0 && + EdidOverrideDataSize !=3D 0) { + // + // Succeeded to get EDID Override Data + // + EdidOverrideFound =3D TRUE; + } + } + + if (!EdidOverrideFound || EdidAttributes =3D=3D EFI_EDID_OVERRIDE_DONT_O= VERRIDE) { + // + // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERR= IDE returned, + // read EDID information through INT10 call + // + + gBS->SetMem (&Regs, sizeof (Regs), 0); + Regs.X.AX =3D VESA_BIOS_EXTENSIONS_EDID; + Regs.X.BX =3D 1; + Regs.X.CX =3D 0; + Regs.X.DX =3D 0; + Regs.X.ES =3D EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock); + Regs.X.DI =3D EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock); + + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x1= 0, &Regs); + // + // See if the VESA call succeeded + // + if (Regs.X.AX =3D=3D VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + // + // Set EDID Discovered Data + // + BiosVideoPrivate->EdidDiscovered.SizeOfEdid =3D VESA_BIOS_EXTENSIONS= _EDID_BLOCK_SIZE; + BiosVideoPrivate->EdidDiscovered.Edid =3D (UINT8 *) AllocateCopyPoo= l ( + VESA_BIOS_EXTENS= IONS_EDID_BLOCK_SIZE, + BiosVideoPrivate= ->VbeEdidDataBlock + ); + + if (NULL =3D=3D BiosVideoPrivate->EdidDiscovered.Edid) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Done; + } + + EdidFound =3D TRUE; + } + } + + if (EdidFound) { + EdidActiveDataSize =3D VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; + EdidActiveDataBlock =3D BiosVideoPrivate->EdidDiscovered.Edid; + } else if (EdidOverrideFound) { + EdidActiveDataSize =3D EdidOverrideDataSize; + EdidActiveDataBlock =3D EdidOverrideDataBlock; + EdidFound =3D TRUE; + } + + if (EdidFound) { + // + // Parse EDID data structure to retrieve modes supported by monitor + // + if (ParseEdidData ((UINT8 *) EdidActiveDataBlock, &ValidEdidTiming)) { + // + // Copy EDID Override Data to EDID Active Data + // + BiosVideoPrivate->EdidActive.SizeOfEdid =3D (UINT32) EdidActiveDataS= ize; + BiosVideoPrivate->EdidActive.Edid =3D (UINT8 *) AllocateCopyPool ( + EdidActiveDataSize, + EdidActiveDataBlock + ); + if (NULL =3D=3D BiosVideoPrivate->EdidActive.Edid) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Done; + } + } + } else { + BiosVideoPrivate->EdidActive.SizeOfEdid =3D 0; + BiosVideoPrivate->EdidActive.Edid =3D NULL; + EdidFound =3D FALSE; + } + + // + // Walk through the mode list to see if there is at least one mode the i= s compatible with the EDID mode + // + ModeNumberPtr =3D (UINT16 *) + ( + (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xff= ff0000) >> 12) | + ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0= 000ffff) + ); + + PreferMode =3D 0; + ModeNumber =3D 0; + + // + // ModeNumberPtr may be not 16-byte aligned, so ReadUnaligned16 is used = to access the buffer pointed by ModeNumberPtr. + // + for (VbeModeNumber =3D ReadUnaligned16 (ModeNumberPtr); + VbeModeNumber !=3D VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; + VbeModeNumber =3D ReadUnaligned16 (++ModeNumberPtr)) { + // + // Make sure this is a mode number defined by the VESA VBE specificati= on. If it isn'tm then skip this mode number. + // + if ((VbeModeNumber & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) =3D=3D 0) { + continue; + } + // + // Get the information about the mode + // + gBS->SetMem (&Regs, sizeof (Regs), 0); + Regs.X.AX =3D VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION; + Regs.X.CX =3D VbeModeNumber; + gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_B= IOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0); + Regs.X.ES =3D EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformatio= nBlock); + Regs.X.DI =3D EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformation= Block); + + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x1= 0, &Regs); + + // + // See if the call succeeded. If it didn't, then try the next mode. + // + if (Regs.X.AX !=3D VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + continue; + } + // + // See if the mode supports color. If it doesn't then try the next mo= de. + // + if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_= BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) =3D=3D 0) { + continue; + } + // + // See if the mode supports graphics. If it doesn't then try the next= mode. + // + if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_= BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) =3D=3D 0) { + continue; + } + // + // See if the mode supports a linear frame buffer. If it doesn't then= try the next mode. + // + if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_= BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) =3D=3D 0) { + continue; + } + // + // See if the mode supports 32 bit color. If it doesn't then try the = next mode. + // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sur= e the + // number of bits per pixel is a multiple of 8 or more than 32 bits pe= r pixel + // + if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) { + continue; + } + + if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) { + continue; + } + + if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) !=3D= 0) { + continue; + } + // + // See if the physical base pointer for the linear mode is valid. If = it isn't then try the next mode. + // + if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr =3D=3D 0) { + continue; + } + + DEBUG ((EFI_D_INFO, "Video Controller Mode 0x%x: %d x %d\n", + VbeModeNumber, BiosVideoPrivate->VbeModeInformationBlock->XRes= olution, BiosVideoPrivate->VbeModeInformationBlock->YResolution)); + + if (EdidFound && (ValidEdidTiming.ValidNumber > 0)) { + // + // EDID exist, check whether this mode match with any mode in EDID + // + Timing.HorizontalResolution =3D BiosVideoPrivate->VbeModeInformation= Block->XResolution; + Timing.VerticalResolution =3D BiosVideoPrivate->VbeModeInformationBl= ock->YResolution; + if (!SearchEdidTiming (&ValidEdidTiming, &Timing)) { + // + // When EDID comes from INT10 call, EDID does not include 800x600,= 640x480 and 1024x768, + // but INT10 can support these modes, we add them into GOP mode. + // + if ((BiosVideoPrivate->EdidDiscovered.SizeOfEdid !=3D 0) && + !((Timing.HorizontalResolution) =3D=3D 1024 && (Timing.Vertica= lResolution =3D=3D 768)) && + !((Timing.HorizontalResolution) =3D=3D 800 && (Timing.Vertical= Resolution =3D=3D 600)) && + !((Timing.HorizontalResolution) =3D=3D 640 && (Timing.Vertical= Resolution =3D=3D 480))) { + continue; + } + } + } + + // + // Select a reasonable mode to be set for current display mode + // + ModeFound =3D FALSE; + + if (BiosVideoPrivate->VbeModeInformationBlock->XResolution =3D=3D 1024= && + BiosVideoPrivate->VbeModeInformationBlock->YResolution =3D=3D 768 + ) { + ModeFound =3D TRUE; + } + if (BiosVideoPrivate->VbeModeInformationBlock->XResolution =3D=3D 800 = && + BiosVideoPrivate->VbeModeInformationBlock->YResolution =3D=3D 600 + ) { + ModeFound =3D TRUE; + PreferMode =3D ModeNumber; + } + if (BiosVideoPrivate->VbeModeInformationBlock->XResolution =3D=3D 640 = && + BiosVideoPrivate->VbeModeInformationBlock->YResolution =3D=3D 480 + ) { + ModeFound =3D TRUE; + } + + if ((!EdidFound) && (!ModeFound)) { + // + // When no EDID exist, only select three possible resolutions, i.e. = 1024x768, 800x600, 640x480 + // + continue; + } + + // + // Record the highest resolution mode to set later + // + if ((BiosVideoPrivate->VbeModeInformationBlock->XResolution > HighestH= orizontalResolution) || + ((BiosVideoPrivate->VbeModeInformationBlock->XResolution =3D=3D Hi= ghestHorizontalResolution) && + (BiosVideoPrivate->VbeModeInformationBlock->YResolution > Highest= VerticalResolution))) { + HighestHorizontalResolution =3D BiosVideoPrivate->VbeModeInformation= Block->XResolution; + HighestVerticalResolution =3D BiosVideoPrivate->VbeModeInformationBl= ock->YResolution; + HighestResolutionMode =3D ModeNumber; + } + + // + // Add mode to the list of available modes + // + ModeNumber ++; + ModeBuffer =3D (BIOS_VIDEO_MODE_DATA *) AllocatePool ( + ModeNumber * sizeof (BIOS_VIDE= O_MODE_DATA) + ); + if (NULL =3D=3D ModeBuffer) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Done; + } + + if (ModeNumber > 1) { + CopyMem ( + ModeBuffer, + BiosVideoPrivate->ModeData, + (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA) + ); + } + + if (BiosVideoPrivate->ModeData !=3D NULL) { + FreePool (BiosVideoPrivate->ModeData); + } + + CurrentModeData =3D &ModeBuffer[ModeNumber - 1]; + CurrentModeData->VbeModeNumber =3D VbeModeNumber; + if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >=3D VESA_BIOS_= EXTENSIONS_VERSION_3_0) { + CurrentModeData->BytesPerScanLine =3D BiosVideoPrivate->VbeModeInfor= mationBlock->LinBytesPerScanLine; + CurrentModeData->Red.Position =3D BiosVideoPrivate->VbeModeInformati= onBlock->LinRedFieldPosition; + CurrentModeData->Red.Mask =3D (UINT8) ((1 << BiosVideoPrivate->VbeMo= deInformationBlock->LinRedMaskSize) - 1); + CurrentModeData->Blue.Position =3D BiosVideoPrivate->VbeModeInformat= ionBlock->LinBlueFieldPosition; + CurrentModeData->Blue.Mask =3D (UINT8) ((1 << BiosVideoPrivate->VbeM= odeInformationBlock->LinBlueMaskSize) - 1); + CurrentModeData->Green.Position =3D BiosVideoPrivate->VbeModeInforma= tionBlock->LinGreenFieldPosition; + CurrentModeData->Green.Mask =3D (UINT8) ((1 << BiosVideoPrivate->Vbe= ModeInformationBlock->LinGreenMaskSize) - 1); + CurrentModeData->Reserved.Position =3D BiosVideoPrivate->VbeModeInfo= rmationBlock->LinRsvdFieldPosition; + CurrentModeData->Reserved.Mask =3D (UINT8) ((1 << BiosVideoPrivate->= VbeModeInformationBlock->LinRsvdMaskSize) - 1); + } else { + CurrentModeData->BytesPerScanLine =3D BiosVideoPrivate->VbeModeInfor= mationBlock->BytesPerScanLine; + CurrentModeData->Red.Position =3D BiosVideoPrivate->VbeModeInformati= onBlock->RedFieldPosition; + CurrentModeData->Red.Mask =3D (UINT8) ((1 << BiosVideoPrivate->VbeMo= deInformationBlock->RedMaskSize) - 1); + CurrentModeData->Blue.Position =3D BiosVideoPrivate->VbeModeInformat= ionBlock->BlueFieldPosition; + CurrentModeData->Blue.Mask =3D (UINT8) ((1 << BiosVideoPrivate->VbeM= odeInformationBlock->BlueMaskSize) - 1); + CurrentModeData->Green.Position =3D BiosVideoPrivate->VbeModeInforma= tionBlock->GreenFieldPosition; + CurrentModeData->Green.Mask =3D (UINT8) ((1 << BiosVideoPrivate->Vbe= ModeInformationBlock->GreenMaskSize) - 1); + CurrentModeData->Reserved.Position =3D BiosVideoPrivate->VbeModeInfo= rmationBlock->RsvdFieldPosition; + CurrentModeData->Reserved.Mask =3D (UINT8) ((1 << BiosVideoPrivate->= VbeModeInformationBlock->RsvdMaskSize) - 1); + } + + CurrentModeData->PixelFormat =3D PixelBitMask; + if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel =3D=3D 32= ) && + (CurrentModeData->Red.Mask =3D=3D 0xff) && (CurrentModeData->Green= .Mask =3D=3D 0xff) && (CurrentModeData->Blue.Mask =3D=3D 0xff)) { + if ((CurrentModeData->Red.Position =3D=3D 0) && (CurrentModeData->Gr= een.Position =3D=3D 8) && (CurrentModeData->Blue.Position =3D=3D 16)) { + CurrentModeData->PixelFormat =3D PixelRedGreenBlueReserved8BitPerC= olor; + } else if ((CurrentModeData->Blue.Position =3D=3D 0) && (CurrentMode= Data->Green.Position =3D=3D 8) && (CurrentModeData->Red.Position =3D=3D 16)= ) { + CurrentModeData->PixelFormat =3D PixelBlueGreenRedReserved8BitPerC= olor; + } + } + + CurrentModeData->PixelBitMask.RedMask =3D ((UINT32) CurrentModeData->R= ed.Mask) << CurrentModeData->Red.Position; + CurrentModeData->PixelBitMask.GreenMask =3D ((UINT32) CurrentModeData-= >Green.Mask) << CurrentModeData->Green.Position; + CurrentModeData->PixelBitMask.BlueMask =3D ((UINT32) CurrentModeData->= Blue.Mask) << CurrentModeData->Blue.Position; + CurrentModeData->PixelBitMask.ReservedMask =3D ((UINT32) CurrentModeDa= ta->Reserved.Mask) << CurrentModeData->Reserved.Position; + + CurrentModeData->LinearFrameBuffer =3D (VOID *) (UINTN)BiosVideoPrivat= e->VbeModeInformationBlock->PhysBasePtr; + CurrentModeData->HorizontalResolution =3D BiosVideoPrivate->VbeModeInf= ormationBlock->XResolution; + CurrentModeData->VerticalResolution =3D BiosVideoPrivate->VbeModeInfor= mationBlock->YResolution; + + CurrentModeData->BitsPerPixel =3D BiosVideoPrivate->VbeModeInformatio= nBlock->BitsPerPixel; + CurrentModeData->FrameBufferSize =3D CurrentModeData->BytesPerScanLine= * CurrentModeData->VerticalResolution; + // + // Make sure the FrameBufferSize does not exceed the max available fra= me buffer size reported by VEB. + // + ASSERT (CurrentModeData->FrameBufferSize <=3D ((UINT32)BiosVideoPrivat= e->VbeInformationBlock->TotalMemory * 64 * 1024)); + + BiosVideoPrivate->ModeData =3D ModeBuffer; + } + // + // Check to see if we found any modes that are compatible with GRAPHICS = OUTPUT + // + if (ModeNumber =3D=3D 0) { + Status =3D EFI_DEVICE_ERROR; + goto Done; + } + + // + // Assign Gop's Blt function + // + BiosVideoPrivate->GraphicsOutput.Blt =3D BiosVideoGraphicsOutputVbeB= lt; + + BiosVideoPrivate->GraphicsOutput.Mode->MaxMode =3D (UINT32) ModeNumber; + // + // Current mode is unknow till now, set it to an invalid mode. + // + BiosVideoPrivate->GraphicsOutput.Mode->Mode =3D GRAPHICS_OUTPUT_INVALIDE= _MODE_NUMBER; + + // + // Find the best mode to initialize + // + if ((PcdGet32 (PcdVideoHorizontalResolution) =3D=3D 0x0) || (PcdGet32 (P= cdVideoVerticalResolution) =3D=3D 0x0)) { + DEBUG_CODE ( + BIOS_VIDEO_MODE_DATA *ModeData; + ModeData =3D &BiosVideoPrivate->ModeData[HighestResolutionMode]; + DEBUG ((EFI_D_INFO, "BiosVideo set highest resolution %d x %d\n", + ModeData->HorizontalResolution, ModeData->VerticalResolution= )); + ); + PreferMode =3D HighestResolutionMode; + } + Status =3D BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOu= tput, (UINT32) PreferMode); + if (EFI_ERROR (Status)) { + for (PreferMode =3D 0; PreferMode < ModeNumber; PreferMode ++) { + Status =3D BiosVideoGraphicsOutputSetMode ( + &BiosVideoPrivate->GraphicsOutput, + (UINT32) PreferMode + ); + if (!EFI_ERROR (Status)) { + break; + } + } + if (PreferMode =3D=3D ModeNumber) { + // + // None mode is set successfully. + // + goto Done; + } + } + +Done: + // + // If there was an error, then free the mode structure + // + if (EFI_ERROR (Status)) { + if (BiosVideoPrivate->ModeData !=3D NULL) { + FreePool (BiosVideoPrivate->ModeData); + BiosVideoPrivate->ModeData =3D NULL; + BiosVideoPrivate->MaxMode =3D 0; + } + if (EdidOverrideDataBlock !=3D NULL) { + FreePool (EdidOverrideDataBlock); + } + } + + return Status; +} + + +/** + Check for VGA device. + + @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure + + @retval EFI_SUCCESS Standard VGA device found + +**/ +EFI_STATUS +BiosVideoCheckForVga ( + IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate + ) +{ + EFI_STATUS Status; + BIOS_VIDEO_MODE_DATA *ModeBuffer; + + Status =3D EFI_UNSUPPORTED; + + // + // Assign Gop's Blt function + // + BiosVideoPrivate->GraphicsOutput.Blt =3D BiosVideoGraphicsOutputVgaB= lt; + + // + // Add mode to the list of available modes + // caller should guarantee that Mode has been allocated. + // + ASSERT (BiosVideoPrivate->GraphicsOutput.Mode !=3D NULL); + BiosVideoPrivate->GraphicsOutput.Mode->MaxMode =3D 1; + + ModeBuffer =3D (BIOS_VIDEO_MODE_DATA *) AllocatePool ( + sizeof (BIOS_VIDEO_MODE_DATA) + ); + if (NULL =3D=3D ModeBuffer) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Done; + } + + ModeBuffer->VbeModeNumber =3D 0x0012; + ModeBuffer->BytesPerScanLine =3D 640; + ModeBuffer->LinearFrameBuffer =3D (VOID *) (UINTN) (0xa0000); + ModeBuffer->HorizontalResolution =3D 640; + ModeBuffer->VerticalResolution =3D 480; + ModeBuffer->PixelFormat =3D PixelBltOnly; + ModeBuffer->BitsPerPixel =3D 8; + ModeBuffer->ColorDepth =3D 32; + ModeBuffer->RefreshRate =3D 60; + + BiosVideoPrivate->ModeData =3D ModeBuffer; + + // + // Test to see if the Video Adapter support the 640x480 16 color mode + // + BiosVideoPrivate->GraphicsOutput.Mode->Mode =3D GRAPHICS_OUTPUT_INVALIDE= _MODE_NUMBER; + Status =3D BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOu= tput, 0); + +Done: + // + // If there was an error, then free the mode structure + // + if (EFI_ERROR (Status)) { + if (BiosVideoPrivate->ModeData !=3D NULL) { + FreePool (BiosVideoPrivate->ModeData); + BiosVideoPrivate->ModeData =3D NULL; + } + if (BiosVideoPrivate->GraphicsOutput.Mode !=3D NULL) { + if (BiosVideoPrivate->GraphicsOutput.Mode->Info !=3D NULL) { + FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); + BiosVideoPrivate->GraphicsOutput.Mode->Info =3D NULL; + } + FreePool (BiosVideoPrivate->GraphicsOutput.Mode); + BiosVideoPrivate->GraphicsOutput.Mode =3D NULL; + } + } + return Status; +} + +// +// Graphics Output Protocol Member Functions for VESA BIOS Extensions +// + +/** + Graphics Output protocol interface to get video mode. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the I= nfo + buffer. + @param Info Caller allocated buffer that returns info= rmation + about ModeNumber. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retri= eve the + video mode. + @retval EFI_NOT_STARTED Video display is not initialized. Call Se= tMode () + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputQueryMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + BIOS_VIDEO_MODE_DATA *ModeData; + + BiosVideoPrivate =3D BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + + if (BiosVideoPrivate->HardwareNeedsStarting) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR, + BiosVideoPrivate->GopDevicePath + ); + return EFI_NOT_STARTED; + } + + if (This =3D=3D NULL || Info =3D=3D NULL || SizeOfInfo =3D=3D NULL || Mo= deNumber >=3D This->Mode->MaxMode) { + return EFI_INVALID_PARAMETER; + } + + *Info =3D (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool ( + sizeof (EFI_GRAPHICS_O= UTPUT_MODE_INFORMATION) + ); + if (NULL =3D=3D *Info) { + return EFI_OUT_OF_RESOURCES; + } + + *SizeOfInfo =3D sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + + ModeData =3D &BiosVideoPrivate->ModeData[ModeNumber]; + (*Info)->Version =3D 0; + (*Info)->HorizontalResolution =3D ModeData->HorizontalResolution; + (*Info)->VerticalResolution =3D ModeData->VerticalResolution; + (*Info)->PixelFormat =3D ModeData->PixelFormat; + CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof= (ModeData->PixelBitMask)); + + (*Info)->PixelsPerScanLine =3D (ModeData->BytesPerScanLine * 8) / ModeD= ata->BitsPerPixel; + + return EFI_SUCCESS; +} + +/** + Worker function to set video mode. + + @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV. + @param ModeData The mode data to be set. + @param DevicePath Pointer to Device Path Protocol. + + @retval EFI_SUCCESS Graphics mode was changed. + @retval EFI_DEVICE_ERROR The device had an error and could not com= plete the + request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this devic= e. + +**/ +EFI_STATUS +BiosVideoSetModeWorker ( + IN BIOS_VIDEO_DEV *BiosVideoPrivate, + IN BIOS_VIDEO_MODE_DATA *ModeData, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + EFI_IA32_REGISTER_SET Regs; + + if (BiosVideoPrivate->LineBuffer !=3D NULL) { + FreePool (BiosVideoPrivate->LineBuffer); + } + + if (BiosVideoPrivate->VgaFrameBuffer !=3D NULL) { + FreePool (BiosVideoPrivate->VgaFrameBuffer); + } + + if (BiosVideoPrivate->VbeFrameBuffer !=3D NULL) { + FreePool (BiosVideoPrivate->VbeFrameBuffer); + } + + BiosVideoPrivate->LineBuffer =3D (UINT8 *) AllocatePool ( + ModeData->BytesPerScanLine + ); + if (NULL =3D=3D BiosVideoPrivate->LineBuffer) { + return EFI_OUT_OF_RESOURCES; + } + // + // Clear all registers + // + ZeroMem (&Regs, sizeof (Regs)); + + if (ModeData->VbeModeNumber < 0x100) { + // + // Allocate a working buffer for BLT operations to the VGA frame buffer + // + BiosVideoPrivate->VgaFrameBuffer =3D (UINT8 *) AllocatePool (4 * 480 *= 80); + if (NULL =3D=3D BiosVideoPrivate->VgaFrameBuffer) { + return EFI_OUT_OF_RESOURCES; + } + // + // Set VGA Mode + // + Regs.X.AX =3D ModeData->VbeModeNumber; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x1= 0, &Regs); + + } else { + // + // Allocate a working buffer for BLT operations to the VBE frame buffer + // + BiosVideoPrivate->VbeFrameBuffer =3D + (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool ( + ModeData->BytesPerScanLine * Mod= eData->VerticalResolution + ); + if (NULL =3D=3D BiosVideoPrivate->VbeFrameBuffer) { + return EFI_OUT_OF_RESOURCES; + } + // + // Set VBE mode + // + Regs.X.AX =3D VESA_BIOS_EXTENSIONS_SET_MODE; + Regs.X.BX =3D (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS= _MODE_NUMBER_LINEAR_FRAME_BUFFER); + ZeroMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_= EXTENSIONS_CRTC_INFORMATION_BLOCK)); + Regs.X.ES =3D EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformatio= nBlock); + Regs.X.DI =3D EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformation= Block); + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x1= 0, &Regs); + + // + // Check to see if the call succeeded + // + if (Regs.X.AX !=3D VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_OUTPUT_ERROR, + DevicePath + ); + return EFI_DEVICE_ERROR; + } + // + // Initialize the state of the VbeFrameBuffer + // + Status =3D BiosVideoPrivate->PciIo->Mem.Read ( + BiosVideoPrivate->PciIo, + EfiPciIoWidthUint32, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) ModeData->Lin= earFrameBuffer, + (ModeData->BytesPerScanLine * = ModeData->VerticalResolution) >> 2, + BiosVideoPrivate->VbeFrameBuff= er + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} + +/** + Graphics Output protocol interface to set video mode. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to be set. + + @retval EFI_SUCCESS Graphics mode was changed. + @retval EFI_DEVICE_ERROR The device had an error and could not com= plete the + request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this devic= e. + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputSetMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This, + IN UINT32 ModeNumber + ) +{ + EFI_STATUS Status; + BIOS_VIDEO_DEV *BiosVideoPrivate; + BIOS_VIDEO_MODE_DATA *ModeData; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; + + if (This =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + BiosVideoPrivate =3D BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + + ModeData =3D &BiosVideoPrivate->ModeData[ModeNumber]; + + if (ModeNumber >=3D This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + if (ModeNumber =3D=3D This->Mode->Mode) { + // + // Clear screen to black + // + ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + BiosVideoGraphicsOutputVbeBlt ( + This, + &Background, + EfiBltVideoFill, + 0, + 0, + 0, + 0, + ModeData->HorizontalResolution, + ModeData->VerticalResolution, + 0 + ); + return EFI_SUCCESS; + } + + Status =3D BiosVideoSetModeWorker (BiosVideoPrivate, ModeData, BiosVideo= Private->GopDevicePath); + if (EFI_ERROR (Status)) { + return Status; + } + + This->Mode->Mode =3D ModeNumber; + This->Mode->Info->Version =3D 0; + This->Mode->Info->HorizontalResolution =3D ModeData->HorizontalResolutio= n; + This->Mode->Info->VerticalResolution =3D ModeData->VerticalResolution; + This->Mode->Info->PixelFormat =3D ModeData->PixelFormat; + CopyMem (&(This->Mode->Info->PixelInformation), &(ModeData->PixelBitMask= ), sizeof (ModeData->PixelBitMask)); + This->Mode->Info->PixelsPerScanLine =3D (ModeData->BytesPerScanLine * 8= ) / ModeData->BitsPerPixel; + This->Mode->SizeOfInfo =3D sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + This->Mode->FrameBufferSize =3D ModeData->FrameBufferSize; + This->Mode->FrameBufferBase =3D (EFI_PHYSICAL_ADDRESS) (UINTN) ModeData-= >LinearFrameBuffer; + + BiosVideoPrivate->HardwareNeedsStarting =3D FALSE; + + return EFI_SUCCESS; +} + +/** + Update physical frame buffer, copy 4 bytes block, then copy remaining by= tes. + + @param PciIo The pointer of EFI_PCI_IO_PROTOCOL + @param VbeBuffer The data to transfer to screen + @param MemAddress Physical frame buffer base address + @param DestinationX The X coordinate of the destination for BltO= peration + @param DestinationY The Y coordinate of the destination for BltO= peration + @param TotalBytes The total bytes of copy + @param VbePixelWidth Bytes per pixel + @param BytesPerScanLine Bytes per scan line + +**/ +VOID +CopyVideoBuffer ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 *VbeBuffer, + IN VOID *MemAddress, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN TotalBytes, + IN UINT32 VbePixelWidth, + IN UINTN BytesPerScanLine + ) +{ + UINTN FrameBufferAddr; + UINTN CopyBlockNum; + UINTN RemainingBytes; + UINTN UnalignedBytes; + EFI_STATUS Status; + + FrameBufferAddr =3D (UINTN) MemAddress + (DestinationY * BytesPerScanLin= e) + DestinationX * VbePixelWidth; + + // + // If TotalBytes is less than 4 bytes, only start byte copy. + // + if (TotalBytes < 4) { + Status =3D PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) FrameBufferAddr, + TotalBytes, + VbeBuffer + ); + ASSERT_EFI_ERROR (Status); + return; + } + + // + // If VbeBuffer is not 4-byte aligned, start byte copy. + // + UnalignedBytes =3D (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3; + + if (UnalignedBytes !=3D 0) { + Status =3D PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) FrameBufferAddr, + UnalignedBytes, + VbeBuffer + ); + ASSERT_EFI_ERROR (Status); + FrameBufferAddr +=3D UnalignedBytes; + VbeBuffer +=3D UnalignedBytes; + } + + // + // Calculate 4-byte block count and remaining bytes. + // + CopyBlockNum =3D (TotalBytes - UnalignedBytes) >> 2; + RemainingBytes =3D (TotalBytes - UnalignedBytes) & 3; + + // + // Copy 4-byte block and remaining bytes to physical frame buffer. + // + if (CopyBlockNum !=3D 0) { + Status =3D PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint32, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) FrameBufferAddr, + CopyBlockNum, + VbeBuffer + ); + ASSERT_EFI_ERROR (Status); + } + + if (RemainingBytes !=3D 0) { + FrameBufferAddr +=3D (CopyBlockNum << 2); + VbeBuffer +=3D (CopyBlockNum << 2); + Status =3D PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) FrameBufferAddr, + RemainingBytes, + VbeBuffer + ); + ASSERT_EFI_ERROR (Status); + } +} + +/** + Worker function to block transfer for VBE device. + + @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV + @param BltBuffer The data to transfer to screen + @param BltOperation The operation to perform + @param SourceX The X coordinate of the source for BltOpe= ration + @param SourceY The Y coordinate of the source for BltOpe= ration + @param DestinationX The X coordinate of the destination for + BltOperation + @param DestinationY The Y coordinate of the destination for + BltOperation + @param Width The width of a rectangle in the blt recta= ngle in + pixels + @param Height The height of a rectangle in the blt rect= angle in + pixels + @param Delta Not used for EfiBltVideoFill and + EfiBltVideoToVideo operation. If a Delta = of 0 is + used, the entire BltBuffer will be operat= ed on. If + a subrectangle of the BltBuffer is used, = then + Delta represents the number of bytes in a= row of + the BltBuffer. + @param Mode Mode data. + + @retval EFI_INVALID_PARAMETER Invalid parameter passed in + @retval EFI_SUCCESS Blt operation success + +**/ +EFI_STATUS +BiosVideoVbeBltWorker ( + IN BIOS_VIDEO_DEV *BiosVideoPrivate, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta, + IN BIOS_VIDEO_MODE_DATA *Mode + ) +{ + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_TPL OriginalTPL; + UINTN DstY; + UINTN SrcY; + UINTN DstX; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt; + VOID *MemAddress; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer; + UINTN BytesPerScanLine; + UINTN Index; + UINT8 *VbeBuffer; + UINT8 *VbeBuffer1; + UINT8 *BltUint8; + UINT32 VbePixelWidth; + UINT32 Pixel; + UINTN TotalBytes; + + PciIo =3D BiosVideoPrivate->PciIo; + + VbeFrameBuffer =3D BiosVideoPrivate->VbeFrameBuffer; + MemAddress =3D Mode->LinearFrameBuffer; + BytesPerScanLine =3D Mode->BytesPerScanLine; + VbePixelWidth =3D Mode->BitsPerPixel / 8; + BltUint8 =3D (UINT8 *) BltBuffer; + TotalBytes =3D Width * VbePixelWidth; + + if (((UINTN) BltOperation) >=3D EfiGraphicsOutputBltOperationMax) { + return EFI_INVALID_PARAMETER; + } + + if (Width =3D=3D 0 || Height =3D=3D 0) { + return EFI_INVALID_PARAMETER; + } + // + // We need to fill the Virtual Screen buffer with the blt data. + // The virtual screen is upside down, as the first row is the bootom row= of + // the image. + // + if (BltOperation =3D=3D EfiBltVideoToBltBuffer) { + // + // Video to BltBuffer: Source is Video, destination is BltBuffer + // + if (SourceY + Height > Mode->VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (SourceX + Width > Mode->HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + } else { + // + // BltBuffer to Video: Source is BltBuffer, destination is Video + // + if (DestinationY + Height > Mode->VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (DestinationX + Width > Mode->HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + } + // + // If Delta is zero, then the entire BltBuffer is being used, so Delta + // is the number of bytes in each row of BltBuffer. Since BltBuffer is = Width pixels size, + // the number of bytes in each row can be computed. + // + if (Delta =3D=3D 0) { + Delta =3D Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + } + // + // We have to raise to TPL Notify, so we make an atomic write the frame = buffer. + // We would not want a timer based event (Cursor, ...) to come in while = we are + // doing this operation. + // + OriginalTPL =3D gBS->RaiseTPL (TPL_NOTIFY); + + switch (BltOperation) { + case EfiBltVideoToBltBuffer: + for (SrcY =3D SourceY, DstY =3D DestinationY; DstY < (Height + Destina= tionY); SrcY++, DstY++) { + Blt =3D (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta += DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + // + // Shuffle the packed bytes in the hardware buffer to match EFI_GRAP= HICS_OUTPUT_BLT_PIXEL + // + VbeBuffer =3D ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine += SourceX * VbePixelWidth)); + for (DstX =3D DestinationX; DstX < (Width + DestinationX); DstX++) { + Pixel =3D VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] = << 16 | VbeBuffer[3] << 24; + Blt->Red =3D (UINT8) ((Pixel >> Mode->Red.Position) & Mode->R= ed.Mask); + Blt->Blue =3D (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->= Blue.Mask); + Blt->Green =3D (UINT8) ((Pixel >> Mode->Green.Position) & Mode-= >Green.Mask); + Blt->Reserved =3D 0; + Blt++; + VbeBuffer +=3D VbePixelWidth; + } + + } + break; + + case EfiBltVideoToVideo: + for (Index =3D 0; Index < Height; Index++) { + if (DestinationY <=3D SourceY) { + SrcY =3D SourceY + Index; + DstY =3D DestinationY + Index; + } else { + SrcY =3D SourceY + Height - Index - 1; + DstY =3D DestinationY + Height - Index - 1; + } + + VbeBuffer =3D ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine = + DestinationX * VbePixelWidth); + VbeBuffer1 =3D ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine = + SourceX * VbePixelWidth); + + gBS->CopyMem ( + VbeBuffer, + VbeBuffer1, + TotalBytes + ); + + // + // Update physical frame buffer. + // + CopyVideoBuffer ( + PciIo, + VbeBuffer, + MemAddress, + DestinationX, + DstY, + TotalBytes, + VbePixelWidth, + BytesPerScanLine + ); + } + break; + + case EfiBltVideoFill: + VbeBuffer =3D (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * Byte= sPerScanLine) + DestinationX * VbePixelWidth); + Blt =3D (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8; + // + // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match th= e hardware buffer + // + Pixel =3D ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) | + ( + (Blt->Green & Mode->Green.Mask) << + Mode->Green.Position + ) | + ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position); + + for (Index =3D 0; Index < Width; Index++) { + gBS->CopyMem ( + VbeBuffer, + &Pixel, + VbePixelWidth + ); + VbeBuffer +=3D VbePixelWidth; + } + + VbeBuffer =3D (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * Byte= sPerScanLine) + DestinationX * VbePixelWidth); + for (DstY =3D DestinationY + 1; DstY < (Height + DestinationY); DstY++= ) { + gBS->CopyMem ( + (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) += DestinationX * VbePixelWidth), + VbeBuffer, + TotalBytes + ); + } + + for (DstY =3D DestinationY; DstY < (Height + DestinationY); DstY++) { + // + // Update physical frame buffer. + // + CopyVideoBuffer ( + PciIo, + VbeBuffer, + MemAddress, + DestinationX, + DstY, + TotalBytes, + VbePixelWidth, + BytesPerScanLine + ); + } + break; + + case EfiBltBufferToVideo: + for (SrcY =3D SourceY, DstY =3D DestinationY; SrcY < (Height + SourceY= ); SrcY++, DstY++) { + Blt =3D (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * = Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + VbeBuffer =3D ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine += DestinationX * VbePixelWidth)); + for (DstX =3D DestinationX; DstX < (Width + DestinationX); DstX++) { + // + // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to matc= h the hardware buffer + // + Pixel =3D ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) | + ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) | + ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position); + gBS->CopyMem ( + VbeBuffer, + &Pixel, + VbePixelWidth + ); + Blt++; + VbeBuffer +=3D VbePixelWidth; + } + + VbeBuffer =3D ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine += DestinationX * VbePixelWidth)); + + // + // Update physical frame buffer. + // + CopyVideoBuffer ( + PciIo, + VbeBuffer, + MemAddress, + DestinationX, + DstY, + TotalBytes, + VbePixelWidth, + BytesPerScanLine + ); + } + break; + + default: ; + } + + gBS->RestoreTPL (OriginalTPL); + + return EFI_SUCCESS; +} + +/** + Graphics Output protocol instance to block transfer for VBE device. + + @param This Pointer to Graphics Output protocol insta= nce + @param BltBuffer The data to transfer to screen + @param BltOperation The operation to perform + @param SourceX The X coordinate of the source for BltOpe= ration + @param SourceY The Y coordinate of the source for BltOpe= ration + @param DestinationX The X coordinate of the destination for + BltOperation + @param DestinationY The Y coordinate of the destination for + BltOperation + @param Width The width of a rectangle in the blt recta= ngle in + pixels + @param Height The height of a rectangle in the blt rect= angle in + pixels + @param Delta Not used for EfiBltVideoFill and + EfiBltVideoToVideo operation. If a Delta = of 0 is + used, the entire BltBuffer will be operat= ed on. If + a subrectangle of the BltBuffer is used, = then + Delta represents the number of bytes in a= row of + the BltBuffer. + + @retval EFI_INVALID_PARAMETER Invalid parameter passed in + @retval EFI_SUCCESS Blt operation success + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputVbeBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta + ) +{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + BIOS_VIDEO_MODE_DATA *Mode; + + if (This =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + BiosVideoPrivate =3D BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + Mode =3D &BiosVideoPrivate->ModeData[This->Mode->Mode]; + + return BiosVideoVbeBltWorker ( + BiosVideoPrivate, + BltBuffer, + BltOperation, + SourceX, + SourceY, + DestinationX, + DestinationY, + Width, + Height, + Delta, + Mode + ); +} + +/** + Write graphics controller registers. + + @param PciIo Pointer to PciIo protocol instance of the + controller + @param Address Register address + @param Data Data to be written to register + + @return None + +**/ +VOID +WriteGraphicsController ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINTN Address, + IN UINTN Data + ) +{ + Address =3D Address | (Data << 8); + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER, + 1, + &Address + ); +} + + +/** + Read the four bit plane of VGA frame buffer. + + @param PciIo Pointer to PciIo protocol instance of the + controller + @param HardwareBuffer Hardware VGA frame buffer address + @param MemoryBuffer Memory buffer address + @param WidthInBytes Number of bytes in a line to read + @param Height Height of the area to read + + @return None + +**/ +VOID +VgaReadBitPlanes ( + EFI_PCI_IO_PROTOCOL *PciIo, + UINT8 *HardwareBuffer, + UINT8 *MemoryBuffer, + UINTN WidthInBytes, + UINTN Height + ) +{ + UINTN BitPlane; + UINTN Rows; + UINTN FrameBufferOffset; + UINT8 *Source; + UINT8 *Destination; + + // + // Program the Mode Register Write mode 0, Read mode 0 + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, + VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MO= DE_0 + ); + + for (BitPlane =3D 0, FrameBufferOffset =3D 0; + BitPlane < VGA_NUMBER_OF_BIT_PLANES; + BitPlane++, FrameBufferOffset +=3D VGA_BYTES_PER_BIT_PLANE + ) { + // + // Program the Read Map Select Register to select the correct bit plane + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER, + BitPlane + ); + + Source =3D HardwareBuffer; + Destination =3D MemoryBuffer + FrameBufferOffset; + + for (Rows =3D 0; Rows < Height; Rows++, Source +=3D VGA_BYTES_PER_SCAN= _LINE, Destination +=3D VGA_BYTES_PER_SCAN_LINE) { + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Source, + WidthInBytes, + (VOID *) Destination + ); + } + } +} + + +/** + Internal routine to convert VGA color to Grahpics Output color. + + @param MemoryBuffer Buffer containing VGA color + @param CoordinateX The X coordinate of pixel on screen + @param CoordinateY The Y coordinate of pixel on screen + @param BltBuffer Buffer to contain converted Grahpics Outp= ut color + + @return None + +**/ +VOID +VgaConvertToGraphicsOutputColor ( + UINT8 *MemoryBuffer, + UINTN CoordinateX, + UINTN CoordinateY, + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer + ) +{ + UINTN Mask; + UINTN Bit; + UINTN Color; + + MemoryBuffer +=3D ((CoordinateY << 6) + (CoordinateY << 4) + (Coordinate= X >> 3)); + Mask =3D mVgaBitMaskTable[CoordinateX & 0x07]; + for (Bit =3D 0x01, Color =3D 0; Bit < 0x10; Bit <<=3D 1, MemoryBuffer += =3D VGA_BYTES_PER_BIT_PLANE) { + if ((*MemoryBuffer & Mask) !=3D 0) { + Color |=3D Bit; + } + } + + *BltBuffer =3D mVgaColorToGraphicsOutputColor[Color]; +} + +/** + Internal routine to convert Grahpics Output color to VGA color. + + @param BltBuffer buffer containing Grahpics Output color + + @return Converted VGA color + +**/ +UINT8 +VgaConvertColor ( + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer + ) +{ + UINT8 Color; + + Color =3D (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0= x02) | ((BltBuffer->Red >> 5) & 0x04)); + if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) { + Color |=3D 0x08; + } + + return Color; +} + + +/** + Grahpics Output protocol instance to block transfer for VGA device. + + @param This Pointer to Grahpics Output protocol insta= nce + @param BltBuffer The data to transfer to screen + @param BltOperation The operation to perform + @param SourceX The X coordinate of the source for BltOpe= ration + @param SourceY The Y coordinate of the source for BltOpe= ration + @param DestinationX The X coordinate of the destination for + BltOperation + @param DestinationY The Y coordinate of the destination for + BltOperation + @param Width The width of a rectangle in the blt recta= ngle in + pixels + @param Height The height of a rectangle in the blt rect= angle in + pixels + @param Delta Not used for EfiBltVideoFill and + EfiBltVideoToVideo operation. If a Delta = of 0 is + used, the entire BltBuffer will be operat= ed on. If + a subrectangle of the BltBuffer is used, = then + Delta represents the number of bytes in a= row of + the BltBuffer. + + @retval EFI_INVALID_PARAMETER Invalid parameter passed in + @retval EFI_SUCCESS Blt operation success + +**/ +EFI_STATUS +EFIAPI +BiosVideoGraphicsOutputVgaBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta + ) +{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + EFI_TPL OriginalTPL; + UINT8 *MemAddress; + UINTN BytesPerScanLine; + UINTN Bit; + UINTN Index; + UINTN Index1; + UINTN StartAddress; + UINTN Bytes; + UINTN Offset; + UINT8 LeftMask; + UINT8 RightMask; + UINTN Address; + UINTN AddressFix; + UINT8 *Address1; + UINT8 *SourceAddress; + UINT8 *DestinationAddress; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Data; + UINT8 PixelColor; + UINT8 *VgaFrameBuffer; + UINTN SourceOffset; + UINTN SourceWidth; + UINTN Rows; + UINTN Columns; + UINTN CoordinateX; + UINTN CoordinateY; + UINTN CurrentMode; + + if (This =3D=3D NULL || ((UINTN) BltOperation) >=3D EfiGraphicsOutputBlt= OperationMax) { + return EFI_INVALID_PARAMETER; + } + + BiosVideoPrivate =3D BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + + CurrentMode =3D This->Mode->Mode; + PciIo =3D BiosVideoPrivate->PciIo; + MemAddress =3D BiosVideoPrivate->ModeData[CurrentMode].LinearFram= eBuffer; + BytesPerScanLine =3D BiosVideoPrivate->ModeData[CurrentMode].BytesPerSc= anLine >> 3; + VgaFrameBuffer =3D BiosVideoPrivate->VgaFrameBuffer; + + + if (Width =3D=3D 0 || Height =3D=3D 0) { + return EFI_INVALID_PARAMETER; + } + // + // We need to fill the Virtual Screen buffer with the blt data. + // The virtual screen is upside down, as the first row is the bootom row= of + // the image. + // + if (BltOperation =3D=3D EfiBltVideoToBltBuffer) { + // + // Video to BltBuffer: Source is Video, destination is BltBuffer + // + if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].Vertica= lResolution) { + return EFI_INVALID_PARAMETER; + } + + if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].Horizont= alResolution) { + return EFI_INVALID_PARAMETER; + } + } else { + // + // BltBuffer to Video: Source is BltBuffer, destination is Video + // + if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].Ve= rticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].Hor= izontalResolution) { + return EFI_INVALID_PARAMETER; + } + } + // + // If Delta is zero, then the entire BltBuffer is being used, so Delta + // is the number of bytes in each row of BltBuffer. Since BltBuffer is = Width pixels size, + // the number of bytes in each row can be computed. + // + if (Delta =3D=3D 0) { + Delta =3D Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + } + // + // We have to raise to TPL Notify, so we make an atomic write the frame = buffer. + // We would not want a timer based event (Cursor, ...) to come in while = we are + // doing this operation. + // + OriginalTPL =3D gBS->RaiseTPL (TPL_NOTIFY); + + // + // Compute some values we need for VGA + // + switch (BltOperation) { + case EfiBltVideoToBltBuffer: + + SourceOffset =3D (SourceY << 6) + (SourceY << 4) + (SourceX >> 3); + SourceWidth =3D ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1; + + // + // Read all the pixels in the 4 bit planes into a memory buffer that l= ooks like the VGA buffer + // + VgaReadBitPlanes ( + PciIo, + MemAddress + SourceOffset, + VgaFrameBuffer + SourceOffset, + SourceWidth, + Height + ); + + // + // Convert VGA Bit Planes to a Graphics Output 32-bit color value + // + BltBuffer +=3D (DestinationY * (Delta >> 2) + DestinationX); + for (Rows =3D 0, CoordinateY =3D SourceY; Rows < Height; Rows++, Coord= inateY++, BltBuffer +=3D (Delta >> 2)) { + for (Columns =3D 0, CoordinateX =3D SourceX; Columns < Width; Column= s++, CoordinateX++, BltBuffer++) { + VgaConvertToGraphicsOutputColor (VgaFrameBuffer, CoordinateX, Coor= dinateY, BltBuffer); + } + + BltBuffer -=3D Width; + } + + break; + + case EfiBltVideoToVideo: + // + // Check for an aligned Video to Video operation + // + if ((SourceX & 0x07) =3D=3D 0x00 && (DestinationX & 0x07) =3D=3D 0x00 = && (Width & 0x07) =3D=3D 0x00) { + // + // Program the Mode Register Write mode 1, Read mode 0 + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, + VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRIT= E_MODE_1 + ); + + SourceAddress =3D (UINT8 *) (MemAddress + (SourceY << 6) + (So= urceY << 4) + (SourceX >> 3)); + DestinationAddress =3D (UINT8 *) (MemAddress + (DestinationY << 6) = + (DestinationY << 4) + (DestinationX >> 3)); + Bytes =3D Width >> 3; + for (Index =3D 0, Offset =3D 0; Index < Height; Index++, Offset +=3D= BytesPerScanLine) { + PciIo->CopyMem ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) (DestinationAddress + Offset), + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) (SourceAddress + Offset), + Bytes + ); + } + } else { + SourceOffset =3D (SourceY << 6) + (SourceY << 4) + (SourceX >> 3); + SourceWidth =3D ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1; + + // + // Read all the pixels in the 4 bit planes into a memory buffer that= looks like the VGA buffer + // + VgaReadBitPlanes ( + PciIo, + MemAddress + SourceOffset, + VgaFrameBuffer + SourceOffset, + SourceWidth, + Height + ); + } + + break; + + case EfiBltVideoFill: + StartAddress =3D (UINTN) (MemAddress + (DestinationY << 6) + (Destina= tionY << 4) + (DestinationX >> 3)); + Bytes =3D ((DestinationX + Width - 1) >> 3) - (DestinationX >>= 3); + LeftMask =3D mVgaLeftMaskTable[DestinationX & 0x07]; + RightMask =3D mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07= ]; + if (Bytes =3D=3D 0) { + LeftMask =3D (UINT8) (LeftMask & RightMask); + RightMask =3D 0; + } + + if (LeftMask =3D=3D 0xff) { + StartAddress--; + Bytes++; + LeftMask =3D 0; + } + + if (RightMask =3D=3D 0xff) { + Bytes++; + RightMask =3D 0; + } + + PixelColor =3D VgaConvertColor (BltBuffer); + + // + // Program the Mode Register Write mode 2, Read mode 0 + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, + VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_= MODE_2 + ); + + // + // Program the Data Rotate/Function Select Register to replace + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER, + VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE + ); + + if (LeftMask !=3D 0) { + // + // Program the BitMask register with the Left column mask + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + LeftMask + ); + + for (Index =3D 0, Address =3D StartAddress; Index < Height; Index++,= Address +=3D BytesPerScanLine) { + // + // Read data from the bit planes into the latches + // + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address, + 1, + &Data + ); + // + // Write the lower 4 bits of PixelColor to the bit planes in the p= ixels enabled by BitMask + // + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address, + 1, + &PixelColor + ); + } + } + + if (Bytes > 1) { + // + // Program the BitMask register with the middle column mask of 0xff + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + 0xff + ); + + for (Index =3D 0, Address =3D StartAddress + 1; Index < Height; Inde= x++, Address +=3D BytesPerScanLine) { + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthFillUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address, + Bytes - 1, + &PixelColor + ); + } + } + + if (RightMask !=3D 0) { + // + // Program the BitMask register with the Right column mask + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + RightMask + ); + + for (Index =3D 0, Address =3D StartAddress + Bytes; Index < Height; = Index++, Address +=3D BytesPerScanLine) { + // + // Read data from the bit planes into the latches + // + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address, + 1, + &Data + ); + // + // Write the lower 4 bits of PixelColor to the bit planes in the p= ixels enabled by BitMask + // + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address, + 1, + &PixelColor + ); + } + } + break; + + case EfiBltBufferToVideo: + StartAddress =3D (UINTN) (MemAddress + (DestinationY << 6) + (Destina= tionY << 4) + (DestinationX >> 3)); + LeftMask =3D mVgaBitMaskTable[DestinationX & 0x07]; + + // + // Program the Mode Register Write mode 2, Read mode 0 + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_MODE_REGISTER, + VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_= MODE_2 + ); + + // + // Program the Data Rotate/Function Select Register to replace + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER, + VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE + ); + + for (Index =3D 0, Address =3D StartAddress; Index < Height; Index++, A= ddress +=3D BytesPerScanLine) { + for (Index1 =3D 0; Index1 < Width; Index1++) { + BiosVideoPrivate->LineBuffer[Index1] =3D VgaConvertColor (&BltBuff= er[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]); + } + AddressFix =3D Address; + + for (Bit =3D 0; Bit < 8; Bit++) { + // + // Program the BitMask register with the Left column mask + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + LeftMask + ); + + for (Index1 =3D Bit, Address1 =3D (UINT8 *) AddressFix; Index1 < W= idth; Index1 +=3D 8, Address1++) { + // + // Read data from the bit planes into the latches + // + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address1, + 1, + &Data + ); + + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address1, + 1, + &BiosVideoPrivate->LineBuffer[Index1] + ); + } + + LeftMask =3D (UINT8) (LeftMask >> 1); + if (LeftMask =3D=3D 0) { + LeftMask =3D 0x80; + AddressFix++; + } + } + } + + break; + + default: ; + } + + gBS->RestoreTPL (OriginalTPL); + + return EFI_SUCCESS; +} + +// +// VGA Mini Port Protocol Functions +// + +/** + VgaMiniPort protocol interface to set mode. + + @param This Pointer to VgaMiniPort protocol instance + @param ModeNumber The index of the mode + + @retval EFI_UNSUPPORTED The requested mode is not supported + @retval EFI_SUCCESS The requested mode is set successfully + +**/ +EFI_STATUS +EFIAPI +BiosVideoVgaMiniPortSetMode ( + IN EFI_VGA_MINI_PORT_PROTOCOL *This, + IN UINTN ModeNumber + ) +{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + EFI_IA32_REGISTER_SET Regs; + + if (This =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Make sure the ModeNumber is a valid value + // + if (ModeNumber >=3D This->MaxMode) { + return EFI_UNSUPPORTED; + } + // + // Get the device structure for this device + // + BiosVideoPrivate =3D BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This); + + switch (ModeNumber) { + case 0: + // + // Set the 80x25 Text VGA Mode + // + Regs.H.AH =3D 0x00; + Regs.H.AL =3D 0x83; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x1= 0, &Regs); + + Regs.H.AH =3D 0x11; + Regs.H.AL =3D 0x14; + Regs.H.BL =3D 0; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x1= 0, &Regs); + break; + + case 1: + // + // Set the 80x50 Text VGA Mode + // + Regs.H.AH =3D 0x00; + Regs.H.AL =3D 0x83; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x1= 0, &Regs); + Regs.H.AH =3D 0x11; + Regs.H.AL =3D 0x12; + Regs.H.BL =3D 0; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x1= 0, &Regs); + break; + + default: + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Event handler for Exit Boot Service. + + @param Event The event that be siganlled when exiting boot servic= e. + @param Context Pointer to instance of BIOS_VIDEO_DEV. + +**/ +VOID +EFIAPI +BiosVideoNotifyExitBootServices ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + BIOS_VIDEO_DEV *BiosVideoPrivate; + EFI_IA32_REGISTER_SET Regs; + + BiosVideoPrivate =3D (BIOS_VIDEO_DEV *)Context; + + // + // Set the 80x25 Text VGA Mode + // + Regs.H.AH =3D 0x00; + Regs.H.AL =3D 0x03; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10,= &Regs); + + Regs.H.AH =3D 0x00; + Regs.H.AL =3D 0x83; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10,= &Regs); + + Regs.H.AH =3D 0x11; + Regs.H.AL =3D 0x04; + Regs.H.BL =3D 0; + BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10,= &Regs); +} + +/** + The user Entry Point for module UefiBiosVideo. The user code starts with= this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI imag= e. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry po= int. + +**/ +EFI_STATUS +EFIAPI +BiosVideoEntryPoint( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status =3D EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gBiosVideoDriverBinding, + ImageHandle, + &gBiosVideoComponentName, + &gBiosVideoComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + // + // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver + // + return gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiLegacyBiosGuid, + NULL, + NULL + ); +} + diff --git a/OvmfPkg/Csm/BiosThunk/VideoDxe/ComponentName.c b/OvmfPkg/Csm/B= iosThunk/VideoDxe/ComponentName.c new file mode 100644 index 0000000000..dc914aa2f3 --- /dev/null +++ b/OvmfPkg/Csm/BiosThunk/VideoDxe/ComponentName.c @@ -0,0 +1,306 @@ +/** @file + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BiosVideo.h" + +// +// EFI Component Name Functions +// +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form o= f a + Unicode string. If the driver specified by This has a user readable name= in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver speci= fied + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code for= mat. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specifie= d by + This and the language specified by Languag= e was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +BiosVideoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + + +/** + Retrieves a Unicode string that is the user readable name of the control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does = not + support the language specified by Language, then EFI_UNSUPPORTED is retu= rned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to = be + returned. + + @param ChildHandle[in] The handle of the child controller to retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of= a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a va= lid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +BiosVideoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle O= PTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosVideoCompo= nentName =3D { + BiosVideoComponentNameGetDriverName, + BiosVideoComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoCompo= nentName2 =3D { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosVideoComponentNameGetDriverNam= e, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosVideoComponentNameGetContr= ollerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mBiosVideoDriverNam= eTable[] =3D { + { + "eng;en", + L"BIOS[INT10] Video Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form o= f a + Unicode string. If the driver specified by This has a user readable name= in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver speci= fied + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code for= mat. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specifie= d by + This and the language specified by Languag= e was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +BiosVideoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mBiosVideoDriverNameTable, + DriverName, + (BOOLEAN)(This =3D=3D &gBiosVideoComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does = not + support the language specified by Language, then EFI_UNSUPPORTED is retu= rned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to = be + returned. + + @param ChildHandle[in] The handle of the child controller to retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of= a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a va= lid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +BiosVideoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle O= PTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/OvmfPkg/Csm/LegacyBiosDxe/LegacyBbs.c b/OvmfPkg/Csm/LegacyBios= Dxe/LegacyBbs.c new file mode 100644 index 0000000000..6b1dd344f3 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/LegacyBbs.c @@ -0,0 +1,377 @@ +/** @file + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "LegacyBiosInterface.h" +#include + +// Give floppy 3 states +// FLOPPY_PRESENT_WITH_MEDIA =3D Floppy controller present and media is i= nserted +// FLOPPY_NOT_PRESENT =3D No floppy controller present +// FLOPPY_PRESENT_NO_MEDIA =3D Floppy controller present but no media inse= rted +// +#define FLOPPY_NOT_PRESENT 0 +#define FLOPPY_PRESENT_WITH_MEDIA 1 +#define FLOPPY_PRESENT_NO_MEDIA 2 + +BBS_TABLE *mBbsTable; +BOOLEAN mBbsTableDoneFlag =3D FALSE; +BOOLEAN IsHaveMediaInFloppy =3D TRUE; + +/** + Checks the state of the floppy and if media is inserted. + + This routine checks the state of the floppy and if media is inserted. + There are 3 cases: + No floppy present - Set BBS entry to ignore + Floppy present & no media - Set BBS entry to lowest priority. We cannot + set it to ignore since 16-bit CSM will + indicate no floppy and thus drive A: is + unusable. CSM-16 will not try floppy since + lowest priority and thus not incur boot + time penality. + Floppy present & media - Set BBS entry to some priority. + + @return State of floppy media + +**/ +UINT8 +HasMediaInFloppy ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + EFI_ISA_IO_PROTOCOL *IsaIo; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + + HandleBuffer =3D NULL; + HandleCount =3D 0; + + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiIsaIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + + // + // If don't find any ISA/IO protocol assume no floppy. Need for floppy + // free system + // + if (HandleCount =3D=3D 0) { + return FLOPPY_NOT_PRESENT; + } + + ASSERT (HandleBuffer !=3D NULL); + + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo + ); + if (EFI_ERROR (Status)) { + continue; + } + + if (IsaIo->ResourceList->Device.HID !=3D EISA_PNP_ID (0x604)) { + continue; + } + // + // Update blockio in case the floppy is inserted in during BdsTimeout + // + Status =3D gBS->DisconnectController (HandleBuffer[Index], NULL, NULL); + + if (EFI_ERROR (Status)) { + continue; + } + + Status =3D gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TR= UE); + + if (EFI_ERROR (Status)) { + continue; + } + + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo + ); + if (EFI_ERROR (Status)) { + continue; + } + + if (BlkIo->Media->MediaPresent) { + FreePool (HandleBuffer); + return FLOPPY_PRESENT_WITH_MEDIA; + } else { + FreePool (HandleBuffer); + return FLOPPY_PRESENT_NO_MEDIA; + } + } + + FreePool (HandleBuffer); + + return FLOPPY_NOT_PRESENT; + +} + + +/** + Complete build of BBS TABLE. + + @param Private Legacy BIOS Instance data + @param BbsTable BBS Table passed to 16-bit code + + @retval EFI_SUCCESS Removable media not present + +**/ +EFI_STATUS +LegacyBiosBuildBbs ( + IN LEGACY_BIOS_INSTANCE *Private, + IN BBS_TABLE *BbsTable + ) +{ + UINTN BbsIndex; + HDD_INFO *HddInfo; + UINTN HddIndex; + UINTN Index; + + // + // First entry is floppy. + // Next 2*MAX_IDE_CONTROLLER entries are for onboard IDE. + // Next n entries are filled in after each ROM is dispatched. + // Entry filled in if follow BBS spec. See LegacyPci.c + // Next entries are for non-BBS compliant ROMS. They are filled in by + // 16-bit code during Legacy16UpdateBbs invocation. Final BootPriority + // occurs after that invocation. + // + // Floppy + // Set default state. + // + IsHaveMediaInFloppy =3D HasMediaInFloppy (); + if (IsHaveMediaInFloppy =3D=3D FLOPPY_PRESENT_WITH_MEDIA) { + BbsTable[0].BootPriority =3D BBS_UNPRIORITIZED_ENTRY; + } else { + if (IsHaveMediaInFloppy =3D=3D FLOPPY_PRESENT_NO_MEDIA) { + BbsTable[0].BootPriority =3D BBS_LOWEST_PRIORITY; + } else { + BbsTable[0].BootPriority =3D BBS_IGNORE_ENTRY; + } + } + + BbsTable[0].Bus =3D 0xff; + BbsTable[0].Device =3D 0xff; + BbsTable[0].Function =3D 0xff; + BbsTable[0].DeviceType =3D BBS_FLOPPY; + BbsTable[0].Class =3D 01; + BbsTable[0].SubClass =3D 02; + BbsTable[0].StatusFlags.OldPosition =3D 0; + BbsTable[0].StatusFlags.Reserved1 =3D 0; + BbsTable[0].StatusFlags.Enabled =3D 0; + BbsTable[0].StatusFlags.Failed =3D 0; + BbsTable[0].StatusFlags.MediaPresent =3D 0; + BbsTable[0].StatusFlags.Reserved2 =3D 0; + + // + // Onboard HDD - Note Each HDD controller controls 2 drives + // Master & Slave + // + HddInfo =3D &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0]; + // + // Get IDE Drive Info + // + LegacyBiosBuildIdeData (Private, &HddInfo, 0); + + for (HddIndex =3D 0; HddIndex < MAX_IDE_CONTROLLER; HddIndex++) { + + BbsIndex =3D HddIndex * 2 + 1; + for (Index =3D 0; Index < 2; ++Index) { + + BbsTable[BbsIndex + Index].Bus =3D HddInfo[HddI= ndex].Bus; + BbsTable[BbsIndex + Index].Device =3D HddInfo[HddI= ndex].Device; + BbsTable[BbsIndex + Index].Function =3D HddInfo[HddI= ndex].Function; + BbsTable[BbsIndex + Index].Class =3D 01; + BbsTable[BbsIndex + Index].SubClass =3D 01; + BbsTable[BbsIndex + Index].StatusFlags.OldPosition =3D 0; + BbsTable[BbsIndex + Index].StatusFlags.Reserved1 =3D 0; + BbsTable[BbsIndex + Index].StatusFlags.Enabled =3D 0; + BbsTable[BbsIndex + Index].StatusFlags.Failed =3D 0; + BbsTable[BbsIndex + Index].StatusFlags.MediaPresent =3D 0; + BbsTable[BbsIndex + Index].StatusFlags.Reserved2 =3D 0; + + // + // If no controller found or no device found set to ignore + // else set to unprioritized and set device type + // + if (HddInfo[HddIndex].CommandBaseAddress =3D=3D 0) { + BbsTable[BbsIndex + Index].BootPriority =3D BBS_IGNORE_ENTRY; + } else { + if (Index =3D=3D 0) { + if ((HddInfo[HddIndex].Status & (HDD_MASTER_IDE | HDD_MASTER_ATA= PI_CDROM | HDD_MASTER_ATAPI_ZIPDISK)) !=3D 0) { + BbsTable[BbsIndex + Index].BootPriority =3D BBS_UNPRIORITIZED_= ENTRY; + if ((HddInfo[HddIndex].Status & HDD_MASTER_IDE) !=3D 0) { + BbsTable[BbsIndex + Index].DeviceType =3D BBS_HARDDISK; + } else if ((HddInfo[HddIndex].Status & HDD_MASTER_ATAPI_CDROM)= !=3D 0) { + BbsTable[BbsIndex + Index].DeviceType =3D BBS_CDROM; + } else { + // + // for ZIPDISK + // + BbsTable[BbsIndex + Index].DeviceType =3D BBS_HARDDISK; + } + } else { + BbsTable[BbsIndex + Index].BootPriority =3D BBS_IGNORE_ENTRY; + } + } else { + if ((HddInfo[HddIndex].Status & (HDD_SLAVE_IDE | HDD_SLAVE_ATAPI= _CDROM | HDD_SLAVE_ATAPI_ZIPDISK)) !=3D 0) { + BbsTable[BbsIndex + Index].BootPriority =3D BBS_UNPRIORITIZED_= ENTRY; + if ((HddInfo[HddIndex].Status & HDD_SLAVE_IDE) !=3D 0) { + BbsTable[BbsIndex + Index].DeviceType =3D BBS_HARDDISK; + } else if ((HddInfo[HddIndex].Status & HDD_SLAVE_ATAPI_CDROM) = !=3D 0) { + BbsTable[BbsIndex + Index].DeviceType =3D BBS_CDROM; + } else { + // + // for ZIPDISK + // + BbsTable[BbsIndex + Index].DeviceType =3D BBS_HARDDISK; + } + } else { + BbsTable[BbsIndex + Index].BootPriority =3D BBS_IGNORE_ENTRY; + } + } + } + } + } + + return EFI_SUCCESS; + +} + + +/** + Get all BBS info + + @param This Protocol instance pointer. + @param HddCount Number of HDD_INFO structures + @param HddInfo Onboard IDE controller information + @param BbsCount Number of BBS_TABLE structures + @param BbsTable List BBS entries + + @retval EFI_SUCCESS Tables returned + @retval EFI_NOT_FOUND resource not found + @retval EFI_DEVICE_ERROR can not get BBS table + +**/ +EFI_STATUS +EFIAPI +LegacyBiosGetBbsInfo ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *HddCount, + OUT HDD_INFO **HddInfo, + OUT UINT16 *BbsCount, + OUT BBS_TABLE **BbsTable + ) +{ + LEGACY_BIOS_INSTANCE *Private; + EFI_IA32_REGISTER_SET Regs; + EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; +// HDD_INFO *LocalHddInfo; +// IN BBS_TABLE *LocalBbsTable; + UINTN NumHandles; + EFI_HANDLE *HandleBuffer; + UINTN Index; + UINTN TempData; + UINT32 Granularity; + + HandleBuffer =3D NULL; + + Private =3D LEGACY_BIOS_INSTANCE_FROM_THIS (This); + EfiToLegacy16BootTable =3D &Private->IntThunk->EfiToLegacy16BootTable; +// LocalHddInfo =3D EfiToLegacy16BootTable->HddInfo; +// LocalBbsTable =3D (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable-= >BbsTable; + + if (!mBbsTableDoneFlag) { + mBbsTable =3D Private->BbsTablePtr; + + // + // Always enable disk controllers so 16-bit CSM code has valid informa= tion for all + // drives. + // + // + // Get PciRootBridgeIO protocol + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &NumHandles, + &HandleBuffer + ); + + if (NumHandles =3D=3D 0) { + return EFI_NOT_FOUND; + } + + mBbsTableDoneFlag =3D TRUE; + for (Index =3D 0; Index < NumHandles; Index++) { + // + // Connect PciRootBridgeIO protocol handle with FALSE parameter to l= et + // PCI bus driver enumerate all subsequent handles + // + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE); + + } + + LegacyBiosBuildBbs (Private, mBbsTable); + + Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xe0000, 0x20000= , &Granularity); + + // + // Call into Legacy16 code to add to BBS table for non BBS compliant O= PROMs. + // + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX =3D Legacy16UpdateBbs; + + // + // Pass in handoff data + // + TempData =3D (UINTN) EfiToLegacy16BootTable; + Regs.X.ES =3D NORMALIZE_EFI_SEGMENT ((UINT32) TempData); + Regs.X.BX =3D NORMALIZE_EFI_OFFSET ((UINT32) TempData); + + Private->LegacyBios.FarCall86 ( + This, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + + Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFl= ushTypeWriteBackInvalidate); + Private->LegacyRegion->Lock (Private->LegacyRegion, 0xe0000, 0x20000, = &Granularity); + + if (Regs.X.AX !=3D 0) { + return EFI_DEVICE_ERROR; + } + } + + if (HandleBuffer !=3D NULL) { + FreePool (HandleBuffer); + } + + *HddCount =3D MAX_IDE_CONTROLLER; + *HddInfo =3D EfiToLegacy16BootTable->HddInfo; + *BbsTable =3D (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable; + *BbsCount =3D (UINT16) (sizeof (Private->IntThunk->BbsTable) / sizeof (B= BS_TABLE)); + return EFI_SUCCESS; +} diff --git a/OvmfPkg/Csm/LegacyBiosDxe/LegacyBda.c b/OvmfPkg/Csm/LegacyBios= Dxe/LegacyBda.c new file mode 100644 index 0000000000..aa6e07ab91 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/LegacyBda.c @@ -0,0 +1,62 @@ +/** @file + This code fills in BDA (0x400) and EBDA (pointed to by 0x4xx) + information. There is support for doing initializeation before + Legacy16 is loaded and before a legacy boot is attempted. + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "LegacyBiosInterface.h" + +/** + Fill in the standard BDA and EBDA stuff before Legacy16 load + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosInitBda ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + BDA_STRUC *Bda; + UINT8 *Ebda; + + Bda =3D (BDA_STRUC *) ((UINTN) 0x400); + Ebda =3D (UINT8 *) ((UINTN) 0x9fc00); + + ACCESS_PAGE0_CODE ( + ZeroMem (Bda, 0x100); + // + // 640k-1k for EBDA + // + Bda->MemSize =3D 0x27f; + Bda->KeyHead =3D 0x1e; + Bda->KeyTail =3D 0x1e; + Bda->FloppyData =3D 0x00; + Bda->FloppyTimeout =3D 0xff; + + Bda->KeyStart =3D 0x001E; + Bda->KeyEnd =3D 0x003E; + Bda->KeyboardStatus =3D 0x10; + Bda->Ebda =3D 0x9fc0; + + // + // Move LPT time out here and zero out LPT4 since some SCSI OPROMS + // use this as scratch pad (LPT4 is Reserved) + // + Bda->Lpt1_2Timeout =3D 0x1414; + Bda->Lpt3_4Timeout =3D 0x1400; + + ); + + ZeroMem (Ebda, 0x400); + *Ebda =3D 0x01; + + return EFI_SUCCESS; +} diff --git a/OvmfPkg/Csm/LegacyBiosDxe/LegacyBios.c b/OvmfPkg/Csm/LegacyBio= sDxe/LegacyBios.c new file mode 100644 index 0000000000..05e3ffd2bb --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/LegacyBios.c @@ -0,0 +1,1214 @@ +/** @file + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "LegacyBiosInterface.h" + +#define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *) ((UINTN) Address)) + +// +// define maximum number of HDD system supports +// +#define MAX_HDD_ENTRIES 0x30 + +// +// Module Global: +// Since this driver will only ever produce one instance of the Private D= ata +// protocol you are not required to dynamically allocate the PrivateData. +// +LEGACY_BIOS_INSTANCE mPrivateData; + +// +// The SMBIOS table in EfiRuntimeServicesData memory +// +VOID *mRuntimeSmbiosEntryPoint =3D NULL; + +// +// The SMBIOS table in EfiReservedMemoryType memory +// +EFI_PHYSICAL_ADDRESS mReserveSmbiosEntryPoint =3D 0; +EFI_PHYSICAL_ADDRESS mStructureTableAddress =3D 0; +UINTN mStructureTablePages =3D 0; +BOOLEAN mEndOfDxe =3D FALSE; + +/** + Allocate memory for legacy usage. The memory is executable. + + @param AllocateType The type of allocation to perform. + @param MemoryType The type of memory to allocate. + @param StartPageAddress Start address of range + @param Pages Number of pages to allocate + @param Result Result of allocation + + @retval EFI_SUCCESS Legacy memory is allocated successful= ly. + @retval Other Legacy memory is not allocated. + +**/ +EFI_STATUS +AllocateLegacyMemory ( + IN EFI_ALLOCATE_TYPE AllocateType, + IN EFI_MEMORY_TYPE MemoryType, + IN EFI_PHYSICAL_ADDRESS StartPageAddress, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Result + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS MemPage; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc; + + // + // Allocate Pages of memory less <=3D StartPageAddress + // + MemPage =3D (EFI_PHYSICAL_ADDRESS) (UINTN) StartPageAddress; + Status =3D gBS->AllocatePages ( + AllocateType, + MemoryType, + Pages, + &MemPage + ); + // + // Do not ASSERT on Status error but let caller decide since some cases + // memory is already taken but that is ok. + // + if (!EFI_ERROR (Status)) { + if (MemoryType !=3D EfiBootServicesCode) { + // + // Make sure that the buffer can be used to store code. + // + Status =3D gDS->GetMemorySpaceDescriptor (MemPage, &MemDesc); + if (!EFI_ERROR (Status) && (MemDesc.Attributes & EFI_MEMORY_XP) !=3D= 0) { + Status =3D gDS->SetMemorySpaceAttributes ( + MemPage, + EFI_PAGES_TO_SIZE (Pages), + MemDesc.Attributes & (~EFI_MEMORY_XP) + ); + } + if (EFI_ERROR (Status)) { + gBS->FreePages (MemPage, Pages); + } + } + } + + if (!EFI_ERROR (Status)) { + *Result =3D (EFI_PHYSICAL_ADDRESS) (UINTN) MemPage; + } + + return Status; +} + + +/** + This function is called when EFI needs to reserve an area in the 0xE0000= or 0xF0000 + 64 KB blocks. + + Note: inconsistency with the Framework CSM spec. Per the spec, this func= tion may be + invoked only once. This limitation is relaxed to allow multiple calls in= this implemenation. + + @param This Protocol instance pointer. + @param LegacyMemorySize Size of required region + @param Region Region to use. 00 =3D Either 0xE0000 = or 0xF0000 + block Bit0 =3D 1 0xF0000 block Bit1 = =3D 1 0xE0000 + block + @param Alignment Address alignment. Bit mapped. First = non-zero + bit from right is alignment. + @param LegacyMemoryAddress Region Assigned + + @retval EFI_SUCCESS Region assigned + @retval EFI_ACCESS_DENIED Procedure previously invoked + @retval Other Region not assigned + +**/ +EFI_STATUS +EFIAPI +LegacyBiosGetLegacyRegion ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN UINTN Region, + IN UINTN Alignment, + OUT VOID **LegacyMemoryAddress + ) +{ + + LEGACY_BIOS_INSTANCE *Private; + EFI_IA32_REGISTER_SET Regs; + EFI_STATUS Status; + UINT32 Granularity; + + Private =3D LEGACY_BIOS_INSTANCE_FROM_THIS (This); + Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xE0000, 0x20000, = &Granularity); + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX =3D Legacy16GetTableAddress; + Regs.X.BX =3D (UINT16) Region; + Regs.X.CX =3D (UINT16) LegacyMemorySize; + Regs.X.DX =3D (UINT16) Alignment; + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + + if (Regs.X.AX =3D=3D 0) { + *LegacyMemoryAddress =3D (VOID *) (((UINTN) Regs.X.DS << 4) + Regs.X.= BX); + Status =3D EFI_SUCCESS; + } else { + Status =3D EFI_OUT_OF_RESOURCES; + } + + Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlus= hTypeWriteBackInvalidate); + Private->LegacyRegion->Lock (Private->LegacyRegion, 0xE0000, 0x20000, &G= ranularity); + + return Status; +} + + +/** + This function is called when copying data to the region assigned by + EFI_LEGACY_BIOS_PROTOCOL.GetLegacyRegion(). + + @param This Protocol instance pointer. + @param LegacyMemorySize Size of data to copy + @param LegacyMemoryAddress Legacy Region destination address Not= e: must + be in region assigned by + LegacyBiosGetLegacyRegion + @param LegacyMemorySourceAddress Source of data + + @retval EFI_SUCCESS The data was copied successfully. + @retval EFI_ACCESS_DENIED Either the starting or ending address= is out of bounds. +**/ +EFI_STATUS +EFIAPI +LegacyBiosCopyLegacyRegion ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN VOID *LegacyMemoryAddress, + IN VOID *LegacyMemorySourceAddress + ) +{ + + LEGACY_BIOS_INSTANCE *Private; + UINT32 Granularity; + + if ((LegacyMemoryAddress < (VOID *)(UINTN)0xE0000 ) || + ((UINTN) LegacyMemoryAddress + LegacyMemorySize > (UINTN) 0x100000) + ) { + return EFI_ACCESS_DENIED; + } + // + // There is no protection from writes over lapping if this function is + // called multiple times. + // + Private =3D LEGACY_BIOS_INSTANCE_FROM_THIS (This); + Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xE0000, 0x20000, = &Granularity); + CopyMem (LegacyMemoryAddress, LegacyMemorySourceAddress, LegacyMemorySiz= e); + + Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlus= hTypeWriteBackInvalidate); + Private->LegacyRegion->Lock (Private->LegacyRegion, 0xE0000, 0x20000, &G= ranularity); + + return EFI_SUCCESS; +} + + +/** + Find Legacy16 BIOS image in the FLASH device and shadow it into memory. = Find + the $EFI table in the shadow area. Thunk into the Legacy16 code after it= had + been shadowed. + + @param Private Legacy BIOS context data + + @retval EFI_SUCCESS Legacy16 code loaded + @retval Other No protocol installed, unload driver. + +**/ +EFI_STATUS +ShadowAndStartLegacy16 ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + UINT8 *Ptr; + UINT8 *PtrEnd; + BOOLEAN Done; + EFI_COMPATIBILITY16_TABLE *Table; + UINT8 CheckSum; + EFI_IA32_REGISTER_SET Regs; + EFI_TO_COMPATIBILITY16_INIT_TABLE *EfiToLegacy16InitTable; + EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; + VOID *LegacyBiosImage; + UINTN LegacyBiosImageSize; + UINTN E820Size; + UINT32 *ClearPtr; + BBS_TABLE *BbsTable; + LEGACY_EFI_HDD_TABLE *LegacyEfiHddTable; + UINTN Index; + UINT32 TpmPointer; + VOID *TpmBinaryImage; + UINTN TpmBinaryImageSize; + UINTN Location; + UINTN Alignment; + UINTN TempData; + EFI_PHYSICAL_ADDRESS Address; + UINT16 OldMask; + UINT16 NewMask; + UINT32 Granularity; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + + Location =3D 0; + Alignment =3D 0; + + // + // we allocate the C/D/E/F segment as RT code so no one will use it any = more. + // + Address =3D 0xC0000; + gDS->GetMemorySpaceDescriptor (Address, &Descriptor); + if (Descriptor.GcdMemoryType =3D=3D EfiGcdMemoryTypeSystemMemory) { + // + // If it is already reserved, we should be safe, or else we allocate i= t. + // + Status =3D gBS->AllocatePages ( + AllocateAddress, + EfiRuntimeServicesCode, + 0x40000/EFI_PAGE_SIZE, + &Address + ); + if (EFI_ERROR (Status)) { + // + // Bugbug: need to figure out whether C/D/E/F segment should be mark= ed as reserved memory. + // + DEBUG ((DEBUG_ERROR, "Failed to allocate the C/D/E/F segment Status = =3D %r", Status)); + } + } + + // + // start testtest + // GetTimerValue (&Ticker); + // + // gRT->SetVariable (L"StartLegacy", + // &gEfiGlobalVariableGuid, + // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVI= CE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + // sizeof (UINT64), + // (VOID *)&Ticker + // ); + // end testtest + // + EfiToLegacy16BootTable =3D &Private->IntThunk->EfiToLegacy16BootTable; + Status =3D Private->LegacyBiosPlatform->GetPlatformInfo ( + Private->LegacyBiosPlatform, + EfiGetPlatformBinarySystemRom, + &LegacyBiosImage, + &LegacyBiosImageSize, + &Location, + &Alignment, + 0, + 0 + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Private->BiosStart =3D (UINT32) (0x100000 - LegacyBiosImageSi= ze); + Private->OptionRom =3D 0xc0000; + Private->LegacyBiosImageSize =3D (UINT32) LegacyBiosImageSize; + + // + // Can only shadow into memory allocated for legacy useage. + // + ASSERT (Private->BiosStart > Private->OptionRom); + + // + // Shadow Legacy BIOS. Turn on memory and copy image + // + Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xc0000, 0x40000, = &Granularity); + + ClearPtr =3D (VOID *) ((UINTN) 0xc0000); + + // + // Initialize region from 0xc0000 to start of BIOS to all ffs. This allo= ws unused + // regions to be used by EMM386 etc. + // + SetMem ((VOID *) ClearPtr, (UINTN) (0x40000 - LegacyBiosImageSize), 0xff= ); + + TempData =3D Private->BiosStart; + + CopyMem ( + (VOID *) TempData, + LegacyBiosImage, + (UINTN) LegacyBiosImageSize + ); + + Private->Cpu->FlushDataCache (Private->Cpu, 0xc0000, 0x40000, EfiCpuFlus= hTypeWriteBackInvalidate); + + // + // Search for Legacy16 table in Shadowed ROM + // + Done =3D FALSE; + Table =3D NULL; + for (Ptr =3D (UINT8 *) TempData; Ptr < (UINT8 *) ((UINTN) 0x100000) && != Done; Ptr +=3D 0x10) { + if (*(UINT32 *) Ptr =3D=3D SIGNATURE_32 ('I', 'F', 'E', '$')) { + Table =3D (EFI_COMPATIBILITY16_TABLE *) Ptr; + PtrEnd =3D Ptr + Table->TableLength; + for (CheckSum =3D 0; Ptr < PtrEnd; Ptr++) { + CheckSum =3D (UINT8) (CheckSum +*Ptr); + } + + Done =3D TRUE; + } + } + + if (Table =3D=3D NULL) { + DEBUG ((EFI_D_ERROR, "No Legacy16 table found\n")); + return EFI_NOT_FOUND; + } + + if (!Done) { + // + // Legacy16 table header checksum error. + // + DEBUG ((EFI_D_ERROR, "Legacy16 table found with bad talbe header check= sum\n")); + } + + // + // Remember location of the Legacy16 table + // + Private->Legacy16Table =3D Table; + Private->Legacy16CallSegment =3D Table->Compatibility16CallSegment; + Private->Legacy16CallOffset =3D Table->Compatibility16CallOffset; + EfiToLegacy16InitTable =3D &Private->IntThunk->EfiToLegacy16I= nitTable; + Private->Legacy16InitPtr =3D EfiToLegacy16InitTable; + Private->Legacy16BootPtr =3D &Private->IntThunk->EfiToLegacy16B= ootTable; + Private->InternalIrqRoutingTable =3D NULL; + Private->NumberIrqRoutingEntries =3D 0; + Private->BbsTablePtr =3D NULL; + Private->LegacyEfiHddTable =3D NULL; + Private->DiskEnd =3D 0; + Private->Disk4075 =3D 0; + Private->HddTablePtr =3D &Private->IntThunk->EfiToLegacy16B= ootTable.HddInfo; + Private->NumberHddControllers =3D MAX_IDE_CONTROLLER; + Private->Dump[0] =3D 'D'; + Private->Dump[1] =3D 'U'; + Private->Dump[2] =3D 'M'; + Private->Dump[3] =3D 'P'; + + ZeroMem ( + Private->Legacy16BootPtr, + sizeof (EFI_TO_COMPATIBILITY16_BOOT_TABLE) + ); + + // + // Store away a copy of the EFI System Table + // + Table->EfiSystemTable =3D (UINT32) (UINTN) gST; + + // + // IPF CSM integration -Bug + // + // Construct the Legacy16 boot memory map. This sets up number of + // E820 entries. + // + LegacyBiosBuildE820 (Private, &E820Size); + // + // Initialize BDA and EBDA standard values needed to load Legacy16 code + // + LegacyBiosInitBda (Private); + LegacyBiosInitCmos (Private); + + // + // All legacy interrupt should be masked when do initialization work fro= m legacy 16 code. + // + Private->Legacy8259->GetMask(Private->Legacy8259, &OldMask, NULL, NULL, = NULL); + NewMask =3D 0xFFFF; + Private->Legacy8259->SetMask(Private->Legacy8259, &NewMask, NULL, NULL, = NULL); + + // + // Call into Legacy16 code to do an INIT + // + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX =3D Legacy16InitializeYourself; + Regs.X.ES =3D EFI_SEGMENT (*((UINT32 *) &EfiToLegacy16InitTable)); + Regs.X.BX =3D EFI_OFFSET (*((UINT32 *) &EfiToLegacy16InitTable)); + + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Table->Compatibility16CallSegment, + Table->Compatibility16CallOffset, + &Regs, + NULL, + 0 + ); + + // + // Restore original legacy interrupt mask value + // + Private->Legacy8259->SetMask(Private->Legacy8259, &OldMask, NULL, NULL, = NULL); + + if (Regs.X.AX !=3D 0) { + return EFI_DEVICE_ERROR; + } + + // + // start testtest + // GetTimerValue (&Ticker); + // + // gRT->SetVariable (L"BackFromInitYourself", + // &gEfiGlobalVariableGuid, + // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVI= CE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + // sizeof (UINT64), + // (VOID *)&Ticker + // ); + // end testtest + // + // Copy E820 table after InitializeYourself is completed + // + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX =3D Legacy16GetTableAddress; + Regs.X.CX =3D (UINT16) E820Size; + Regs.X.DX =3D 1; + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Table->Compatibility16CallSegment, + Table->Compatibility16CallOffset, + &Regs, + NULL, + 0 + ); + + Table->E820Pointer =3D (UINT32) (Regs.X.DS * 16 + Regs.X.BX); + Table->E820Length =3D (UINT32) E820Size; + if (Regs.X.AX !=3D 0) { + DEBUG ((EFI_D_ERROR, "Legacy16 E820 length insufficient\n")); + } else { + TempData =3D Table->E820Pointer; + CopyMem ((VOID *) TempData, Private->E820Table, E820Size); + } + // + // Get PnPInstallationCheck Info. + // + Private->PnPInstallationCheckSegment =3D Table->PnPInstallationCheckSeg= ment; + Private->PnPInstallationCheckOffset =3D Table->PnPInstallationCheckOff= set; + + // + // Check if PCI Express is supported. If yes, Save base address. + // + Status =3D Private->LegacyBiosPlatform->GetPlatformInfo ( + Private->LegacyBiosPlatform, + EfiGetPlatformPciExpressBase, + NULL, + NULL, + &Location, + &Alignment, + 0, + 0 + ); + if (!EFI_ERROR (Status)) { + Private->Legacy16Table->PciExpressBase =3D (UINT32)Location; + Location =3D 0; + } + // + // Check if TPM is supported. If yes get a region in E0000,F0000 to copy= it + // into, copy it and update pointer to binary image. This needs to be + // done prior to any OPROM for security purposes. + // + Status =3D Private->LegacyBiosPlatform->GetPlatformInfo ( + Private->LegacyBiosPlatform, + EfiGetPlatformBinaryTpmBinary, + &TpmBinaryImage, + &TpmBinaryImageSize, + &Location, + &Alignment, + 0, + 0 + ); + if (!EFI_ERROR (Status)) { + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX =3D Legacy16GetTableAddress; + Regs.X.CX =3D (UINT16) TpmBinaryImageSize; + Regs.X.DX =3D 1; + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Table->Compatibility16CallSegment, + Table->Compatibility16CallOffset, + &Regs, + NULL, + 0 + ); + + TpmPointer =3D (UINT32) (Regs.X.DS * 16 + Regs.X.BX); + if (Regs.X.AX !=3D 0) { + DEBUG ((EFI_D_ERROR, "TPM cannot be loaded\n")); + } else { + CopyMem ((VOID *) (UINTN)TpmPointer, TpmBinaryImage, TpmBinaryImageS= ize); + Table->TpmSegment =3D Regs.X.DS; + Table->TpmOffset =3D Regs.X.BX; + + } + } + // + // Lock the Legacy BIOS region + // + Private->Cpu->FlushDataCache (Private->Cpu, Private->BiosStart, (UINT32)= LegacyBiosImageSize, EfiCpuFlushTypeWriteBackInvalidate); + Private->LegacyRegion->Lock (Private->LegacyRegion, Private->BiosStart, = (UINT32) LegacyBiosImageSize, &Granularity); + + // + // Get the BbsTable from LOW_MEMORY_THUNK + // + BbsTable =3D (BBS_TABLE *)(UINTN)Private->IntThunk->BbsTable; + ZeroMem ((VOID *)BbsTable, sizeof (Private->IntThunk->BbsTable)); + + EfiToLegacy16BootTable->BbsTable =3D (UINT32)(UINTN)BbsTable; + Private->BbsTablePtr =3D (VOID *) BbsTable; + // + // Skip Floppy and possible onboard IDE drives + // + EfiToLegacy16BootTable->NumberBbsEntries =3D 1 + 2 * MAX_IDE_CONTROLLER; + + for (Index =3D 0; Index < (sizeof (Private->IntThunk->BbsTable) / sizeof= (BBS_TABLE)); Index++) { + BbsTable[Index].BootPriority =3D BBS_IGNORE_ENTRY; + } + // + // Allocate space for Legacy HDD table + // + LegacyEfiHddTable =3D (LEGACY_EFI_HDD_TABLE *) AllocateZeroPool ((UINTN)= MAX_HDD_ENTRIES * sizeof (LEGACY_EFI_HDD_TABLE)); + ASSERT (LegacyEfiHddTable); + + Private->LegacyEfiHddTable =3D LegacyEfiHddTable; + Private->LegacyEfiHddTableIndex =3D 0x00; + + // + // start testtest + // GetTimerValue (&Ticker); + // + // gRT->SetVariable (L"EndOfLoadFv", + // &gEfiGlobalVariableGuid, + // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVI= CE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + // sizeof (UINT64), + // (VOID *)&Ticker + // ); + // end testtest + // + return EFI_SUCCESS; +} + +/** + Shadow all legacy16 OPROMs that haven't been shadowed. + Warning: Use this with caution. This routine disconnects all EFI + drivers. If used externally then caller must re-connect EFI + drivers. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS OPROMs shadowed + +**/ +EFI_STATUS +EFIAPI +LegacyBiosShadowAllLegacyOproms ( + IN EFI_LEGACY_BIOS_PROTOCOL *This + ) +{ + LEGACY_BIOS_INSTANCE *Private; + + // + // EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; + // EFI_LEGACY16_TABLE *Legacy16Table; + // + Private =3D LEGACY_BIOS_INSTANCE_FROM_THIS (This); + + // + // LegacyBiosPlatform =3D Private->LegacyBiosPlatform; + // Legacy16Table =3D Private->Legacy16Table; + // + // Shadow PCI ROMs. We must do this near the end since this will kick + // of Native EFI drivers that may be needed to collect info for Legacy16 + // + // WARNING: PciIo is gone after this call. + // + PciProgramAllInterruptLineRegisters (Private); + + PciShadowRoms (Private); + + // + // Shadow PXE base code, BIS etc. + // + // LegacyBiosPlatform->ShadowServiceRoms (LegacyBiosPlatform, + // &Private->OptionRom, + // Legacy16Table); + // + return EFI_SUCCESS; +} + +/** + Get the PCI BIOS interface version. + + @param Private Driver private data. + + @return The PCI interface version number in Binary Coded Decimal (BCD) f= ormat. + E.g.: 0x0210 indicates 2.10, 0x0300 indicates 3.00 + +**/ +UINT16 +GetPciInterfaceVersion ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_IA32_REGISTER_SET Reg; + BOOLEAN ThunkFailed; + UINT16 PciInterfaceVersion; + + PciInterfaceVersion =3D 0; + + Reg.X.AX =3D 0xB101; + Reg.E.EDI =3D 0; + + ThunkFailed =3D Private->LegacyBios.Int86 (&Private->LegacyBios, 0x1A, &= Reg); + if (!ThunkFailed) { + // + // From PCI Firmware 3.0 Specification: + // If the CARRY FLAG [CF] is cleared and AH is set to 00h, it is sti= ll necessary to examine the + // contents of [EDX] for the presence of the string "PCI" + (trailin= g space) to fully validate the + // presence of the PCI function set. [BX] will further indicate the = version level, with enough + // granularity to allow for incremental changes in the code that don= 't affect the function interface. + // Version numbers are stored as Binary Coded Decimal (BCD) values. = For example, Version 2.10 + // would be returned as a 02h in the [BH] registers and 10h in the [= BL] registers. + // + if ((Reg.X.Flags.CF =3D=3D 0) && (Reg.H.AH =3D=3D 0) && (Reg.E.EDX =3D= =3D SIGNATURE_32 ('P', 'C', 'I', ' '))) { + PciInterfaceVersion =3D Reg.X.BX; + } + } + return PciInterfaceVersion; +} + +/** + Callback function to calculate SMBIOS table size, and allocate memory fo= r SMBIOS table. + SMBIOS table will be copied into EfiReservedMemoryType memory in legacy = boot path. + + @param Event Event whose notification function is being= invoked. + @param Context The pointer to the notification function's= context, + which is implementation-dependent. + +**/ +VOID +EFIAPI +InstallSmbiosEventCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure; + + // + // Get SMBIOS table from EFI configuration table + // + Status =3D EfiGetSystemConfigurationTable ( + &gEfiSmbiosTableGuid, + &mRuntimeSmbiosEntryPoint + ); + if ((EFI_ERROR (Status)) || (mRuntimeSmbiosEntryPoint =3D=3D NULL)) { + return; + } + + EntryPointStructure =3D (SMBIOS_TABLE_ENTRY_POINT *) mRuntimeSmbiosEntry= Point; + + // + // Allocate memory for SMBIOS Entry Point Structure. + // CSM framework spec requires SMBIOS table below 4GB in EFI_TO_COMPATIB= ILITY16_BOOT_TABLE. + // + if (mReserveSmbiosEntryPoint =3D=3D 0) { + // + // Entrypoint structure with fixed size is allocated only once. + // + mReserveSmbiosEntryPoint =3D SIZE_4GB - 1; + Status =3D gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + EFI_SIZE_TO_PAGES ((UINTN) (EntryPointStructure->Entry= PointLength)), + &mReserveSmbiosEntryPoint + ); + if (EFI_ERROR (Status)) { + mReserveSmbiosEntryPoint =3D 0; + return; + } + DEBUG ((EFI_D_INFO, "Allocate memory for Smbios Entry Point Structure\= n")); + } + + if ((mStructureTableAddress !=3D 0) && + (mStructureTablePages < EFI_SIZE_TO_PAGES ((UINT32)EntryPointStructu= re->TableLength))) { + // + // If original buffer is not enough for the new SMBIOS table, free ori= ginal buffer and re-allocate + // + gBS->FreePages (mStructureTableAddress, mStructureTablePages); + mStructureTableAddress =3D 0; + mStructureTablePages =3D 0; + DEBUG ((EFI_D_INFO, "Original size is not enough. Re-allocate the memo= ry.\n")); + } + + if (mStructureTableAddress =3D=3D 0) { + // + // Allocate reserved memory below 4GB. + // Smbios spec requires the structure table is below 4GB. + // + mStructureTableAddress =3D SIZE_4GB - 1; + mStructureTablePages =3D EFI_SIZE_TO_PAGES (EntryPointStructure->Tab= leLength); + Status =3D gBS->AllocatePages ( + AllocateMaxAddress, + EfiReservedMemoryType, + mStructureTablePages, + &mStructureTableAddress + ); + if (EFI_ERROR (Status)) { + gBS->FreePages ( + mReserveSmbiosEntryPoint, + EFI_SIZE_TO_PAGES ((UINTN) (EntryPointStructure->EntryPointLength)) + ); + mReserveSmbiosEntryPoint =3D 0; + mStructureTableAddress =3D 0; + mStructureTablePages =3D 0; + return; + } + DEBUG ((EFI_D_INFO, "Allocate memory for Smbios Structure Table\n")); + } +} + +/** + Callback function to toggle EndOfDxe status. NULL pointer detection needs + this status to decide if it's necessary to change attributes of page 0. + + @param Event Event whose notification function is being invo= ked. + @param Context The pointer to the notification function's cont= ext, + which is implementation-dependent. + +**/ +VOID +EFIAPI +ToggleEndOfDxeStatus ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + mEndOfDxe =3D TRUE; + return; +} + +/** + Install Driver to produce Legacy BIOS protocol. + + @param ImageHandle Handle of driver image. + @param SystemTable Pointer to system table. + + @retval EFI_SUCCESS Legacy BIOS protocol installed + @retval No protocol installed, unload driver. + +**/ +EFI_STATUS +EFIAPI +LegacyBiosInstall ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LEGACY_BIOS_INSTANCE *Private; + EFI_TO_COMPATIBILITY16_INIT_TABLE *EfiToLegacy16InitTable; + EFI_PHYSICAL_ADDRESS MemoryAddress; + EFI_PHYSICAL_ADDRESS EbdaReservedBaseAddress; + VOID *MemoryPtr; + EFI_PHYSICAL_ADDRESS MemoryAddressUnder1MB; + UINTN Index; + UINT32 *BaseVectorMaster; + EFI_PHYSICAL_ADDRESS StartAddress; + UINT32 *ClearPtr; + EFI_PHYSICAL_ADDRESS MemStart; + UINT32 IntRedirCode; + UINT32 Granularity; + BOOLEAN DecodeOn; + UINT32 MemorySize; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + UINT64 Length; + UINT8 *SecureBoot; + EFI_EVENT InstallSmbiosEvent; + EFI_EVENT EndOfDxeEvent; + + // + // Load this driver's image to memory + // + Status =3D RelocateImageUnder4GIfNeeded (ImageHandle, SystemTable); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // When UEFI Secure Boot is enabled, CSM module will not start any more. + // + SecureBoot =3D NULL; + GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, N= ULL); + if ((SecureBoot !=3D NULL) && (*SecureBoot =3D=3D SECURE_BOOT_MODE_ENABL= E)) { + FreePool (SecureBoot); + return EFI_SECURITY_VIOLATION; + } + + if (SecureBoot !=3D NULL) { + FreePool (SecureBoot); + } + + Private =3D &mPrivateData; + ZeroMem (Private, sizeof (LEGACY_BIOS_INSTANCE)); + + // + // Grab a copy of all the protocols we depend on. Any error would + // be a dispatcher bug!. + // + Status =3D gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **= ) &Private->Cpu); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->LocateProtocol (&gEfiTimerArchProtocolGuid, NULL, (VOID = **) &Private->Timer); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->LocateProtocol (&gEfiLegacyRegion2ProtocolGuid, NULL, (V= OID **) &Private->LegacyRegion); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->LocateProtocol (&gEfiLegacyBiosPlatformProtocolGuid, NUL= L, (VOID **) &Private->LegacyBiosPlatform); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID= **) &Private->Legacy8259); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->LocateProtocol (&gEfiLegacyInterruptProtocolGuid, NULL, = (VOID **) &Private->LegacyInterrupt); + ASSERT_EFI_ERROR (Status); + + // + // Locate Memory Test Protocol if exists + // + Status =3D gBS->LocateProtocol ( + &gEfiGenericMemTestProtocolGuid, + NULL, + (VOID **) &Private->GenericMemoryTest + ); + ASSERT_EFI_ERROR (Status); + + // + // Make sure all memory from 0-640K is tested + // + for (StartAddress =3D 0; StartAddress < 0xa0000; ) { + gDS->GetMemorySpaceDescriptor (StartAddress, &Descriptor); + if (Descriptor.GcdMemoryType !=3D EfiGcdMemoryTypeReserved) { + StartAddress =3D Descriptor.BaseAddress + Descriptor.Length; + continue; + } + Length =3D MIN (Descriptor.Length, 0xa0000 - StartAddress); + Private->GenericMemoryTest->CompatibleRangeTest ( + Private->GenericMemoryTest, + StartAddress, + Length + ); + StartAddress =3D StartAddress + Length; + } + // + // Make sure all memory from 1MB to 16MB is tested and added to memory m= ap + // + for (StartAddress =3D BASE_1MB; StartAddress < BASE_16MB; ) { + gDS->GetMemorySpaceDescriptor (StartAddress, &Descriptor); + if (Descriptor.GcdMemoryType !=3D EfiGcdMemoryTypeReserved) { + StartAddress =3D Descriptor.BaseAddress + Descriptor.Length; + continue; + } + Length =3D MIN (Descriptor.Length, BASE_16MB - StartAddress); + Private->GenericMemoryTest->CompatibleRangeTest ( + Private->GenericMemoryTest, + StartAddress, + Length + ); + StartAddress =3D StartAddress + Length; + } + + Private->Signature =3D LEGACY_BIOS_INSTANCE_SIGNATURE; + + Private->LegacyBios.Int86 =3D LegacyBiosInt86; + Private->LegacyBios.FarCall86 =3D LegacyBiosFarCall86; + Private->LegacyBios.CheckPciRom =3D LegacyBiosCheckPciRom; + Private->LegacyBios.InstallPciRom =3D LegacyBiosInstallPciRom; + Private->LegacyBios.LegacyBoot =3D LegacyBiosLegacyBoot; + Private->LegacyBios.UpdateKeyboardLedStatus =3D LegacyBiosUpdateKeyboard= LedStatus; + Private->LegacyBios.GetBbsInfo =3D LegacyBiosGetBbsInfo; + Private->LegacyBios.ShadowAllLegacyOproms =3D LegacyBiosShadowAllLegacyO= proms; + Private->LegacyBios.PrepareToBootEfi =3D LegacyBiosPrepareToBootEfi; + Private->LegacyBios.GetLegacyRegion =3D LegacyBiosGetLegacyRegion; + Private->LegacyBios.CopyLegacyRegion =3D LegacyBiosCopyLegacyRegion; + Private->LegacyBios.BootUnconventionalDevice =3D LegacyBiosBootUnconvent= ionalDevice; + + Private->ImageHandle =3D ImageHandle; + + // + // Enable read attribute of legacy region. + // + DecodeOn =3D TRUE; + Private->LegacyRegion->Decode ( + Private->LegacyRegion, + 0xc0000, + 0x40000, + &Granularity, + &DecodeOn + ); + // + // Set Cachebility for legacy region + // BUGBUG: Comments about this legacy region cacheability setting + // This setting will make D865GCHProduction CSM Unhappy + // + if (PcdGetBool (PcdLegacyBiosCacheLegacyRegion)) { + gDS->SetMemorySpaceAttributes ( + 0x0, + 0xA0000, + EFI_MEMORY_WB + ); + gDS->SetMemorySpaceAttributes ( + 0xc0000, + 0x40000, + EFI_MEMORY_WB + ); + } + + gDS->SetMemorySpaceAttributes ( + 0xA0000, + 0x20000, + EFI_MEMORY_UC + ); + + // + // Allocate 0 - 4K for real mode interupt vectors and BDA. + // + AllocateLegacyMemory ( + AllocateAddress, + EfiReservedMemoryType, + 0, + 1, + &MemoryAddress + ); + ASSERT (MemoryAddress =3D=3D 0x000000000); + + ClearPtr =3D (VOID *) ((UINTN) 0x0000); + + // + // Initialize region from 0x0000 to 4k. This initializes interrupt vector + // range. + // + ACCESS_PAGE0_CODE ( + gBS->SetMem ((VOID *) ClearPtr, 0x400, INITIAL_VALUE_BELOW_1K); + ZeroMem ((VOID *) ((UINTN)ClearPtr + 0x400), 0xC00); + ); + + // + // Allocate pages for OPROM usage + // + MemorySize =3D PcdGet32 (PcdEbdaReservedMemorySize); + ASSERT ((MemorySize & 0xFFF) =3D=3D 0); + + Status =3D AllocateLegacyMemory ( + AllocateAddress, + EfiReservedMemoryType, + CONVENTIONAL_MEMORY_TOP - MemorySize, + EFI_SIZE_TO_PAGES (MemorySize), + &MemoryAddress + ); + ASSERT_EFI_ERROR (Status); + + ZeroMem ((VOID *) ((UINTN) MemoryAddress), MemorySize); + + // + // Allocate all 32k chunks from 0x60000 ~ 0x88000 for Legacy OPROMs that + // don't use PMM but look for zeroed memory. Note that various non-BBS + // OpROMs expect different areas to be free + // + EbdaReservedBaseAddress =3D MemoryAddress; + MemoryAddress =3D PcdGet32 (PcdOpromReservedMemoryBase); + MemorySize =3D PcdGet32 (PcdOpromReservedMemorySize); + // + // Check if base address and size for reserved memory are 4KB aligned. + // + ASSERT ((MemoryAddress & 0xFFF) =3D=3D 0); + ASSERT ((MemorySize & 0xFFF) =3D=3D 0); + // + // Check if the reserved memory is below EBDA reserved range. + // + ASSERT ((MemoryAddress < EbdaReservedBaseAddress) && ((MemoryAddress + M= emorySize - 1) < EbdaReservedBaseAddress)); + for (MemStart =3D MemoryAddress; MemStart < MemoryAddress + MemorySize; = MemStart +=3D 0x1000) { + Status =3D AllocateLegacyMemory ( + AllocateAddress, + EfiBootServicesCode, + MemStart, + 1, + &StartAddress + ); + if (!EFI_ERROR (Status)) { + MemoryPtr =3D (VOID *) ((UINTN) StartAddress); + ZeroMem (MemoryPtr, 0x1000); + } else { + DEBUG ((EFI_D_ERROR, "WARNING: Allocate legacy memory fail for SCSI = card - %x\n", MemStart)); + } + } + + // + // Allocate low PMM memory and zero it out + // + MemorySize =3D PcdGet32 (PcdLowPmmMemorySize); + ASSERT ((MemorySize & 0xFFF) =3D=3D 0); + Status =3D AllocateLegacyMemory ( + AllocateMaxAddress, + EfiBootServicesCode, + CONVENTIONAL_MEMORY_TOP, + EFI_SIZE_TO_PAGES (MemorySize), + &MemoryAddressUnder1MB + ); + ASSERT_EFI_ERROR (Status); + + ZeroMem ((VOID *) ((UINTN) MemoryAddressUnder1MB), MemorySize); + + // + // Allocate space for thunker and Init Thunker + // + Status =3D AllocateLegacyMemory ( + AllocateMaxAddress, + EfiReservedMemoryType, + CONVENTIONAL_MEMORY_TOP, + (sizeof (LOW_MEMORY_THUNK) / EFI_PAGE_SIZE) + 2, + &MemoryAddress + ); + ASSERT_EFI_ERROR (Status); + Private->IntThunk =3D (LOW_MEMORY_THUNK *) (UINTN) Mem= oryAddress; + EfiToLegacy16InitTable =3D &Private->IntThunk->EfiToLe= gacy16InitTable; + EfiToLegacy16InitTable->ThunkStart =3D (UINT32) (EFI_PHYSICAL_ADDR= ESS) (UINTN) MemoryAddress; + EfiToLegacy16InitTable->ThunkSizeInBytes =3D (UINT32) (sizeof (LOW_MEMOR= Y_THUNK)); + + Status =3D LegacyBiosInitializeThunk (Private); + ASSERT_EFI_ERROR (Status); + + // + // Init the legacy memory map in memory < 1 MB. + // + EfiToLegacy16InitTable->BiosLessThan1MB =3D (UINT32) MemoryAddre= ssUnder1MB; + EfiToLegacy16InitTable->LowPmmMemory =3D (UINT32) MemoryAddre= ssUnder1MB; + EfiToLegacy16InitTable->LowPmmMemorySizeInBytes =3D MemorySize; + + MemorySize =3D PcdGet32 (PcdHighPmmMemorySize); + ASSERT ((MemorySize & 0xFFF) =3D=3D 0); + // + // Allocate high PMM Memory under 16 MB + // + Status =3D AllocateLegacyMemory ( + AllocateMaxAddress, + EfiBootServicesCode, + 0x1000000, + EFI_SIZE_TO_PAGES (MemorySize), + &MemoryAddress + ); + if (EFI_ERROR (Status)) { + // + // If it fails, allocate high PMM Memory under 4GB + // + Status =3D AllocateLegacyMemory ( + AllocateMaxAddress, + EfiBootServicesCode, + 0xFFFFFFFF, + EFI_SIZE_TO_PAGES (MemorySize), + &MemoryAddress + ); + } + if (!EFI_ERROR (Status)) { + EfiToLegacy16InitTable->HiPmmMemory =3D (UINT32) (EFI_PHYSI= CAL_ADDRESS) (UINTN) MemoryAddress; + EfiToLegacy16InitTable->HiPmmMemorySizeInBytes =3D MemorySize; + } + + // + // ShutdownAPs(); + // + // Start the Legacy BIOS; + // + Status =3D ShadowAndStartLegacy16 (Private); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Initialize interrupt redirection code and entries; + // IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f. + // + CopyMem ( + Private->IntThunk->InterruptRedirectionCode, + (VOID *) (UINTN) InterruptRedirectionTemplate, + sizeof (Private->IntThunk->InterruptRedirectionCode) + ); + + // + // Save Unexpected interrupt vector so can restore it just prior to boot + // + ACCESS_PAGE0_CODE ( + BaseVectorMaster =3D (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BASE= _VECTOR_MASTER); + Private->BiosUnexpectedInt =3D BaseVectorMaster[0]; + IntRedirCode =3D (UINT32) (UINTN) Private->IntThunk->InterruptRedirect= ionCode; + for (Index =3D 0; Index < 8; Index++) { + BaseVectorMaster[Index] =3D (EFI_SEGMENT (IntRedirCode + Index * 4) = << 16) | EFI_OFFSET (IntRedirCode + Index * 4); + } + ); + + // + // Save EFI value + // + Private->ThunkSeg =3D (UINT16) (EFI_SEGMENT (IntRedirCode)); + + // + // Allocate reserved memory for SMBIOS table used in legacy boot if SMBI= OS table exists + // + InstallSmbiosEventCallback (NULL, NULL); + + // + // Create callback function to update the size of reserved memory after = LegacyBiosDxe starts + // + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + InstallSmbiosEventCallback, + NULL, + &gEfiSmbiosTableGuid, + &InstallSmbiosEvent + ); + ASSERT_EFI_ERROR (Status); + + // + // Create callback to update status of EndOfDxe, which is needed by NULL + // pointer detection + // + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + ToggleEndOfDxeStatus, + NULL, + &gEfiEndOfDxeEventGroupGuid, + &EndOfDxeEvent + ); + ASSERT_EFI_ERROR (Status); + + // + // Make a new handle and install the protocol + // + Private->Handle =3D NULL; + Status =3D gBS->InstallProtocolInterface ( + &Private->Handle, + &gEfiLegacyBiosProtocolGuid, + EFI_NATIVE_INTERFACE, + &Private->LegacyBios + ); + Private->Csm16PciInterfaceVersion =3D GetPciInterfaceVersion (Private); + + DEBUG ((EFI_D_INFO, "CSM16 PCI BIOS Interface Version: %02x.%02x\n", + (UINT8) (Private->Csm16PciInterfaceVersion >> 8), + (UINT8) Private->Csm16PciInterfaceVersion + )); + ASSERT (Private->Csm16PciInterfaceVersion !=3D 0); + return Status; +} diff --git a/OvmfPkg/Csm/LegacyBiosDxe/LegacyBootSupport.c b/OvmfPkg/Csm/Le= gacyBiosDxe/LegacyBootSupport.c new file mode 100644 index 0000000000..211750c012 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/LegacyBootSupport.c @@ -0,0 +1,2173 @@ +/** @file + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "LegacyBiosInterface.h" +#include + +#define BOOT_LEGACY_OS 0 +#define BOOT_EFI_OS 1 +#define BOOT_UNCONVENTIONAL_DEVICE 2 + +UINT32 mLoadOptionsSize =3D 0; +UINTN mBootMode =3D BOOT_LEGACY_OS; +VOID *mLoadOptions =3D NULL; +BBS_BBS_DEVICE_PATH *mBbsDevicePathPtr =3D NULL; +BBS_BBS_DEVICE_PATH mBbsDevicePathNode; +UDC_ATTRIBUTES mAttributes =3D { 0, 0, 0, 0 }; +UINTN mBbsEntry =3D 0; +VOID *mBeerData =3D NULL; +VOID *mServiceAreaData =3D NULL; +UINT64 mLowWater =3D 0xffffffffffffffffULL; + +extern BBS_TABLE *mBbsTable; + +extern VOID *mRuntimeSmbiosEntryPoint; +extern EFI_PHYSICAL_ADDRESS mReserveSmbiosEntryPoint; +extern EFI_PHYSICAL_ADDRESS mStructureTableAddress; + +/** + Print the BBS Table. + + @param BbsTable The BBS table. + + +**/ +VOID +PrintBbsTable ( + IN BBS_TABLE *BbsTable + ) +{ + UINT16 Index; + UINT16 SubIndex; + CHAR8 *String; + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs mfgs:m= fgo dess:deso\n")); + DEBUG ((EFI_D_INFO, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n")); + for (Index =3D 0; Index < MAX_BBS_ENTRIES; Index++) { + // + // Filter + // + if (BbsTable[Index].BootPriority =3D=3D BBS_IGNORE_ENTRY) { + continue; + } + + DEBUG (( + EFI_D_INFO, + " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x", + (UINTN) Index, + (UINTN) BbsTable[Index].BootPriority, + (UINTN) BbsTable[Index].Bus, + (UINTN) BbsTable[Index].Device, + (UINTN) BbsTable[Index].Function, + (UINTN) BbsTable[Index].Class, + (UINTN) BbsTable[Index].SubClass, + (UINTN) BbsTable[Index].DeviceType, + (UINTN) * (UINT16 *) &BbsTable[Index].StatusFlags + )); + DEBUG (( + EFI_D_INFO, + " %04x:%04x %04x:%04x %04x:%04x", + (UINTN) BbsTable[Index].BootHandlerSegment, + (UINTN) BbsTable[Index].BootHandlerOffset, + (UINTN) BbsTable[Index].MfgStringSegment, + (UINTN) BbsTable[Index].MfgStringOffset, + (UINTN) BbsTable[Index].DescStringSegment, + (UINTN) BbsTable[Index].DescStringOffset + )); + + // + // Print DescString + // + String =3D (CHAR8 *)(((UINTN)BbsTable[Index].DescStringSegment << 4) += BbsTable[Index].DescStringOffset); + if (String !=3D NULL) { + DEBUG ((EFI_D_INFO," (")); + for (SubIndex =3D 0; String[SubIndex] !=3D 0; SubIndex++) { + DEBUG ((EFI_D_INFO, "%c", String[SubIndex])); + } + DEBUG ((EFI_D_INFO,")")); + } + DEBUG ((EFI_D_INFO,"\n")); + } + + DEBUG ((EFI_D_INFO, "\n")); + + return ; +} + +/** + Print the BBS Table. + + @param HddInfo The HddInfo table. + + +**/ +VOID +PrintHddInfo ( + IN HDD_INFO *HddInfo + ) +{ + UINTN Index; + + DEBUG ((EFI_D_INFO, "\n")); + for (Index =3D 0; Index < MAX_IDE_CONTROLLER; Index++) { + DEBUG ((EFI_D_INFO, "Index - %04x\n", Index)); + DEBUG ((EFI_D_INFO, " Status - %04x\n", (UINTN)HddInfo[Index].Stat= us)); + DEBUG ((EFI_D_INFO, " B/D/F - %02x/%02x/%02x\n", (UINTN)HddInfo[I= ndex].Bus, (UINTN)HddInfo[Index].Device, (UINTN)HddInfo[Index].Function)); + DEBUG ((EFI_D_INFO, " Command - %04x\n", HddInfo[Index].CommandBase= Address)); + DEBUG ((EFI_D_INFO, " Control - %04x\n", HddInfo[Index].ControlBase= Address)); + DEBUG ((EFI_D_INFO, " BusMaster - %04x\n", HddInfo[Index].BusMasterAd= dress)); + DEBUG ((EFI_D_INFO, " HddIrq - %02x\n", HddInfo[Index].HddIrq)); + DEBUG ((EFI_D_INFO, " IdentifyDrive[0].Raw[0] - %x\n", HddInfo[Index]= .IdentifyDrive[0].Raw[0])); + DEBUG ((EFI_D_INFO, " IdentifyDrive[1].Raw[0] - %x\n", HddInfo[Index]= .IdentifyDrive[1].Raw[0])); + } + + DEBUG ((EFI_D_INFO, "\n")); + + return ; +} + +/** + Print the PCI Interrupt Line and Interrupt Pin registers. +**/ +VOID +PrintPciInterruptRegister ( + VOID + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_HANDLE *Handles; + UINTN HandleNum; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Interrupt[2]; + UINTN Segment; + UINTN Bus; + UINTN Device; + UINTN Function; + + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleNum, + &Handles + ); + + Bus =3D 0; + Device =3D 0; + Function =3D 0; + + DEBUG ((EFI_D_INFO, "\n")); + DEBUG ((EFI_D_INFO, " bb/dd/ff interrupt line interrupt pin\n")); + DEBUG ((EFI_D_INFO, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n")); + for (Index =3D 0; Index < HandleNum; Index++) { + Status =3D gBS->HandleProtocol (Handles[Index], &gEfiPciIoProtocolGuid= , (VOID **) &PciIo); + if (!EFI_ERROR (Status)) { + Status =3D PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PCI_INT_LINE_OFFSET, + 2, + Interrupt + ); + } + if (!EFI_ERROR (Status)) { + Status =3D PciIo->GetLocation ( + PciIo, + &Segment, + &Bus, + &Device, + &Function + ); + } + if (!EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, " %02x/%02x/%02x 0x%02x 0x%02x\n", + Bus, Device, Function, Interrupt[0], Interrupt[1])); + } + } + DEBUG ((EFI_D_INFO, "\n")); + + if (Handles !=3D NULL) { + FreePool (Handles); + } +} + +/** + Identify drive data must be updated to actual parameters before boot. + + @param IdentifyDriveData ATA Identify Data + +**/ +VOID +UpdateIdentifyDriveData ( + IN UINT8 *IdentifyDriveData + ); + +/** + Update SIO data. + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS Removable media not present + +**/ +EFI_STATUS +UpdateSioData ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN Index1; + UINT8 LegacyInterrupts[16]; + EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable; + UINTN RoutingTableEntries; + EFI_LEGACY_IRQ_PRIORITY_TABLE_ENTRY *IrqPriorityTable; + UINTN NumberPriorityEntries; + EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; + UINT8 HddIrq; + UINT16 LegacyInt; + UINT16 LegMask; + UINT32 Register; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_ISA_IO_PROTOCOL *IsaIo; + + LegacyInt =3D 0; + HandleBuffer =3D NULL; + + EfiToLegacy16BootTable =3D &Private->IntThunk->EfiToLegacy16BootTable; + LegacyBiosBuildSioData (Private); + SetMem (LegacyInterrupts, sizeof (LegacyInterrupts), 0); + + // + // Create list of legacy interrupts. + // + for (Index =3D 0; Index < 4; Index++) { + LegacyInterrupts[Index] =3D EfiToLegacy16BootTable->SioData.Serial[Ind= ex].Irq; + } + + for (Index =3D 4; Index < 7; Index++) { + LegacyInterrupts[Index] =3D EfiToLegacy16BootTable->SioData.Parallel[I= ndex - 4].Irq; + } + + LegacyInterrupts[7] =3D EfiToLegacy16BootTable->SioData.Floppy.Irq; + + // + // Get Legacy Hdd IRQs. If native mode treat as PCI + // + for (Index =3D 0; Index < 2; Index++) { + HddIrq =3D EfiToLegacy16BootTable->HddInfo[Index].HddIrq; + if ((HddIrq !=3D 0) && ((HddIrq =3D=3D 15) || (HddIrq =3D=3D 14))) { + LegacyInterrupts[Index + 8] =3D HddIrq; + } + } + + Private->LegacyBiosPlatform->GetRoutingTable ( + Private->LegacyBiosPlatform, + (VOID *) &RoutingTable, + &RoutingTableEntries, + NULL, + NULL, + (VOID **) &IrqPriorityTable, + &NumberPriorityEntries + ); + // + // Remove legacy interrupts from the list of PCI interrupts available. + // + for (Index =3D 0; Index <=3D 0x0b; Index++) { + for (Index1 =3D 0; Index1 <=3D NumberPriorityEntries; Index1++) { + if (LegacyInterrupts[Index] !=3D 0) { + LegacyInt =3D (UINT16) (LegacyInt | (1 << LegacyInterrupts[Index])= ); + if (LegacyInterrupts[Index] =3D=3D IrqPriorityTable[Index1].Irq) { + IrqPriorityTable[Index1].Used =3D LEGACY_USED; + } + } + } + } + + Private->Legacy8259->GetMask ( + Private->Legacy8259, + &LegMask, + NULL, + NULL, + NULL + ); + + // + // Set SIO interrupts and disable mouse. Let mouse driver + // re-enable it. + // + LegMask =3D (UINT16) ((LegMask &~LegacyInt) | 0x1000); + Private->Legacy8259->SetMask ( + Private->Legacy8259, + &LegMask, + NULL, + NULL, + NULL + ); + + // + // Disable mouse in keyboard controller + // + Register =3D 0xA7; + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiIsaIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo + ); + ASSERT_EFI_ERROR (Status); + IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, 0x64, 1, &Register); + + } + + if (HandleBuffer !=3D NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; + +} + +/** + Identify drive data must be updated to actual parameters before boot. + This requires updating the checksum, if it exists. + + @param IdentifyDriveData ATA Identify Data + @param Checksum checksum of the ATA Identify Data + + @retval EFI_SUCCESS checksum calculated + @retval EFI_SECURITY_VIOLATION IdentifyData invalid + +**/ +EFI_STATUS +CalculateIdentifyDriveChecksum ( + IN UINT8 *IdentifyDriveData, + OUT UINT8 *Checksum + ) +{ + UINTN Index; + UINT8 LocalChecksum; + LocalChecksum =3D 0; + *Checksum =3D 0; + if (IdentifyDriveData[510] !=3D 0xA5) { + return EFI_SECURITY_VIOLATION; + } + + for (Index =3D 0; Index < 512; Index++) { + LocalChecksum =3D (UINT8) (LocalChecksum + IdentifyDriveData[Index]); + } + + *Checksum =3D LocalChecksum; + return EFI_SUCCESS; +} + + +/** + Identify drive data must be updated to actual parameters before boot. + + @param IdentifyDriveData ATA Identify Data + + +**/ +VOID +UpdateIdentifyDriveData ( + IN UINT8 *IdentifyDriveData + ) +{ + UINT16 NumberCylinders; + UINT16 NumberHeads; + UINT16 NumberSectorsTrack; + UINT32 CapacityInSectors; + UINT8 OriginalChecksum; + UINT8 FinalChecksum; + EFI_STATUS Status; + ATAPI_IDENTIFY *ReadInfo; + + // + // Status indicates if Integrity byte is correct. Checksum should be + // 0 if valid. + // + ReadInfo =3D (ATAPI_IDENTIFY *) IdentifyDriveData; + Status =3D CalculateIdentifyDriveChecksum (IdentifyDriveData, &Origin= alChecksum); + if (OriginalChecksum !=3D 0) { + Status =3D EFI_SECURITY_VIOLATION; + } + // + // If NumberCylinders =3D 0 then do data(Controller present but don driv= e attached). + // + NumberCylinders =3D ReadInfo->Raw[1]; + if (NumberCylinders !=3D 0) { + ReadInfo->Raw[54] =3D NumberCylinders; + + NumberHeads =3D ReadInfo->Raw[3]; + ReadInfo->Raw[55] =3D NumberHeads; + + NumberSectorsTrack =3D ReadInfo->Raw[6]; + ReadInfo->Raw[56] =3D NumberSectorsTrack; + + // + // Copy Multisector info and set valid bit. + // + ReadInfo->Raw[59] =3D (UINT16) (ReadInfo->Raw[47] + 0x100); + CapacityInSectors =3D (UINT32) ((UINT32) (NumberCylinders) * (UINT32) = (NumberHeads) * (UINT32) (NumberSectorsTrack)); + ReadInfo->Raw[57] =3D (UINT16) (CapacityInSectors >> 16); + ReadInfo->Raw[58] =3D (UINT16) (CapacityInSectors & 0xffff); + if (Status =3D=3D EFI_SUCCESS) { + // + // Forece checksum byte to 0 and get new checksum. + // + ReadInfo->Raw[255] &=3D 0xff; + CalculateIdentifyDriveChecksum (IdentifyDriveData, &FinalChecksum); + + // + // Force new checksum such that sum is 0. + // + FinalChecksum =3D (UINT8) ((UINT8)0 - FinalChecksum); + ReadInfo->Raw[255] =3D (UINT16) (ReadInfo->Raw[255] | (FinalChecksum= << 8)); + } + } +} + +/** + Identify drive data must be updated to actual parameters before boot. + Do for all drives. + + @param Private Legacy BIOS Instance data + + +**/ +VOID +UpdateAllIdentifyDriveData ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + UINTN Index; + HDD_INFO *HddInfo; + + HddInfo =3D &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0]; + + for (Index =3D 0; Index < MAX_IDE_CONTROLLER; Index++) { + // + // Each controller can have 2 devices. Update for each device + // + if ((HddInfo[Index].Status & HDD_MASTER_IDE) !=3D 0) { + UpdateIdentifyDriveData ((UINT8 *) (&HddInfo[Index].IdentifyDrive[0]= .Raw[0])); + } + + if ((HddInfo[Index].Status & HDD_SLAVE_IDE) !=3D 0) { + UpdateIdentifyDriveData ((UINT8 *) (&HddInfo[Index].IdentifyDrive[1]= .Raw[0])); + } + } +} + +/** + Enable ide controller. This gets disabled when LegacyBoot.c is about + to run the Option ROMs. + + @param Private Legacy BIOS Instance data + + +**/ +VOID +EnableIdeController ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_STATUS Status; + EFI_HANDLE IdeController; + UINT8 ByteBuffer; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + + Status =3D Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformIdeHandle, + 0, + &HandleBuffer, + &HandleCount, + NULL + ); + if (!EFI_ERROR (Status)) { + IdeController =3D HandleBuffer[0]; + Status =3D gBS->HandleProtocol ( + IdeController, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + ByteBuffer =3D 0x1f; + if (!EFI_ERROR (Status)) { + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x04, 1, &ByteBuffer); + } + } +} + + +/** + Enable ide controller. This gets disabled when LegacyBoot.c is about + to run the Option ROMs. + + @param Private Legacy BIOS Instance data + + +**/ +VOID +EnableAllControllers ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE01 PciConfigHeader; + EFI_STATUS Status; + + // + // + // + EnableIdeController (Private); + + // + // Assumption is table is built from low bus to high bus numbers. + // + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + ASSERT_EFI_ERROR (Status); + + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + ASSERT_EFI_ERROR (Status); + + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + + // + // We do not enable PPB here. This is for HotPlug Consideration. + // The Platform HotPlug Driver is responsible for Padding enough hot p= lug + // resources. It is also responsible for enable this bridge. If it + // does not pad it. It will cause some early Windows fail to installat= ion. + // If the platform driver does not pad resource for PPB, PPB should be= in + // un-enabled state to let Windows know that this PPB is not configure= d by + // BIOS. So Windows will allocate default resource for PPB. + // + // The reason for why we enable the command register is: + // The CSM will use the IO bar to detect some IRQ status, if the comma= nd + // is disabled, the IO resource will be out of scope. + // For example: + // We installed a legacy IRQ handle for a PCI IDE controller. When IRQ + // comes up, the handle will check the IO space to identify is the + // controller generated the IRQ source. + // If the IO command is not enabled, the IRQ handler will has wrong + // information. It will cause IRQ storm when the correctly IRQ handler= fails + // to run. + // + if (!(IS_PCI_VGA (&PciConfigHeader) || + IS_PCI_OLD_VGA (&PciConfigHeader) || + IS_PCI_IDE (&PciConfigHeader) || + IS_PCI_P2P (&PciConfigHeader) || + IS_PCI_P2P_SUB (&PciConfigHeader) || + IS_PCI_LPC (&PciConfigHeader) )) { + + PciConfigHeader.Hdr.Command |=3D 0x1f; + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 4, 1, &PciConfigHeader= .Hdr.Command); + } + } +} + +/** + The following routines are identical in operation, so combine + for code compaction: + EfiGetPlatformBinaryGetMpTable + EfiGetPlatformBinaryGetOemIntData + EfiGetPlatformBinaryGetOem32Data + EfiGetPlatformBinaryGetOem16Data + + @param This Protocol instance pointer. + @param Id Table/Data identifier + + @retval EFI_SUCCESS Success + @retval EFI_INVALID_PARAMETER Invalid ID + @retval EFI_OUT_OF_RESOURCES no resource to get data or table + +**/ +EFI_STATUS +LegacyGetDataOrTable ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_GET_PLATFORM_INFO_MODE Id + ) +{ + VOID *Table; + UINT32 TablePtr; + UINTN TableSize; + UINTN Alignment; + UINTN Location; + EFI_STATUS Status; + EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; + EFI_COMPATIBILITY16_TABLE *Legacy16Table; + EFI_IA32_REGISTER_SET Regs; + LEGACY_BIOS_INSTANCE *Private; + + Private =3D LEGACY_BIOS_INSTANCE_FROM_THIS (This); + + LegacyBiosPlatform =3D Private->LegacyBiosPlatform; + Legacy16Table =3D Private->Legacy16Table; + + // + // Phase 1 - get an address allocated in 16-bit code + // + while (TRUE) { + switch (Id) { + case EfiGetPlatformBinaryMpTable: + case EfiGetPlatformBinaryOemIntData: + case EfiGetPlatformBinaryOem32Data: + case EfiGetPlatformBinaryOem16Data: + { + Status =3D LegacyBiosPlatform->GetPlatformInfo ( + LegacyBiosPlatform, + Id, + (VOID *) &Table, + &TableSize, + &Location, + &Alignment, + 0, + 0 + ); + DEBUG ((EFI_D_INFO, "LegacyGetDataOrTable - ID: %x, %r\n", (UINTN)= Id, Status)); + DEBUG ((EFI_D_INFO, " Table - %x, Size - %x, Location - %x, Align= ment - %x\n", (UINTN)Table, (UINTN)TableSize, (UINTN)Location, (UINTN)Align= ment)); + break; + } + + default: + { + return EFI_INVALID_PARAMETER; + } + } + + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX =3D Legacy16GetTableAddress; + Regs.X.CX =3D (UINT16) TableSize; + Regs.X.BX =3D (UINT16) Location; + Regs.X.DX =3D (UINT16) Alignment; + Private->LegacyBios.FarCall86 ( + This, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + + if (Regs.X.AX !=3D 0) { + DEBUG ((EFI_D_ERROR, "Table ID %x length insufficient\n", Id)); + return EFI_OUT_OF_RESOURCES; + } else { + break; + } + } + // + // Phase 2 Call routine second time with address to allow address adjust= ment + // + Status =3D LegacyBiosPlatform->GetPlatformInfo ( + LegacyBiosPlatform, + Id, + (VOID *) &Table, + &TableSize, + &Location, + &Alignment, + Regs.X.DS, + Regs.X.BX + ); + switch (Id) { + case EfiGetPlatformBinaryMpTable: + { + Legacy16Table->MpTablePtr =3D (UINT32) (Regs.X.DS * 16 + Regs.X.= BX); + Legacy16Table->MpTableLength =3D (UINT32)TableSize; + DEBUG ((EFI_D_INFO, "MP table in legacy region - %x\n", (UINTN)Legac= y16Table->MpTablePtr)); + break; + } + + case EfiGetPlatformBinaryOemIntData: + { + + Legacy16Table->OemIntSegment =3D Regs.X.DS; + Legacy16Table->OemIntOffset =3D Regs.X.BX; + DEBUG ((EFI_D_INFO, "OemInt table in legacy region - %04x:%04x\n", (= UINTN)Legacy16Table->OemIntSegment, (UINTN)Legacy16Table->OemIntOffset)); + break; + } + + case EfiGetPlatformBinaryOem32Data: + { + Legacy16Table->Oem32Segment =3D Regs.X.DS; + Legacy16Table->Oem32Offset =3D Regs.X.BX; + DEBUG ((EFI_D_INFO, "Oem32 table in legacy region - %04x:%04x\n", (U= INTN)Legacy16Table->Oem32Segment, (UINTN)Legacy16Table->Oem32Offset)); + break; + } + + case EfiGetPlatformBinaryOem16Data: + { + // + // Legacy16Table->Oem16Segment =3D Regs.X.DS; + // Legacy16Table->Oem16Offset =3D Regs.X.BX; + DEBUG ((EFI_D_INFO, "Oem16 table in legacy region - %04x:%04x\n", (U= INTN)Legacy16Table->Oem16Segment, (UINTN)Legacy16Table->Oem16Offset)); + break; + } + + default: + { + return EFI_INVALID_PARAMETER; + } + } + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Phase 3 Copy table to final location + // + TablePtr =3D (UINT32) (Regs.X.DS * 16 + Regs.X.BX); + + CopyMem ( + (VOID *) (UINTN)TablePtr, + Table, + TableSize + ); + + return EFI_SUCCESS; +} + +/** + Copy SMBIOS table to EfiReservedMemoryType of memory for legacy boot. + +**/ +VOID +CreateSmbiosTableInReservedMemory ( + VOID + ) +{ + SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure; + + if ((mRuntimeSmbiosEntryPoint =3D=3D NULL) || + (mReserveSmbiosEntryPoint =3D=3D 0) || + (mStructureTableAddress =3D=3D 0)) { + return; + } + + EntryPointStructure =3D (SMBIOS_TABLE_ENTRY_POINT *) mRuntimeSmbiosEntry= Point; + + // + // Copy SMBIOS Entry Point Structure + // + CopyMem ( + (VOID *)(UINTN) mReserveSmbiosEntryPoint, + EntryPointStructure, + EntryPointStructure->EntryPointLength + ); + + // + // Copy SMBIOS Structure Table into EfiReservedMemoryType memory + // + CopyMem ( + (VOID *)(UINTN) mStructureTableAddress, + (VOID *)(UINTN) EntryPointStructure->TableAddress, + EntryPointStructure->TableLength + ); + + // + // Update TableAddress in Entry Point Structure + // + EntryPointStructure =3D (SMBIOS_TABLE_ENTRY_POINT *)(UINTN) mReserveSmbi= osEntryPoint; + EntryPointStructure->TableAddress =3D (UINT32)(UINTN) mStructureTableAdd= ress; + + // + // Fixup checksums in the Entry Point Structure + // + EntryPointStructure->IntermediateChecksum =3D 0; + EntryPointStructure->EntryPointStructureChecksum =3D 0; + + EntryPointStructure->IntermediateChecksum =3D + CalculateCheckSum8 ( + (UINT8 *) EntryPointStructure + OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT,= IntermediateAnchorString), + EntryPointStructure->EntryPointLength - OFFSET_OF (SMBIOS_TABLE_ENTR= Y_POINT, IntermediateAnchorString) + ); + EntryPointStructure->EntryPointStructureChecksum =3D + CalculateCheckSum8 ((UINT8 *) EntryPointStructure, EntryPointStructure= ->EntryPointLength); +} + +/** + Assign drive number to legacy HDD drives prior to booting an EFI + aware OS so the OS can access drives without an EFI driver. + Note: BBS compliant drives ARE NOT available until this call by + either shell or EFI. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS Drive numbers assigned + +**/ +EFI_STATUS +GenericLegacyBoot ( + IN EFI_LEGACY_BIOS_PROTOCOL *This + ) +{ + EFI_STATUS Status; + LEGACY_BIOS_INSTANCE *Private; + EFI_IA32_REGISTER_SET Regs; + EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; + EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; + UINTN CopySize; + VOID *AcpiPtr; + HDD_INFO *HddInfo; + HDD_INFO *LocalHddInfo; + UINTN Index; + EFI_COMPATIBILITY16_TABLE *Legacy16Table; + UINT32 *BdaPtr; + UINT16 HddCount; + UINT16 BbsCount; + BBS_TABLE *LocalBbsTable; + UINT32 *BaseVectorMaster; + EFI_TIME BootTime; + UINT32 LocalTime; + EFI_HANDLE IdeController; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + VOID *AcpiTable; + UINTN ShadowAddress; + UINT32 Granularity; + + LocalHddInfo =3D NULL; + HddCount =3D 0; + BbsCount =3D 0; + LocalBbsTable =3D NULL; + + Private =3D LEGACY_BIOS_INSTANCE_FROM_THIS (This); + DEBUG_CODE ( + DEBUG ((EFI_D_ERROR, "Start of legacy boot\n")); + ); + + Legacy16Table =3D Private->Legacy16Table; + EfiToLegacy16BootTable =3D &Private->IntThunk->EfiToLegac= y16BootTable; + HddInfo =3D &EfiToLegacy16BootTable->HddInfo[0]; + + LegacyBiosPlatform =3D Private->LegacyBiosPlatform; + + EfiToLegacy16BootTable->MajorVersion =3D EFI_TO_LEGACY_MAJOR_VERSION; + EfiToLegacy16BootTable->MinorVersion =3D EFI_TO_LEGACY_MINOR_VERSION; + + // + // If booting to a legacy OS then force HDD drives to the appropriate + // boot mode by calling GetIdeHandle. + // A reconnect -r can force all HDDs back to native mode. + // + IdeController =3D NULL; + if ((mBootMode =3D=3D BOOT_LEGACY_OS) || (mBootMode =3D=3D BOOT_UNCONVEN= TIONAL_DEVICE)) { + Status =3D LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformIdeHandle, + 0, + &HandleBuffer, + &HandleCount, + NULL + ); + if (!EFI_ERROR (Status)) { + IdeController =3D HandleBuffer[0]; + } + } + // + // Unlock the Legacy BIOS region + // + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + + // + // Reconstruct the Legacy16 boot memory map + // + LegacyBiosBuildE820 (Private, &CopySize); + if (CopySize > Private->Legacy16Table->E820Length) { + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX =3D Legacy16GetTableAddress; + Regs.X.CX =3D (UINT16) CopySize; + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Private->Legacy16Table->Compatibility16CallSegment, + Private->Legacy16Table->Compatibility16CallOffset, + &Regs, + NULL, + 0 + ); + + Private->Legacy16Table->E820Pointer =3D (UINT32) (Regs.X.DS * 16 + Reg= s.X.BX); + Private->Legacy16Table->E820Length =3D (UINT32) CopySize; + if (Regs.X.AX !=3D 0) { + DEBUG ((EFI_D_ERROR, "Legacy16 E820 length insufficient\n")); + } else { + CopyMem ( + (VOID *)(UINTN) Private->Legacy16Table->E820Pointer, + Private->E820Table, + CopySize + ); + } + } else { + CopyMem ( + (VOID *)(UINTN) Private->Legacy16Table->E820Pointer, + Private->E820Table, + CopySize + ); + Private->Legacy16Table->E820Length =3D (UINT32) CopySize; + } + + // + // We do not ASSERT if SmbiosTable not found. It is possbile that a plat= form does not produce SmbiosTable. + // + if (mReserveSmbiosEntryPoint =3D=3D 0) { + DEBUG ((EFI_D_INFO, "Smbios table is not found!\n")); + } + CreateSmbiosTableInReservedMemory (); + EfiToLegacy16BootTable->SmbiosTable =3D (UINT32)(UINTN)mReserveSmbiosEnt= ryPoint; + + AcpiTable =3D NULL; + Status =3D EfiGetSystemConfigurationTable ( + &gEfiAcpi20TableGuid, + &AcpiTable + ); + if (EFI_ERROR (Status)) { + Status =3D EfiGetSystemConfigurationTable ( + &gEfiAcpi10TableGuid, + &AcpiTable + ); + } + // + // We do not ASSERT if AcpiTable not found. It is possbile that a platfo= rm does not produce AcpiTable. + // + if (AcpiTable =3D=3D NULL) { + DEBUG ((EFI_D_INFO, "ACPI table is not found!\n")); + } + EfiToLegacy16BootTable->AcpiTable =3D (UINT32)(UINTN)AcpiTable; + + // + // Get RSD Ptr table rev at offset 15 decimal + // Rev =3D 0 Length is 20 decimal + // Rev !=3D 0 Length is UINT32 at offset 20 decimal + // + if (AcpiTable !=3D NULL) { + + AcpiPtr =3D AcpiTable; + if (*((UINT8 *) AcpiPtr + 15) =3D=3D 0) { + CopySize =3D 20; + } else { + AcpiPtr =3D ((UINT8 *) AcpiPtr + 20); + CopySize =3D (*(UINT32 *) AcpiPtr); + } + + CopyMem ( + (VOID *)(UINTN) Private->Legacy16Table->AcpiRsdPtrPointer, + AcpiTable, + CopySize + ); + } + // + // Make sure all PCI Interrupt Line register are programmed to match 8259 + // + PciProgramAllInterruptLineRegisters (Private); + + // + // Unlock the Legacy BIOS region as PciProgramAllInterruptLineRegisters + // can lock it. + // + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + Private->BiosStart, + Private->LegacyBiosImageSize, + &Granularity + ); + + // + // Configure Legacy Device Magic + // + // Only do this code if booting legacy OS + // + if ((mBootMode =3D=3D BOOT_LEGACY_OS) || (mBootMode =3D=3D BOOT_UNCONVEN= TIONAL_DEVICE)) { + UpdateSioData (Private); + } + // + // Setup BDA and EBDA standard areas before Legacy Boot + // + ACCESS_PAGE0_CODE ( + LegacyBiosCompleteBdaBeforeBoot (Private); + ); + LegacyBiosCompleteStandardCmosBeforeBoot (Private); + + // + // We must build IDE data, if it hasn't been done, before PciShadowRoms + // to insure EFI drivers are connected. + // + LegacyBiosBuildIdeData (Private, &HddInfo, 1); + UpdateAllIdentifyDriveData (Private); + + // + // Clear IO BAR, if IDE controller in legacy mode. + // + InitLegacyIdeController (IdeController); + + // + // Generate number of ticks since midnight for BDA. DOS requires this + // for its time. We have to make assumptions as to how long following + // code takes since after PciShadowRoms PciIo is gone. Place result in + // 40:6C-6F + // + // Adjust value by 1 second. + // + gRT->GetTime (&BootTime, NULL); + LocalTime =3D BootTime.Hour * 3600 + BootTime.Minute * 60 + BootTime.Sec= ond; + LocalTime +=3D 1; + + // + // Multiply result by 18.2 for number of ticks since midnight. + // Use 182/10 to avoid floating point math. + // + LocalTime =3D (LocalTime * 182) / 10; + ACCESS_PAGE0_CODE ( + BdaPtr =3D (UINT32 *) (UINTN)0x46C; + *BdaPtr =3D LocalTime; + ); + + // + // Shadow PCI ROMs. We must do this near the end since this will kick + // of Native EFI drivers that may be needed to collect info for Legacy16 + // + // WARNING: PciIo is gone after this call. + // + PciShadowRoms (Private); + + // + // Shadow PXE base code, BIS etc. + // + Private->LegacyRegion->UnLock (Private->LegacyRegion, 0xc0000, 0x40000, = &Granularity); + ShadowAddress =3D Private->OptionRom; + Private->LegacyBiosPlatform->PlatformHooks ( + Private->LegacyBiosPlatform, + EfiPlatformHookShadowServiceRoms, + 0, + 0, + &ShadowAddress, + Legacy16Table, + NULL + ); + Private->OptionRom =3D (UINT32)ShadowAddress; + // + // Register Legacy SMI Handler + // + LegacyBiosPlatform->SmmInit ( + LegacyBiosPlatform, + EfiToLegacy16BootTable + ); + + // + // Let platform code know the boot options + // + LegacyBiosGetBbsInfo ( + This, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + + DEBUG_CODE ( + PrintPciInterruptRegister (); + PrintBbsTable (LocalBbsTable); + PrintHddInfo (LocalHddInfo); + ); + // + // If drive wasn't spun up then BuildIdeData may have found new drives. + // Need to update BBS boot priority. + // + for (Index =3D 0; Index < MAX_IDE_CONTROLLER; Index++) { + if ((LocalHddInfo[Index].IdentifyDrive[0].Raw[0] !=3D 0) && + (LocalBbsTable[2 * Index + 1].BootPriority =3D=3D BBS_IGNORE_ENTRY) + ) { + LocalBbsTable[2 * Index + 1].BootPriority =3D BBS_UNPRIORITIZED_ENTR= Y; + } + + if ((LocalHddInfo[Index].IdentifyDrive[1].Raw[0] !=3D 0) && + (LocalBbsTable[2 * Index + 2].BootPriority =3D=3D BBS_IGNORE_ENTRY) + ) { + LocalBbsTable[2 * Index + 2].BootPriority =3D BBS_UNPRIORITIZED_ENTR= Y; + } + } + + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + 0xc0000, + 0x40000, + &Granularity + ); + + LegacyBiosPlatform->PrepareToBoot ( + LegacyBiosPlatform, + mBbsDevicePathPtr, + mBbsTable, + mLoadOptionsSize, + mLoadOptions, + (VOID *) &Private->IntThunk->EfiToLegacy16BootTable + ); + + // + // If no boot device return to BDS + // + if ((mBootMode =3D=3D BOOT_LEGACY_OS) || (mBootMode =3D=3D BOOT_UNCONVEN= TIONAL_DEVICE)) { + for (Index =3D 0; Index < BbsCount; Index++){ + if ((LocalBbsTable[Index].BootPriority !=3D BBS_DO_NOT_BOOT_FROM) && + (LocalBbsTable[Index].BootPriority !=3D BBS_UNPRIORITIZED_ENTRY)= && + (LocalBbsTable[Index].BootPriority !=3D BBS_IGNORE_ENTRY)) { + break; + } + } + if (Index =3D=3D BbsCount) { + return EFI_DEVICE_ERROR; + } + } + // + // Let the Legacy16 code know the device path type for legacy boot + // + EfiToLegacy16BootTable->DevicePathType =3D mBbsDevicePathPtr->DeviceType; + + // + // Copy MP table, if it exists. + // + LegacyGetDataOrTable (This, EfiGetPlatformBinaryMpTable); + + if (!Private->LegacyBootEntered) { + // + // Copy OEM INT Data, if it exists. Note: This code treats any data + // as a bag of bits and knows nothing of the contents nor cares. + // Contents are IBV specific. + // + LegacyGetDataOrTable (This, EfiGetPlatformBinaryOemIntData); + + // + // Copy OEM16 Data, if it exists.Note: This code treats any data + // as a bag of bits and knows nothing of the contents nor cares. + // Contents are IBV specific. + // + LegacyGetDataOrTable (This, EfiGetPlatformBinaryOem16Data); + + // + // Copy OEM32 Data, if it exists.Note: This code treats any data + // as a bag of bits and knows nothing of the contents nor cares. + // Contents are IBV specific. + // + LegacyGetDataOrTable (This, EfiGetPlatformBinaryOem32Data); + } + + // + // Call into Legacy16 code to prepare for INT 19h + // + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX =3D Legacy16PrepareToBoot; + + // + // Pass in handoff data + // + Regs.X.ES =3D NORMALIZE_EFI_SEGMENT ((UINTN)EfiToLegacy16BootTable); + Regs.X.BX =3D NORMALIZE_EFI_OFFSET ((UINTN)EfiToLegacy16BootTable); + + Private->LegacyBios.FarCall86 ( + This, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + + if (Regs.X.AX !=3D 0) { + return EFI_DEVICE_ERROR; + } + // + // Lock the Legacy BIOS region + // + Private->LegacyRegion->Lock ( + Private->LegacyRegion, + 0xc0000, + 0x40000, + &Granularity + ); + + if ((Private->Legacy16Table->TableLength >=3D OFFSET_OF (EFI_COMPATIBILI= TY16_TABLE, HiPermanentMemoryAddress)) && + ((Private->Legacy16Table->UmaAddress !=3D 0) && (Private->Legacy16Ta= ble->UmaSize !=3D 0))) { + // + // Here we could reduce UmaAddress down as far as Private->OptionRom, = taking into + // account the granularity of the access control. + // + DEBUG((EFI_D_INFO, "Unlocking UMB RAM region 0x%x-0x%x\n", Private->Le= gacy16Table->UmaAddress, + Private->Legacy16Table->UmaAddress + Private->Lega= cy16Table->UmaSize)); + + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + Private->Legacy16Table->UmaAddress, + Private->Legacy16Table->UmaSize, + &Granularity + ); + } + + // + // Lock attributes of the Legacy Region if chipset supports + // + Private->LegacyRegion->BootLock ( + Private->LegacyRegion, + 0xc0000, + 0x40000, + &Granularity + ); + + // + // Call into Legacy16 code to do the INT 19h + // + EnableAllControllers (Private); + if ((mBootMode =3D=3D BOOT_LEGACY_OS) || (mBootMode =3D=3D BOOT_UNCONVEN= TIONAL_DEVICE)) { + + // + // Signal all the events that are waiting on EVT_SIGNAL_LEGACY_BOOT + // + EfiSignalEventLegacyBoot (); + + // + // Report Status Code to indicate legacy boot event was signalled + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_LEGACY_BOOT_EVENT) + ); + + DEBUG ((EFI_D_INFO, "Legacy INT19 Boot...\n")); + + // + // Disable DXE Timer while executing in real mode + // + Private->Timer->SetTimerPeriod (Private->Timer, 0); + + // + // Save and disable interrupt of debug timer + // + SaveAndSetDebugTimerInterrupt (FALSE); + + + // + // Put the 8259 into its legacy mode by reprogramming the vector bases + // + Private->Legacy8259->SetVectorBase (Private->Legacy8259, LEGACY_MODE_B= ASE_VECTOR_MASTER, LEGACY_MODE_BASE_VECTOR_SLAVE); + // + // PC History + // The original PC used INT8-F for master PIC. Since these mapped ov= er + // processor exceptions TIANO moved the master PIC to INT68-6F. + // We need to set these back to the Legacy16 unexpected interrupt(saved + // in LegacyBios.c) since some OS see that these have values different= from + // what is expected and invoke them. Since the legacy OS corrupts EFI + // memory, there is no handler for these interrupts and OS blows up. + // + // We need to save the TIANO values for the rare case that the Legacy16 + // code cannot boot but knows memory hasn't been destroyed. + // + // To compound the problem, video takes over one of these INTS and mus= t be + // be left. + // @bug - determine if video hooks INT(in which case we must find new + // set of TIANO vectors) or takes it over. + // + // + ACCESS_PAGE0_CODE ( + BaseVectorMaster =3D (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BA= SE_VECTOR_MASTER); + for (Index =3D 0; Index < 8; Index++) { + Private->ThunkSavedInt[Index] =3D BaseVectorMaster[Index]; + if (Private->ThunkSeg =3D=3D (UINT16) (BaseVectorMaster[Index] >> = 16)) { + BaseVectorMaster[Index] =3D (UINT32) (Private->BiosUnexpectedInt= ); + } + } + ); + + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX =3D Legacy16Boot; + + Private->LegacyBios.FarCall86 ( + This, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + + ACCESS_PAGE0_CODE ( + BaseVectorMaster =3D (UINT32 *) (sizeof (UINT32) * PROTECTED_MODE_BA= SE_VECTOR_MASTER); + for (Index =3D 0; Index < 8; Index++) { + BaseVectorMaster[Index] =3D Private->ThunkSavedInt[Index]; + } + ); + } + Private->LegacyBootEntered =3D TRUE; + if ((mBootMode =3D=3D BOOT_LEGACY_OS) || (mBootMode =3D=3D BOOT_UNCONVEN= TIONAL_DEVICE)) { + // + // Should never return unless never passed control to 0:7c00(first sta= ge + // OS loader) and only then if no bootable device found. + // + return EFI_DEVICE_ERROR; + } else { + // + // If boot to EFI then expect to return to caller + // + return EFI_SUCCESS; + } +} + + +/** + Assign drive number to legacy HDD drives prior to booting an EFI + aware OS so the OS can access drives without an EFI driver. + Note: BBS compliant drives ARE NOT available until this call by + either shell or EFI. + + @param This Protocol instance pointer. + @param BbsCount Number of BBS_TABLE structures + @param BbsTable List BBS entries + + @retval EFI_SUCCESS Drive numbers assigned + +**/ +EFI_STATUS +EFIAPI +LegacyBiosPrepareToBootEfi ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *BbsCount, + OUT BBS_TABLE **BbsTable + ) +{ + EFI_STATUS Status; + EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; + LEGACY_BIOS_INSTANCE *Private; + + Private =3D LEGACY_BIOS_INSTANCE_FROM_THIS (This); + EfiToLegacy16BootTable =3D &Private->IntThunk->EfiToLegacy16BootTable; + mBootMode =3D BOOT_EFI_OS; + mBbsDevicePathPtr =3D NULL; + Status =3D GenericLegacyBoot (This); + *BbsTable =3D (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->B= bsTable; + *BbsCount =3D (UINT16) (sizeof (Private->IntThunk->BbsTabl= e) / sizeof (BBS_TABLE)); + return Status; +} + +/** + To boot from an unconventional device like parties and/or execute HDD di= agnostics. + + @param This Protocol instance pointer. + @param Attributes How to interpret the other input parameters + @param BbsEntry The 0-based index into the BbsTable for the pare= nt + device. + @param BeerData Pointer to the 128 bytes of ram BEER data. + @param ServiceAreaData Pointer to the 64 bytes of raw Service Area data= . The + caller must provide a pointer to the specific Se= rvice + Area and not the start all Service Areas. + + @retval EFI_INVALID_PARAMETER if error. Does NOT return if no error. + +***/ +EFI_STATUS +EFIAPI +LegacyBiosBootUnconventionalDevice ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UDC_ATTRIBUTES Attributes, + IN UINTN BbsEntry, + IN VOID *BeerData, + IN VOID *ServiceAreaData + ) +{ + EFI_STATUS Status; + EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable; + LEGACY_BIOS_INSTANCE *Private; + UD_TABLE *UcdTable; + UINTN Index; + UINT16 BootPriority; + BBS_TABLE *BbsTable; + + BootPriority =3D 0; + Private =3D LEGACY_BIOS_INSTANCE_FROM_THIS (This); + mBootMode =3D BOOT_UNCONVENTIONAL_DEVICE; + mBbsDevicePathPtr =3D &mBbsDevicePathNode; + mAttributes =3D Attributes; + mBbsEntry =3D BbsEntry; + mBeerData =3D BeerData, mServiceAreaData =3D ServiceAreaData; + + EfiToLegacy16BootTable =3D &Private->IntThunk->EfiToLegacy16BootTable; + + // + // Do input parameter checking + // + if ((Attributes.DirectoryServiceValidity =3D=3D 0) && + (Attributes.RabcaUsedFlag =3D=3D 0) && + (Attributes.ExecuteHddDiagnosticsFlag =3D=3D 0) + ) { + return EFI_INVALID_PARAMETER; + } + + if (((Attributes.DirectoryServiceValidity !=3D 0) && (ServiceAreaData = =3D=3D NULL)) || + (((Attributes.DirectoryServiceValidity | Attributes.RabcaUsedFlag) != =3D 0) && (BeerData =3D=3D NULL)) + ) { + return EFI_INVALID_PARAMETER; + } + + UcdTable =3D (UD_TABLE *) AllocatePool ( + sizeof (UD_TABLE) + ); + if (NULL =3D=3D UcdTable) { + return EFI_OUT_OF_RESOURCES; + } + + EfiToLegacy16BootTable->UnconventionalDeviceTable =3D (UINT32)(UINTN)Ucd= Table; + UcdTable->Attributes =3D Attributes; + UcdTable->BbsTableEntryNumberForParentDevice =3D (UINT8) BbsEntry; + // + // Force all existing BBS entries to DoNotBoot. This allows 16-bit CSM + // to assign drive numbers but bot boot from. Only newly created entries + // will be valid. + // + BbsTable =3D (BBS_TABLE*)(UINTN)EfiToLegacy16BootTable->BbsTable; + for (Index =3D 0; Index < EfiToLegacy16BootTable->NumberBbsEntries; Inde= x++) { + BbsTable[Index].BootPriority =3D BBS_DO_NOT_BOOT_FROM; + } + // + // If parent is onboard IDE then assign controller & device number + // else they are 0. + // + if (BbsEntry < MAX_IDE_CONTROLLER * 2) { + UcdTable->DeviceNumber =3D (UINT8) ((BbsEntry - 1) % 2); + } + + if (BeerData !=3D NULL) { + CopyMem ( + (VOID *) UcdTable->BeerData, + BeerData, + (UINTN) 128 + ); + } + + if (ServiceAreaData !=3D NULL) { + CopyMem ( + (VOID *) UcdTable->ServiceAreaData, + ServiceAreaData, + (UINTN) 64 + ); + } + // + // For each new entry do the following: + // 1. Increment current number of BBS entries + // 2. Copy parent entry to new entry. + // 3. Zero out BootHandler Offset & segment + // 4. Set appropriate device type. BEV(0x80) for HDD diagnostics + // and Floppy(0x01) for PARTIES boot. + // 5. Assign new priority. + // + if ((Attributes.ExecuteHddDiagnosticsFlag) !=3D 0) { + EfiToLegacy16BootTable->NumberBbsEntries +=3D 1; + + CopyMem ( + (VOID *) &BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPri= ority, + (VOID *) &BbsTable[BbsEntry].BootPriority, + sizeof (BBS_TABLE) + ); + + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerOffset = =3D 0; + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerSegment = =3D 0; + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].DeviceType = =3D 0x80; + + UcdTable->BbsTableEntryNumberForHddDiag =3D (UINT8) (EfiToLegacy16Boot= Table->NumberBbsEntries - 1); + + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority =3D Bo= otPriority; + BootPriority +=3D 1; + + // + // Set device type as BBS_TYPE_DEV for PARTIES diagnostic + // + mBbsDevicePathNode.DeviceType =3D BBS_TYPE_BEV; + } + + if (((Attributes.DirectoryServiceValidity | Attributes.RabcaUsedFlag)) != =3D 0) { + EfiToLegacy16BootTable->NumberBbsEntries +=3D 1; + CopyMem ( + (VOID *) &BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPri= ority, + (VOID *) &BbsTable[BbsEntry].BootPriority, + sizeof (BBS_TABLE) + ); + + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerOffset = =3D 0; + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootHandlerSegment = =3D 0; + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].DeviceType = =3D 0x01; + UcdTable->BbsTableEntryNumberForBoot =3D (UINT8) (EfiToLegacy16BootTab= le->NumberBbsEntries - 1); + BbsTable[EfiToLegacy16BootTable->NumberBbsEntries].BootPriority =3D Bo= otPriority; + + // + // Set device type as BBS_TYPE_FLOPPY for PARTIES boot as floppy + // + mBbsDevicePathNode.DeviceType =3D BBS_TYPE_FLOPPY; + } + // + // Build the BBS Device Path for this boot selection + // + mBbsDevicePathNode.Header.Type =3D BBS_DEVICE_PATH; + mBbsDevicePathNode.Header.SubType =3D BBS_BBS_DP; + SetDevicePathNodeLength (&mBbsDevicePathNode.Header, sizeof (BBS_BBS_DEV= ICE_PATH)); + mBbsDevicePathNode.StatusFlag =3D 0; + mBbsDevicePathNode.String[0] =3D 0; + + Status =3D GenericLegacyBoot (This); + return Status; +} + +/** + Attempt to legacy boot the BootOption. If the EFI contexted has been + compromised this function will not return. + + @param This Protocol instance pointer. + @param BbsDevicePath EFI Device Path from BootXXXX variable. + @param LoadOptionsSize Size of LoadOption in size. + @param LoadOptions LoadOption from BootXXXX variable + + @retval EFI_SUCCESS Removable media not present + +**/ +EFI_STATUS +EFIAPI +LegacyBiosLegacyBoot ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN BBS_BBS_DEVICE_PATH *BbsDevicePath, + IN UINT32 LoadOptionsSize, + IN VOID *LoadOptions + ) +{ + EFI_STATUS Status; + + mBbsDevicePathPtr =3D BbsDevicePath; + mLoadOptionsSize =3D LoadOptionsSize; + mLoadOptions =3D LoadOptions; + mBootMode =3D BOOT_LEGACY_OS; + Status =3D GenericLegacyBoot (This); + + return Status; +} + +/** + Convert EFI Memory Type to E820 Memory Type. + + @param Type EFI Memory Type + + @return ACPI Memory Type for EFI Memory Type + +**/ +EFI_ACPI_MEMORY_TYPE +EfiMemoryTypeToE820Type ( + IN UINT32 Type + ) +{ + switch (Type) { + case EfiLoaderCode: + case EfiLoaderData: + case EfiBootServicesCode: + case EfiBootServicesData: + case EfiConventionalMemory: + // + // The memory of EfiRuntimeServicesCode and EfiRuntimeServicesData are + // usable memory for legacy OS, because legacy OS is not aware of EFI ru= ntime concept. + // In ACPI specification, EfiRuntimeServiceCode and EfiRuntimeServiceData + // should be mapped to AddressRangeReserved. This statement is for UEFI = OS, not for legacy OS. + // + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + return EfiAcpiAddressRangeMemory; + + case EfiPersistentMemory: + return EfiAddressRangePersistentMemory; + + case EfiACPIReclaimMemory: + return EfiAcpiAddressRangeACPI; + + case EfiACPIMemoryNVS: + return EfiAcpiAddressRangeNVS; + + // + // All other types map to reserved. + // Adding the code just waists FLASH space. + // + // case EfiReservedMemoryType: + // case EfiUnusableMemory: + // case EfiMemoryMappedIO: + // case EfiMemoryMappedIOPortSpace: + // case EfiPalCode: + // + default: + return EfiAcpiAddressRangeReserved; + } +} + +/** + Build the E820 table. + + @param Private Legacy BIOS Instance data + @param Size Size of E820 Table + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosBuildE820 ( + IN LEGACY_BIOS_INSTANCE *Private, + OUT UINTN *Size + ) +{ + EFI_STATUS Status; + EFI_E820_ENTRY64 *E820Table; + EFI_MEMORY_DESCRIPTOR *EfiMemoryMap; + EFI_MEMORY_DESCRIPTOR *EfiMemoryMapEnd; + EFI_MEMORY_DESCRIPTOR *EfiEntry; + EFI_MEMORY_DESCRIPTOR *NextEfiEntry; + EFI_MEMORY_DESCRIPTOR TempEfiEntry; + UINTN EfiMemoryMapSize; + UINTN EfiMapKey; + UINTN EfiDescriptorSize; + UINT32 EfiDescriptorVersion; + UINTN Index; + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + UINTN TempIndex; + UINTN IndexSort; + UINTN TempNextIndex; + EFI_E820_ENTRY64 TempE820; + EFI_ACPI_MEMORY_TYPE TempType; + BOOLEAN ChangedFlag; + UINTN Above1MIndex; + UINT64 MemoryBlockLength; + + E820Table =3D (EFI_E820_ENTRY64 *) Private->E820Table; + + // + // Get the EFI memory map. + // + EfiMemoryMapSize =3D 0; + EfiMemoryMap =3D NULL; + Status =3D gBS->GetMemoryMap ( + &EfiMemoryMapSize, + EfiMemoryMap, + &EfiMapKey, + &EfiDescriptorSize, + &EfiDescriptorVersion + ); + ASSERT (Status =3D=3D EFI_BUFFER_TOO_SMALL); + + do { + // + // Use size returned for the AllocatePool. + // We don't just multiply by 2 since the "for" loop below terminates on + // EfiMemoryMapEnd which is dependent upon EfiMemoryMapSize. Otherwise + // we process bogus entries and create bogus E820 entries. + // + EfiMemoryMap =3D (EFI_MEMORY_DESCRIPTOR *) AllocatePool (EfiMemoryMapS= ize); + ASSERT (EfiMemoryMap !=3D NULL); + Status =3D gBS->GetMemoryMap ( + &EfiMemoryMapSize, + EfiMemoryMap, + &EfiMapKey, + &EfiDescriptorSize, + &EfiDescriptorVersion + ); + if (EFI_ERROR (Status)) { + FreePool (EfiMemoryMap); + } + } while (Status =3D=3D EFI_BUFFER_TOO_SMALL); + + ASSERT_EFI_ERROR (Status); + + // + // Punch in the E820 table for memory less than 1 MB. + // Assume ZeroMem () has been done on data structure. + // + // + // First entry is 0 to (640k - EBDA) + // + ACCESS_PAGE0_CODE ( + E820Table[0].BaseAddr =3D 0; + E820Table[0].Length =3D (UINT64) ((*(UINT16 *) (UINTN)0x40E) << 4); + E820Table[0].Type =3D EfiAcpiAddressRangeMemory; + ); + + // + // Second entry is (640k - EBDA) to 640k + // + E820Table[1].BaseAddr =3D E820Table[0].Length; + E820Table[1].Length =3D (UINT64) ((640 * 1024) - E820Table[0].Length); + E820Table[1].Type =3D EfiAcpiAddressRangeReserved; + + // + // Third Entry is legacy BIOS + // DO NOT CLAIM region from 0xA0000-0xDFFFF. OS can use free areas + // to page in memory under 1MB. + // Omit region from 0xE0000 to start of BIOS, if any. This can be + // used for a multiple reasons including OPROMS. + // + + // + // The CSM binary image size is not the actually size that CSM binary us= ed, + // to avoid memory corrupt, we declare the 0E0000 - 0FFFFF is used by CS= M binary. + // + E820Table[2].BaseAddr =3D 0xE0000; + E820Table[2].Length =3D 0x20000; + E820Table[2].Type =3D EfiAcpiAddressRangeReserved; + + Above1MIndex =3D 2; + + // + // Process the EFI map to produce E820 map; + // + + // + // Sort memory map from low to high + // + EfiEntry =3D EfiMemoryMap; + NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize); + EfiMemoryMapEnd =3D (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + = EfiMemoryMapSize); + while (EfiEntry < EfiMemoryMapEnd) { + while (NextEfiEntry < EfiMemoryMapEnd) { + if (EfiEntry->PhysicalStart > NextEfiEntry->PhysicalStart) { + CopyMem (&TempEfiEntry, EfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR)); + CopyMem (EfiEntry, NextEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR)); + CopyMem (NextEfiEntry, &TempEfiEntry, sizeof (EFI_MEMORY_DESCRIPTO= R)); + } + + NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (NextEfiEntry, EfiDescriptor= Size); + } + + EfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize); + NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize); + } + + EfiEntry =3D EfiMemoryMap; + EfiMemoryMapEnd =3D (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + = EfiMemoryMapSize); + for (Index =3D Above1MIndex; (EfiEntry < EfiMemoryMapEnd) && (Index < EF= I_MAX_E820_ENTRY - 1); ) { + MemoryBlockLength =3D (UINT64) (LShiftU64 (EfiEntry->NumberOfPages, 12= )); + if ((EfiEntry->PhysicalStart + MemoryBlockLength) < 0x100000) { + // + // Skip the memory block if under 1MB + // + } else { + if (EfiEntry->PhysicalStart < 0x100000) { + // + // When the memory block spans below 1MB, ensure the memory block = start address is at least 1MB + // + MemoryBlockLength -=3D 0x100000 - EfiEntry->PhysicalStart; + EfiEntry->PhysicalStart =3D 0x100000; + } + + // + // Convert memory type to E820 type + // + TempType =3D EfiMemoryTypeToE820Type (EfiEntry->Type); + + if ((E820Table[Index].Type =3D=3D TempType) && (EfiEntry->PhysicalSt= art =3D=3D (E820Table[Index].BaseAddr + E820Table[Index].Length))) { + // + // Grow an existing entry + // + E820Table[Index].Length +=3D MemoryBlockLength; + } else { + // + // Make a new entry + // + ++Index; + E820Table[Index].BaseAddr =3D EfiEntry->PhysicalStart; + E820Table[Index].Length =3D MemoryBlockLength; + E820Table[Index].Type =3D TempType; + } + } + EfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize); + } + + FreePool (EfiMemoryMap); + + // + // Process the reserved memory map to produce E820 map ; + // + for (Hob.Raw =3D GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw =3D GET_= NEXT_HOB (Hob)) { + if (Hob.Raw !=3D NULL && GET_HOB_TYPE (Hob) =3D=3D EFI_HOB_TYPE_RESOUR= CE_DESCRIPTOR) { + ResourceHob =3D Hob.ResourceDescriptor; + if (((ResourceHob->ResourceType =3D=3D EFI_RESOURCE_MEMORY_MAPPED_IO= ) || + (ResourceHob->ResourceType =3D=3D EFI_RESOURCE_FIRMWARE_DEVICE) = || + (ResourceHob->ResourceType =3D=3D EFI_RESOURCE_MEMORY_RESERVED) = ) && + (ResourceHob->PhysicalStart > 0x100000) && + (Index < EFI_MAX_E820_ENTRY - 1)) { + ++Index; + E820Table[Index].BaseAddr =3D ResourceHob->PhysicalStart; + E820Table[Index].Length =3D ResourceHob->ResourceLength; + E820Table[Index].Type =3D EfiAcpiAddressRangeReserved; + } + } + } + + Index ++; + Private->IntThunk->EfiToLegacy16InitTable.NumberE820Entries =3D (UINT32)= Index; + Private->IntThunk->EfiToLegacy16BootTable.NumberE820Entries =3D (UINT32)= Index; + Private->NumberE820Entries =3D (UINT32)Index; + *Size =3D (UINTN) (Index * sizeof (EFI_E820_ENTRY64)); + + // + // Sort E820Table from low to high + // + for (TempIndex =3D 0; TempIndex < Index; TempIndex++) { + ChangedFlag =3D FALSE; + for (TempNextIndex =3D 1; TempNextIndex < Index - TempIndex; TempNextI= ndex++) { + if (E820Table[TempNextIndex - 1].BaseAddr > E820Table[TempNextIndex]= .BaseAddr) { + ChangedFlag =3D TRUE; + TempE820.BaseAddr =3D E820Table[TempNextIndex - 1]= .BaseAddr; + TempE820.Length =3D E820Table[TempNextIndex - 1]= .Length; + TempE820.Type =3D E820Table[TempNextIndex - 1]= .Type; + + E820Table[TempNextIndex - 1].BaseAddr =3D E820Table[TempNextIndex= ].BaseAddr; + E820Table[TempNextIndex - 1].Length =3D E820Table[TempNextIndex= ].Length; + E820Table[TempNextIndex - 1].Type =3D E820Table[TempNextIndex= ].Type; + + E820Table[TempNextIndex].BaseAddr =3D TempE820.BaseAddr; + E820Table[TempNextIndex].Length =3D TempE820.Length; + E820Table[TempNextIndex].Type =3D TempE820.Type; + } + } + + if (!ChangedFlag) { + break; + } + } + + // + // Remove the overlap range + // + for (TempIndex =3D 1; TempIndex < Index; TempIndex++) { + if (E820Table[TempIndex - 1].BaseAddr <=3D E820Table[TempIndex].BaseAd= dr && + ((E820Table[TempIndex - 1].BaseAddr + E820Table[TempIndex - 1].Len= gth) >=3D + (E820Table[TempIndex].BaseAddr +E820Table[TempIndex].Length))) { + // + //Overlap range is found + // + ASSERT (E820Table[TempIndex - 1].Type =3D=3D E820Table[TempIndex].= Type); + + if (TempIndex =3D=3D Index - 1) { + E820Table[TempIndex].BaseAddr =3D 0; + E820Table[TempIndex].Length =3D 0; + E820Table[TempIndex].Type =3D (EFI_ACPI_MEMORY_TYPE) 0; + Index--; + break; + } else { + for (IndexSort =3D TempIndex; IndexSort < Index - 1; IndexSort += +) { + E820Table[IndexSort].BaseAddr =3D E820Table[IndexSort + 1].Bas= eAddr; + E820Table[IndexSort].Length =3D E820Table[IndexSort + 1].Len= gth; + E820Table[IndexSort].Type =3D E820Table[IndexSort + 1].Typ= e; + } + Index--; + } + } + } + + + + Private->IntThunk->EfiToLegacy16InitTable.NumberE820Entries =3D (UINT32)= Index; + Private->IntThunk->EfiToLegacy16BootTable.NumberE820Entries =3D (UINT32)= Index; + Private->NumberE820Entries =3D (UINT32)Index; + *Size =3D (UINTN) (Index * sizeof (EFI_E820_ENTRY64)); + + // + // Determine OS usable memory above 1MB + // + Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb =3D 0x0000; + for (TempIndex =3D Above1MIndex; TempIndex < Index; TempIndex++) { + if (E820Table[TempIndex].BaseAddr >=3D 0x100000 && E820Table[TempIndex= ].BaseAddr < 0x100000000ULL) { // not include above 4G memory + // + // ACPIReclaimMemory is also usable memory for ACPI OS, after OS dum= ps all ACPI tables. + // + if ((E820Table[TempIndex].Type =3D=3D EfiAcpiAddressRangeMemory) || = (E820Table[TempIndex].Type =3D=3D EfiAcpiAddressRangeACPI)) { + Private->IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb +=3D (U= INT32) (E820Table[TempIndex].Length); + } else { + break; // break at first not normal memory, because SMM may use re= served memory. + } + } + } + + Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb =3D Private->= IntThunk->EfiToLegacy16BootTable.OsMemoryAbove1Mb; + + // + // Print DEBUG information + // + for (TempIndex =3D 0; TempIndex < Index; TempIndex++) { + DEBUG((EFI_D_INFO, "E820[%2d]: 0x%016lx - 0x%016lx, Type =3D %d\n", + TempIndex, + E820Table[TempIndex].BaseAddr, + (E820Table[TempIndex].BaseAddr + E820Table[TempIndex].Length), + E820Table[TempIndex].Type + )); + } + + return EFI_SUCCESS; +} + + +/** + Fill in the standard BDA and EBDA stuff prior to legacy Boot + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosCompleteBdaBeforeBoot ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + BDA_STRUC *Bda; + UINT16 MachineConfig; + DEVICE_PRODUCER_DATA_HEADER *SioPtr; + + Bda =3D (BDA_STRUC *) ((UINTN) 0x400); + MachineConfig =3D 0; + + SioPtr =3D &(Private->IntThunk->EfiToLegacy16BootTable.SioData); + Bda->Com1 =3D SioPtr->Serial[0].Address; + Bda->Com2 =3D SioPtr->Serial[1].Address; + Bda->Com3 =3D SioPtr->Serial[2].Address; + Bda->Com4 =3D SioPtr->Serial[3].Address; + + if (SioPtr->Serial[0].Address !=3D 0x00) { + MachineConfig +=3D 0x200; + } + + if (SioPtr->Serial[1].Address !=3D 0x00) { + MachineConfig +=3D 0x200; + } + + if (SioPtr->Serial[2].Address !=3D 0x00) { + MachineConfig +=3D 0x200; + } + + if (SioPtr->Serial[3].Address !=3D 0x00) { + MachineConfig +=3D 0x200; + } + + Bda->Lpt1 =3D SioPtr->Parallel[0].Address; + Bda->Lpt2 =3D SioPtr->Parallel[1].Address; + Bda->Lpt3 =3D SioPtr->Parallel[2].Address; + + if (SioPtr->Parallel[0].Address !=3D 0x00) { + MachineConfig +=3D 0x4000; + } + + if (SioPtr->Parallel[1].Address !=3D 0x00) { + MachineConfig +=3D 0x4000; + } + + if (SioPtr->Parallel[2].Address !=3D 0x00) { + MachineConfig +=3D 0x4000; + } + + Bda->NumberOfDrives =3D (UINT8) (Bda->NumberOfDrives + Private->IdeDrive= Count); + if (SioPtr->Floppy.NumberOfFloppy !=3D 0x00) { + MachineConfig =3D (UINT16) (MachineConfig + 0x01 + (SioPtr->Floppy= .NumberOfFloppy - 1) * 0x40); + Bda->FloppyXRate =3D 0x07; + } + + Bda->Lpt1_2Timeout =3D 0x1414; + Bda->Lpt3_4Timeout =3D 0x1414; + Bda->Com1_2Timeout =3D 0x0101; + Bda->Com3_4Timeout =3D 0x0101; + + // + // Force VGA and Coprocessor, indicate 101/102 keyboard + // + MachineConfig =3D (UINT16) (MachineConfig + 0x00 + 0x02 + (SioPtr-= >MousePresent * 0x04)); + Bda->MachineConfig =3D MachineConfig; + + return EFI_SUCCESS; +} + +/** + Fill in the standard BDA for Keyboard LEDs + + @param This Protocol instance pointer. + @param Leds Current LED status + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +EFIAPI +LegacyBiosUpdateKeyboardLedStatus ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 Leds + ) +{ + LEGACY_BIOS_INSTANCE *Private; + BDA_STRUC *Bda; + UINT8 LocalLeds; + EFI_IA32_REGISTER_SET Regs; + + Private =3D LEGACY_BIOS_INSTANCE_FROM_THIS (This); + + ACCESS_PAGE0_CODE ( + Bda =3D (BDA_STRUC *) ((UINTN) 0x400); + LocalLeds =3D Leds; + Bda->LedStatus =3D (UINT8) ((Bda->LedStatus &~0x07) | LocalLeds); + LocalLeds =3D (UINT8) (LocalLeds << 4); + Bda->ShiftStatus =3D (UINT8) ((Bda->ShiftStatus &~0x70) | LocalLeds= ); + LocalLeds =3D (UINT8) (Leds & 0x20); + Bda->KeyboardStatus =3D (UINT8) ((Bda->KeyboardStatus &~0x20) | LocalL= eds); + ); + + // + // Call into Legacy16 code to allow it to do any processing + // + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + Regs.X.AX =3D Legacy16SetKeyboardLeds; + Regs.H.CL =3D Leds; + + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Private->Legacy16Table->Compatibility16CallSegment, + Private->Legacy16Table->Compatibility16CallOffset, + &Regs, + NULL, + 0 + ); + + return EFI_SUCCESS; +} + + +/** + Fill in the standard CMOS stuff prior to legacy Boot + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosCompleteStandardCmosBeforeBoot ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + UINT8 Bda; + UINT8 Floppy; + UINT32 Size; + + // + // Update CMOS locations + // 10 floppy + // 12,19,1A - ignore as OS don't use them and there is no standard due + // to large capacity drives + // CMOS 14 =3D BDA 40:10 plus bit 3(display enabled) + // + ACCESS_PAGE0_CODE ( + Bda =3D (UINT8)(*((UINT8 *)((UINTN)0x410)) | BIT3); + ); + + // + // Force display enabled + // + Floppy =3D 0x00; + if ((Bda & BIT0) !=3D 0) { + Floppy =3D BIT6; + } + + // + // Check if 2.88MB floppy set + // + if ((Bda & (BIT7 | BIT6)) !=3D 0) { + Floppy =3D (UINT8)(Floppy | BIT1); + } + + LegacyWriteStandardCmos (CMOS_10, Floppy); + LegacyWriteStandardCmos (CMOS_14, Bda); + + // + // Force Status Register A to set rate selection bits and divider + // + LegacyWriteStandardCmos (CMOS_0A, 0x26); + + // + // redo memory size since it can change + // + Size =3D (15 * SIZE_1MB) >> 10; + if (Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb < (15 * S= IZE_1MB)) { + Size =3D Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb >= > 10; + } + + LegacyWriteStandardCmos (CMOS_17, (UINT8)(Size & 0xFF)); + LegacyWriteStandardCmos (CMOS_30, (UINT8)(Size & 0xFF)); + LegacyWriteStandardCmos (CMOS_18, (UINT8)(Size >> 8)); + LegacyWriteStandardCmos (CMOS_31, (UINT8)(Size >> 8)); + + LegacyCalculateWriteStandardCmosChecksum (); + + return EFI_SUCCESS; +} + +/** + Relocate this image under 4G memory for IPF. + + @param ImageHandle Handle of driver image. + @param SystemTable Pointer to system table. + + @retval EFI_SUCCESS Image successfully relocated. + @retval EFI_ABORTED Failed to relocate image. + +**/ +EFI_STATUS +RelocateImageUnder4GIfNeeded ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} diff --git a/OvmfPkg/Csm/LegacyBiosDxe/LegacyCmos.c b/OvmfPkg/Csm/LegacyBio= sDxe/LegacyCmos.c new file mode 100644 index 0000000000..de25e06184 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/LegacyCmos.c @@ -0,0 +1,117 @@ +/** @file + This code fills in standard CMOS values and updates the standard CMOS + checksum. The Legacy16 code or LegacyBiosPlatform.c is responsible for + non-standard CMOS locations and non-standard checksums. + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "LegacyBiosInterface.h" + +/** + Read CMOS register through index/data port. + + @param[in] Index The index of the CMOS register to read. + + @return The data value from the CMOS register specified by Index. + +**/ +UINT8 +LegacyReadStandardCmos ( + IN UINT8 Index + ) +{ + IoWrite8 (PORT_70, Index); + return IoRead8 (PORT_71); +} + +/** + Write CMOS register through index/data port. + + @param[in] Index The index of the CMOS register to write. + @param[in] Value The value of CMOS register to write. + + @return The value written to the CMOS register specified by Index. + +**/ +UINT8 +LegacyWriteStandardCmos ( + IN UINT8 Index, + IN UINT8 Value + ) +{ + IoWrite8 (PORT_70, Index); + return IoWrite8 (PORT_71, Value); +} + +/** + Calculate the new standard CMOS checksum and write it. + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS Calculate 16-bit checksum successfully + +**/ +EFI_STATUS +LegacyCalculateWriteStandardCmosChecksum ( + VOID + ) +{ + UINT8 Register; + UINT16 Checksum; + + for (Checksum =3D 0, Register =3D 0x10; Register < 0x2e; Register++) { + Checksum =3D (UINT16)(Checksum + LegacyReadStandardCmos (Register)); + } + LegacyWriteStandardCmos (CMOS_2E, (UINT8)(Checksum >> 8)); + LegacyWriteStandardCmos (CMOS_2F, (UINT8)(Checksum & 0xff)); + return EFI_SUCCESS; +} + + +/** + Fill in the standard CMOS stuff before Legacy16 load + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosInitCmos ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + UINT32 Size; + + // + // Clear all errors except RTC lost power + // + LegacyWriteStandardCmos (CMOS_0E, (UINT8)(LegacyReadStandardCmos (CMOS_0= E) & BIT7)); + + // + // Update CMOS locations 15,16,17,18,30,31 and 32 + // CMOS 16,15 =3D 640Kb =3D 0x280 + // CMOS 18,17 =3D 31,30 =3D 15Mb max in 1Kb increments =3D0x3C00 max + // CMOS 32 =3D 0x20 + // + LegacyWriteStandardCmos (CMOS_15, 0x80); + LegacyWriteStandardCmos (CMOS_16, 0x02); + + Size =3D 15 * SIZE_1MB; + if (Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb < (15 * S= IZE_1MB)) { + Size =3D Private->IntThunk->EfiToLegacy16InitTable.OsMemoryAbove1Mb >= > 10; + } + + LegacyWriteStandardCmos (CMOS_17, (UINT8)(Size & 0xFF)); + LegacyWriteStandardCmos (CMOS_30, (UINT8)(Size & 0xFF)); + LegacyWriteStandardCmos (CMOS_18, (UINT8)(Size >> 8)); + LegacyWriteStandardCmos (CMOS_31, (UINT8)(Size >> 8)); + + LegacyCalculateWriteStandardCmosChecksum (); + + return EFI_SUCCESS; +} diff --git a/OvmfPkg/Csm/LegacyBiosDxe/LegacyIde.c b/OvmfPkg/Csm/LegacyBios= Dxe/LegacyIde.c new file mode 100644 index 0000000000..789f48370e --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/LegacyIde.c @@ -0,0 +1,310 @@ +/** @file + Collect IDE information from Native EFI Driver + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "LegacyBiosInterface.h" + +BOOLEAN mIdeDataBuiltFlag =3D FALSE; + +/** + Collect IDE Inquiry data from the IDE disks + + @param Private Legacy BIOS Instance data + @param HddInfo Hdd Information + @param Flag Reconnect IdeController or not + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosBuildIdeData ( + IN LEGACY_BIOS_INSTANCE *Private, + IN HDD_INFO **HddInfo, + IN UINT16 Flag + ) +{ + EFI_STATUS Status; + EFI_HANDLE IdeController; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + EFI_DISK_INFO_PROTOCOL *DiskInfo; + UINT32 IdeChannel; + UINT32 IdeDevice; + UINT32 Size; + UINT8 *InquiryData; + UINT32 InquiryDataSize; + HDD_INFO *LocalHddInfo; + UINT32 PciIndex; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePathNode; + PCI_DEVICE_PATH *PciDevicePath; + + // + // Only build data once + // We have a problem with GetBbsInfo in that it can be invoked two + // places. Once in BDS, when all EFI drivers are connected and once in + // LegacyBoot after all EFI drivers are disconnected causing this routine + // to hang. In LegacyBoot this function is also called before EFI drivers + // are disconnected. + // Cases covered + // GetBbsInfo invoked in BDS. Both invocations in LegacyBoot ignored. + // GetBbsInfo not invoked in BDS. First invocation of this function + // proceeds normally and second via GetBbsInfo ignored. + // + PciDevicePath =3D NULL; + LocalHddInfo =3D *HddInfo; + Status =3D Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformIdeHandle, + 0, + &HandleBuffer, + &HandleCount, + (VOID *) &LocalHddInfo + ); + if (!EFI_ERROR (Status)) { + IdeController =3D HandleBuffer[0]; + // + // Force IDE drive spin up! + // + if (Flag !=3D 0) { + gBS->DisconnectController ( + IdeController, + NULL, + NULL + ); + } + + gBS->ConnectController (IdeController, NULL, NULL, FALSE); + + // + // Do GetIdeHandle twice since disconnect/reconnect will switch to nat= ive mode + // And GetIdeHandle will switch to Legacy mode, if required. + // + Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformIdeHandle, + 0, + &HandleBuffer, + &HandleCount, + (VOID *) &LocalHddInfo + ); + } + + mIdeDataBuiltFlag =3D TRUE; + + // + // Get Identity command from all drives + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDiskInfoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + + Private->IdeDriveCount =3D (UINT8) HandleCount; + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiDiskInfoProtocolGuid, + (VOID **) &DiskInfo + ); + ASSERT_EFI_ERROR (Status); + + if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid))= { + // + // Locate which PCI device + // + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + (VOID *) &DevicePath + ); + ASSERT_EFI_ERROR (Status); + + DevicePathNode =3D DevicePath; + while (!IsDevicePathEnd (DevicePathNode)) { + TempDevicePathNode =3D NextDevicePathNode (DevicePathNode); + if ((DevicePathType (DevicePathNode) =3D=3D HARDWARE_DEVICE_PATH) = && + ( DevicePathSubType (DevicePathNode) =3D=3D HW_PCI_DP) && + ( DevicePathType(TempDevicePathNode) =3D=3D MESSAGING_DEVICE= _PATH) && + ( DevicePathSubType(TempDevicePathNode) =3D=3D MSG_ATAPI_DP)= ) { + PciDevicePath =3D (PCI_DEVICE_PATH *) DevicePathNode; + break; + } + DevicePathNode =3D NextDevicePathNode (DevicePathNode); + } + + if (PciDevicePath =3D=3D NULL) { + continue; + } + + // + // Find start of PCI device in HddInfo. The assumption of the data + // structure is 2 controllers(channels) per PCI device and each + // controller can have 2 drives(devices). + // HddInfo[PciIndex+0].[0] =3D Channel[0].Device[0] Primary Master + // HddInfo[PciIndex+0].[1] =3D Channel[0].Device[1] Primary Slave + // HddInfo[PciIndex+1].[0] =3D Channel[1].Device[0] Secondary Master + // HddInfo[PciIndex+1].[1] =3D Channel[1].Device[1] Secondary Slave + // @bug eventually need to pass in max number of entries + // for end of for loop + // + for (PciIndex =3D 0; PciIndex < 8; PciIndex++) { + if ((PciDevicePath->Device =3D=3D LocalHddInfo[PciIndex].Device) && + (PciDevicePath->Function =3D=3D LocalHddInfo[PciIndex].Functio= n) + ) { + break; + } + } + + if (PciIndex =3D=3D 8) { + continue; + } + + Status =3D DiskInfo->WhichIde (DiskInfo, &IdeChannel, &IdeDevice); + if (!EFI_ERROR (Status)) { + Size =3D sizeof (ATAPI_IDENTIFY); + DiskInfo->Identify ( + DiskInfo, + &LocalHddInfo[PciIndex + IdeChannel].IdentifyDrive[Ide= Device], + &Size + ); + if (IdeChannel =3D=3D 0) { + LocalHddInfo[PciIndex + IdeChannel].Status |=3D HDD_PRIMARY; + } else if (IdeChannel =3D=3D 1) { + LocalHddInfo[PciIndex + IdeChannel].Status |=3D HDD_SECONDARY; + } + + InquiryData =3D NULL; + InquiryDataSize =3D 0; + Status =3D DiskInfo->Inquiry ( + DiskInfo, + NULL, + &InquiryDataSize + ); + if (Status =3D=3D EFI_BUFFER_TOO_SMALL) { + InquiryData =3D (UINT8 *) AllocatePool ( + InquiryDataSize + ); + if (InquiryData !=3D NULL) { + Status =3D DiskInfo->Inquiry ( + DiskInfo, + InquiryData, + &InquiryDataSize + ); + } + } else { + Status =3D EFI_DEVICE_ERROR; + } + + // + // If ATAPI device then Inquiry will pass and ATA fail. + // + if (!EFI_ERROR (Status)) { + ASSERT (InquiryData !=3D NULL); + // + // If IdeDevice =3D 0 then set master bit, else slave bit + // + if (IdeDevice =3D=3D 0) { + if ((InquiryData[0] & 0x1f) =3D=3D 0x05) { + LocalHddInfo[PciIndex + IdeChannel].Status |=3D HDD_MASTER_A= TAPI_CDROM; + } else if ((InquiryData[0] & 0x1f) =3D=3D 0x00) { + LocalHddInfo[PciIndex + IdeChannel].Status |=3D HDD_MASTER_A= TAPI_ZIPDISK; + } + } else { + if ((InquiryData[0] & 0x1f) =3D=3D 0x05) { + LocalHddInfo[PciIndex + IdeChannel].Status |=3D HDD_SLAVE_AT= API_CDROM; + } else if ((InquiryData[0] & 0x1f) =3D=3D 0x00) { + LocalHddInfo[PciIndex + IdeChannel].Status |=3D HDD_SLAVE_AT= API_ZIPDISK; + } + } + FreePool (InquiryData); + } else { + if (IdeDevice =3D=3D 0) { + LocalHddInfo[PciIndex + IdeChannel].Status |=3D HDD_MASTER_IDE; + } else { + LocalHddInfo[PciIndex + IdeChannel].Status |=3D HDD_SLAVE_IDE; + } + } + } + } + } + + if (HandleBuffer !=3D NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; +} + + +/** + If the IDE channel is in compatibility (legacy) mode, remove all + PCI I/O BAR addresses from the controller. + + @param IdeController The handle of target IDE controller + + +**/ +VOID +InitLegacyIdeController ( + IN EFI_HANDLE IdeController + ) +{ + EFI_PCI_IO_PROTOCOL *PciIo; + UINT32 IOBarClear; + EFI_STATUS Status; + PCI_TYPE00 PciData; + + // + // If the IDE channel is in compatibility (legacy) mode, remove all + // PCI I/O BAR addresses from the controller. Some software gets + // confused if an IDE controller is in compatibility (legacy) mode + // and has PCI I/O resources allocated + // + Status =3D gBS->HandleProtocol ( + IdeController, + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo + ); + if (EFI_ERROR (Status)) { + return ; + } + + Status =3D PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (PciDat= a), &PciData); + if (EFI_ERROR (Status)) { + return ; + } + + // + // Check whether this is IDE + // + if ((PciData.Hdr.ClassCode[2] !=3D PCI_CLASS_MASS_STORAGE) || + (PciData.Hdr.ClassCode[1] !=3D PCI_CLASS_MASS_STORAGE_IDE)) { + return ; + } + + // + // Clear bar for legacy IDE + // + IOBarClear =3D 0x00; + if ((PciData.Hdr.ClassCode[0] & IDE_PI_REGISTER_PNE) =3D=3D 0) { + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x10, 1, &IOBarClear); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x14, 1, &IOBarClear); + } + if ((PciData.Hdr.ClassCode[0] & IDE_PI_REGISTER_SNE) =3D=3D 0) { + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x18, 1, &IOBarClear); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1C, 1, &IOBarClear); + } + + return ; +} diff --git a/OvmfPkg/Csm/LegacyBiosDxe/LegacyPci.c b/OvmfPkg/Csm/LegacyBios= Dxe/LegacyPci.c new file mode 100644 index 0000000000..dc1f760876 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/LegacyPci.c @@ -0,0 +1,3083 @@ +/** @file + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "LegacyBiosInterface.h" +#include + +#define PCI_START_ADDRESS(x) (((x) + 0x7ff) & ~0x7ff) + +#define MAX_BRIDGE_INDEX 0x20 +typedef struct { + UINTN PciSegment; + UINTN PciBus; + UINTN PciDevice; + UINTN PciFunction; + UINT8 PrimaryBus; + UINT8 SecondaryBus; + UINT8 SubordinateBus; +} BRIDGE_TABLE; + +#define ROM_MAX_ENTRIES 24 +BRIDGE_TABLE Bridges[MAX_BRIDGE_INDEX]; +UINTN SortedBridgeIndex[MAX_BRIDGE_INDEX]; +UINTN NumberOfBridges; +LEGACY_PNP_EXPANSION_HEADER *mBasePnpPtr; +UINT16 mBbsRomSegment; +UINTN mHandleCount; +EFI_HANDLE mVgaHandle; +BOOLEAN mIgnoreBbsUpdateFlag; +BOOLEAN mVgaInstallationInProgress =3D FALSE; +UINT32 mRomCount =3D 0x00; +ROM_INSTANCE_ENTRY mRomEntry[ROM_MAX_ENTRIES]; +EDKII_IOMMU_PROTOCOL *mIoMmu; + +/** + Query shadowed legacy ROM parameters registered by RomShadow() previousl= y. + + @param PciHandle PCI device whos ROM has been shadowed + @param DiskStart DiskStart value from EFI_LEGACY_BIOS_PROTOCOL.I= nstallPciRom + @param DiskEnd DiskEnd value from EFI_LEGACY_BIOS_PROTOCOL.Ins= tallPciRom + @param RomShadowAddress Address where ROM was shadowed + @param ShadowedSize Runtime size of ROM + + @retval EFI_SUCCESS Query Logging successful. + @retval EFI_NOT_FOUND No logged data found about PciHandle. + +**/ +EFI_STATUS +GetShadowedRomParameters ( + IN EFI_HANDLE PciHandle, + OUT UINT8 *DiskStart, OPTIONAL + OUT UINT8 *DiskEnd, OPTIONAL + OUT VOID **RomShadowAddress, OPTIONAL + OUT UINTN *ShadowedSize OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN Index; + UINTN PciSegment; + UINTN PciBus; + UINTN PciDevice; + UINTN PciFunction; + + // + // Get the PCI I/O Protocol on PciHandle + // + Status =3D gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the location of the PCI device + // + PciIo->GetLocation ( + PciIo, + &PciSegment, + &PciBus, + &PciDevice, + &PciFunction + ); + + for(Index =3D 0; Index < mRomCount; Index++) { + if ((mRomEntry[Index].PciSegment =3D=3D PciSegment) && + (mRomEntry[Index].PciBus =3D=3D PciBus) && + (mRomEntry[Index].PciDevice =3D=3D PciDevice) && + (mRomEntry[Index].PciFunction =3D=3D PciFunction)) { + break; + } + } + + if (Index =3D=3D mRomCount) { + return EFI_NOT_FOUND; + } + + if (DiskStart !=3D NULL) { + *DiskStart =3D mRomEntry[Index].DiskStart; + } + + if (DiskEnd !=3D NULL) { + *DiskEnd =3D mRomEntry[Index].DiskEnd; + } + + if (RomShadowAddress !=3D NULL) { + *RomShadowAddress =3D (VOID *)(UINTN)mRomEntry[Index].ShadowAddress; + } + + if (ShadowedSize !=3D NULL) { + *ShadowedSize =3D mRomEntry[Index].ShadowedSize; + } + + return EFI_SUCCESS; +} + +/** + Every legacy ROM that is shadowed by the Legacy BIOS driver will be + registered into this API so that the policy code can know what has + happend + + @param PciHandle PCI device whos ROM is being shadowed + @param ShadowAddress Address that ROM was shadowed + @param ShadowedSize Runtime size of ROM + @param DiskStart DiskStart value from + EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom + @param DiskEnd DiskEnd value from + EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom + + @retval EFI_SUCCESS Logging successful. + @retval EFI_OUT_OF_RESOURCES No remaining room for registering another= option + ROM. + +**/ +EFI_STATUS +RomShadow ( + IN EFI_HANDLE PciHandle, + IN UINT32 ShadowAddress, + IN UINT32 ShadowedSize, + IN UINT8 DiskStart, + IN UINT8 DiskEnd + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + + // + // See if there is room to register another option ROM + // + if (mRomCount >=3D ROM_MAX_ENTRIES) { + return EFI_OUT_OF_RESOURCES; + } + // + // Get the PCI I/O Protocol on PciHandle + // + Status =3D gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the location of the PCI device + // + PciIo->GetLocation ( + PciIo, + &mRomEntry[mRomCount].PciSegment, + &mRomEntry[mRomCount].PciBus, + &mRomEntry[mRomCount].PciDevice, + &mRomEntry[mRomCount].PciFunction + ); + mRomEntry[mRomCount].ShadowAddress =3D ShadowAddress; + mRomEntry[mRomCount].ShadowedSize =3D ShadowedSize; + mRomEntry[mRomCount].DiskStart =3D DiskStart; + mRomEntry[mRomCount].DiskEnd =3D DiskEnd; + + mRomCount++; + + return EFI_SUCCESS; +} + + +/** + Return EFI_SUCCESS if PciHandle has had a legacy BIOS ROM shadowed. This + information represents every call to RomShadow () + + @param PciHandle PCI device to get status for + + @retval EFI_SUCCESS Legacy ROM loaded for this device + @retval EFI_NOT_FOUND No Legacy ROM loaded for this device + +**/ +EFI_STATUS +IsLegacyRom ( + IN EFI_HANDLE PciHandle + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN Index; + UINTN Segment; + UINTN Bus; + UINTN Device; + UINTN Function; + + // + // Get the PCI I/O Protocol on PciHandle + // + Status =3D gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the location of the PCI device + // + PciIo->GetLocation ( + PciIo, + &Segment, + &Bus, + &Device, + &Function + ); + + // + // See if the option ROM from PciHandle has been previously posted + // + for (Index =3D 0; Index < mRomCount; Index++) { + if (mRomEntry[Index].PciSegment =3D=3D Segment && + mRomEntry[Index].PciBus =3D=3D Bus && + mRomEntry[Index].PciDevice =3D=3D Device && + mRomEntry[Index].PciFunction =3D=3D Function + ) { + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + Find the PC-AT ROM Image in the raw PCI Option ROM. Also return the + related information from the header. + + @param Csm16Revision The PCI interface version of underlying = CSM16 + @param VendorId Vendor ID of the PCI device + @param DeviceId Device ID of the PCI device + @param Rom On input pointing to beginning of the ra= w PCI OpROM + On output pointing to the first legacy P= CI OpROM + @param ImageSize On input is the size of Raw PCI Rom + On output is the size of the first legac= y PCI ROM + @param MaxRuntimeImageLength The max runtime image length only valid = if OpRomRevision >=3D 3 + @param OpRomRevision Revision of the PCI Rom + @param ConfigUtilityCodeHeader Pointer to Configuration Utility Code He= ader + + @retval EFI_SUCCESS Successfully find the legacy PCI ROM + @retval EFI_NOT_FOUND Failed to find the legacy PCI ROM + +**/ +EFI_STATUS +GetPciLegacyRom ( + IN UINT16 Csm16Revision, + IN UINT16 VendorId, + IN UINT16 DeviceId, + IN OUT VOID **Rom, + IN OUT UINTN *ImageSize, + OUT UINTN *MaxRuntimeImageLength, OPTIONAL + OUT UINT8 *OpRomRevision, OPTIONAL + OUT VOID **ConfigUtilityCodeHeader OPTIONAL + ) +{ + BOOLEAN Match; + UINT16 *DeviceIdList; + EFI_PCI_ROM_HEADER RomHeader; + PCI_3_0_DATA_STRUCTURE *Pcir; + VOID *BackupImage; + VOID *BestImage; + + + if (*ImageSize < sizeof (EFI_PCI_ROM_HEADER)) { + return EFI_NOT_FOUND; + } + + BestImage =3D NULL; + BackupImage =3D NULL; + RomHeader.Raw =3D *Rom; + while (RomHeader.Generic->Signature =3D=3D PCI_EXPANSION_ROM_HEADER_SIGN= ATURE) { + if (RomHeader.Generic->PcirOffset =3D=3D 0 || + (RomHeader.Generic->PcirOffset & 3) !=3D0 || + *ImageSize < RomHeader.Raw - (UINT8 *) *Rom + RomHeader.Generic->P= cirOffset + sizeof (PCI_DATA_STRUCTURE)) { + break; + } + + Pcir =3D (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic= ->PcirOffset); + // + // Check signature in the PCI Data Structure. + // + if (Pcir->Signature !=3D PCI_DATA_STRUCTURE_SIGNATURE) { + break; + } + + if (((UINTN)RomHeader.Raw - (UINTN)*Rom) + Pcir->ImageLength * 512 > *= ImageSize) { + break; + } + + if (Pcir->CodeType =3D=3D PCI_CODE_TYPE_PCAT_IMAGE) { + Match =3D FALSE; + if (Pcir->VendorId =3D=3D VendorId) { + if (Pcir->DeviceId =3D=3D DeviceId) { + Match =3D TRUE; + } else if ((Pcir->Revision >=3D 3) && (Pcir->DeviceListOffset !=3D= 0)) { + DeviceIdList =3D (UINT16 *)(((UINT8 *) Pcir) + Pcir->DeviceListO= ffset); + // + // Checking the device list + // + while (*DeviceIdList !=3D 0) { + if (*DeviceIdList =3D=3D DeviceId) { + Match =3D TRUE; + break; + } + DeviceIdList ++; + } + } + } + + if (Match) { + if (Csm16Revision >=3D 0x0300) { + // + // Case 1: CSM16 3.0 + // + if (Pcir->Revision >=3D 3) { + // + // case 1.1: meets OpRom 3.0 + // Perfect!!! + // + BestImage =3D RomHeader.Raw; + break; + } else { + // + // case 1.2: meets OpRom 2.x + // Store it and try to find the OpRom 3.0 + // + BackupImage =3D RomHeader.Raw; + } + } else { + // + // Case 2: CSM16 2.x + // + if (Pcir->Revision >=3D 3) { + // + // case 2.1: meets OpRom 3.0 + // Store it and try to find the OpRom 2.x + // + BackupImage =3D RomHeader.Raw; + } else { + // + // case 2.2: meets OpRom 2.x + // Perfect!!! + // + BestImage =3D RomHeader.Raw; + break; + } + } + } else { + DEBUG ((EFI_D_ERROR, "GetPciLegacyRom - OpRom not match (%04x-%04x= )\n", (UINTN)VendorId, (UINTN)DeviceId)); + } + } + + if ((Pcir->Indicator & 0x80) =3D=3D 0x80) { + break; + } else { + RomHeader.Raw +=3D 512 * Pcir->ImageLength; + } + } + + if (BestImage =3D=3D NULL) { + if (BackupImage =3D=3D NULL) { + return EFI_NOT_FOUND; + } + // + // The versions of CSM16 and OpRom don't match exactly + // + BestImage =3D BackupImage; + } + RomHeader.Raw =3D BestImage; + Pcir =3D (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic->= PcirOffset); + *Rom =3D BestImage; + *ImageSize =3D Pcir->ImageLength * 512; + + if (MaxRuntimeImageLength !=3D NULL) { + if (Pcir->Revision < 3) { + *MaxRuntimeImageLength =3D 0; + } else { + *MaxRuntimeImageLength =3D Pcir->MaxRuntimeImageLength * 512; + } + } + + if (OpRomRevision !=3D NULL) { + // + // Optional return PCI Data Structure revision + // + if (Pcir->Length >=3D 0x1C) { + *OpRomRevision =3D Pcir->Revision; + } else { + *OpRomRevision =3D 0; + } + } + + if (ConfigUtilityCodeHeader !=3D NULL) { + // + // Optional return ConfigUtilityCodeHeaderOffset supported by the PC-A= T ROM + // + if ((Pcir->Revision < 3) || (Pcir->ConfigUtilityCodeHeaderOffset =3D= =3D 0)) { + *ConfigUtilityCodeHeader =3D NULL; + } else { + *ConfigUtilityCodeHeader =3D RomHeader.Raw + Pcir->ConfigUtilityCode= HeaderOffset; + } + } + + return EFI_SUCCESS; +} + +/** + Build a table of bridge info for PIRQ translation. + + @param RoutingTable RoutingTable obtained from Platform. + @param RoutingTableEntries Number of RoutingTable entries. + + @retval EFI_SUCCESS New Subordinate bus. + @retval EFI_NOT_FOUND No more Subordinate busses. + +**/ +EFI_STATUS +CreateBridgeTable ( + IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable, + IN UINTN RoutingTableEntries + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN BridgeIndex; + UINTN Index; + UINTN Index1; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE01 PciConfigHeader; + BRIDGE_TABLE SlotBridges[MAX_BRIDGE_INDEX]; + UINTN SlotBridgeIndex; + + BridgeIndex =3D 0x00; + SlotBridgeIndex =3D 0x00; + + // + // Assumption is table is built from low bus to high bus numbers. + // + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status)) { + continue; + } + + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + + if (IS_PCI_P2P (&PciConfigHeader) && (BridgeIndex < MAX_BRIDGE_INDEX))= { + PciIo->GetLocation ( + PciIo, + &Bridges[BridgeIndex].PciSegment, + &Bridges[BridgeIndex].PciBus, + &Bridges[BridgeIndex].PciDevice, + &Bridges[BridgeIndex].PciFunction + ); + + Bridges[BridgeIndex].PrimaryBus =3D PciConfigHeader.Bridge.Prima= ryBus; + + Bridges[BridgeIndex].SecondaryBus =3D PciConfigHeader.Bridge.Secon= daryBus; + + Bridges[BridgeIndex].SubordinateBus =3D PciConfigHeader.Bridge.Subor= dinateBus; + + for (Index1 =3D 0; Index1 < RoutingTableEntries; Index1++){ + // + // Test whether we have found the Bridge in the slot, must be the = one that directly interfaced to the board + // Once we find one, store it in the SlotBridges[] + // + if ((RoutingTable[Index1].Slot !=3D 0) && (Bridges[BridgeIndex].Pr= imaryBus =3D=3D RoutingTable[Index1].Bus) + && ((Bridges[BridgeIndex].PciDevice << 3) =3D=3D RoutingTable[I= ndex1].Device)) { + CopyMem (&SlotBridges[SlotBridgeIndex], &Bridges[BridgeIndex], s= izeof (BRIDGE_TABLE)); + SlotBridgeIndex++; + + break; + } + } + + ++BridgeIndex; + } + } + + // + // Pack up Bridges by removing those useless ones + // + for (Index =3D 0; Index < BridgeIndex;){ + for (Index1 =3D 0; Index1 < SlotBridgeIndex; Index1++) { + if (((Bridges[Index].PciBus =3D=3D SlotBridges[Index1].PrimaryBus) &= & (Bridges[Index].PciDevice =3D=3D SlotBridges[Index1].PciDevice)) || + ((Bridges[Index].PciBus >=3D SlotBridges[Index1].SecondaryBus) && = (Bridges[Index].PciBus <=3D SlotBridges[Index1].SubordinateBus))) { + // + // We have found one that meets our criteria + // + Index++; + break; + } + } + + // + // This one doesn't meet criteria, pack it + // + if (Index1 >=3D SlotBridgeIndex) { + for (Index1 =3D Index; BridgeIndex > 1 && Index1 < BridgeIndex - 1 ;= Index1++) { + CopyMem (&Bridges[Index1], &Bridges[Index1 + 1], sizeof (BRIDGE_TA= BLE)); + } + + BridgeIndex--; + } + } + + NumberOfBridges =3D BridgeIndex; + + // + // Sort bridges low to high by Secondary bus followed by subordinate bus + // + if (NumberOfBridges > 1) { + Index =3D 0; + do { + SortedBridgeIndex[Index] =3D Index; + ++Index; + } while (Index < NumberOfBridges); + + for (Index =3D 0; Index < NumberOfBridges - 1; Index++) { + for (Index1 =3D Index + 1; Index1 < NumberOfBridges; Index1++) { + if (Bridges[Index].SecondaryBus > Bridges[Index1].SecondaryBus) { + SortedBridgeIndex[Index] =3D Index1; + SortedBridgeIndex[Index1] =3D Index; + } + + if ((Bridges[Index].SecondaryBus =3D=3D Bridges[Index1].SecondaryB= us) && + (Bridges[Index].SubordinateBus > Bridges[Index1].SubordinateBu= s) + ) { + SortedBridgeIndex[Index] =3D Index1; + SortedBridgeIndex[Index1] =3D Index; + } + } + } + } + FreePool (HandleBuffer); + return EFI_SUCCESS; +} + + +/** + Find base Bridge for device. + + @param Private Legacy BIOS Instance data + @param PciBus Input =3D Bus of device. + @param PciDevice Input =3D Device. + @param RoutingTable The platform specific routing table + @param RoutingTableEntries Number of entries in table + + @retval EFI_SUCCESS At base bus. + @retval EFI_NOT_FOUND Behind a bridge. + +**/ +EFI_STATUS +GetBaseBus ( + IN LEGACY_BIOS_INSTANCE *Private, + IN UINTN PciBus, + IN UINTN PciDevice, + IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable, + IN UINTN RoutingTableEntries + ) +{ + UINTN Index; + for (Index =3D 0; Index < RoutingTableEntries; Index++) { + if ((RoutingTable[Index].Bus =3D=3D PciBus) && (RoutingTable[Index].De= vice =3D=3D (PciDevice << 3))) { + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + Translate PIRQ through busses + + @param Private Legacy BIOS Instance data + @param PciBus Input =3D Bus of device. Output =3D Transla= ted Bus + @param PciDevice Input =3D Device. Output =3D Translated Dev= ice + @param PciFunction Input =3D Function. Output =3D Translated F= unction + @param PirqIndex Input =3D Original PIRQ index. If single fu= nction + device then 0, otherwise 0-3. + Output =3D Translated Index + + @retval EFI_SUCCESS Pirq successfully translated. + @retval EFI_NOT_FOUND The device is not behind any known bridge. + +**/ +EFI_STATUS +TranslateBusPirq ( + IN LEGACY_BIOS_INSTANCE *Private, + IN OUT UINTN *PciBus, + IN OUT UINTN *PciDevice, + IN OUT UINTN *PciFunction, + IN OUT UINT8 *PirqIndex + ) +{ + /* + This routine traverses the PCI busses from base slot + and translates the PIRQ register to the appropriate one. + + Example: + + Bus 0, Device 1 is PCI-PCI bridge that all PCI slots reside on. + Primary bus# =3D 0 + Secondary bus # =3D 1 + Subordinate bus # is highest bus # behind this bus + Bus 1, Device 0 is Slot 0 and is not a bridge. + Bus 1, Device 1 is Slot 1 and is a bridge. + Slot PIRQ routing is A,B,C,D. + Primary bus # =3D 1 + Secondary bus # =3D 2 + Subordinate bus # =3D 5 + Bus 2, Device 6 is a bridge. It has no bridges behind it. + Primary bus # =3D 2 + Secondary bus # =3D 3 + Subordinate bus # =3D 3 + Bridge PIRQ routing is C,D,A,B + Bus 2, Device 7 is a bridge. It has 1 bridge behind it. + Primary bus # =3D 2 + Secondary bus =3D 4 Device 6 takes bus 2. + Subordinate bus =3D 5. + Bridge PIRQ routing is D,A,B,C + Bus 4, Device 2 is a bridge. It has no bridges behind it. + Primary bus # =3D 4 + Secondary bus # =3D 5 + Subordinate bus =3D 5 + Bridge PIRQ routing is B,C,D,A + Bus 5, Device 1 is to be programmed. + Device PIRQ routing is C,D,A,B + + +Search busses starting from slot bus for final bus >=3D Secondary bus and +final bus <=3D Suborninate bus. Assumption is bus entries increase in bus +number. +Starting PIRQ is A,B,C,D. +Bus 2, Device 7 satisfies search criteria. Rotate (A,B,C,D) left by device + 7 modulo 4 giving (D,A,B,C). +Bus 4, Device 2 satisfies search criteria. Rotate (D,A,B,C) left by 2 givi= ng + (B,C,D,A). +No other busses match criteria. Device to be programmed is Bus 5, Device 1. +Rotate (B,C,D,A) by 1 giving C,D,A,B. Translated PIRQ is C. + +*/ + UINTN LocalBus; + UINTN LocalDevice; + UINTN BaseBus; + UINTN BaseDevice; + UINTN BaseFunction; + UINT8 LocalPirqIndex; + BOOLEAN BaseIndexFlag; + UINTN BridgeIndex; + UINTN SBridgeIndex; + BaseIndexFlag =3D FALSE; + BridgeIndex =3D 0x00; + + LocalPirqIndex =3D *PirqIndex; + LocalBus =3D *PciBus; + LocalDevice =3D *PciDevice; + BaseBus =3D *PciBus; + BaseDevice =3D *PciDevice; + BaseFunction =3D *PciFunction; + + // + // LocalPirqIndex list PIRQs in rotated fashion + // =3D 0 A,B,C,D + // =3D 1 B,C,D,A + // =3D 2 C,D,A,B + // =3D 3 D,A,B,C + // + + for (BridgeIndex =3D 0; BridgeIndex < NumberOfBridges; BridgeIndex++) { + SBridgeIndex =3D SortedBridgeIndex[BridgeIndex]; + // + // Check if device behind this bridge + // + if ((LocalBus >=3D Bridges[SBridgeIndex].SecondaryBus) && (LocalBus <= =3D Bridges[SBridgeIndex].SubordinateBus)) { + // + // If BaseIndexFlag =3D FALSE then have found base bridge, i.e + // bridge in slot. Save info for use by IRQ routing table. + // + if (!BaseIndexFlag) { + BaseBus =3D Bridges[SBridgeIndex].PciBus; + BaseDevice =3D Bridges[SBridgeIndex].PciDevice; + BaseFunction =3D Bridges[SBridgeIndex].PciFunction; + BaseIndexFlag =3D TRUE; + } else { + LocalPirqIndex =3D (UINT8) ((LocalPirqIndex + (UINT8)Bridges[SBrid= geIndex].PciDevice)%4); + } + + // + // Check if at device. If not get new PCI location & PIRQ + // + if (Bridges[SBridgeIndex].SecondaryBus =3D=3D (UINT8) LocalBus) { + // + // Translate PIRQ + // + LocalPirqIndex =3D (UINT8) ((LocalPirqIndex + (UINT8) (LocalDevice= )) % 4); + break; + } + } + } + + // + // In case we fail to find the Bridge just above us, this is some potent= ial error and we want to warn the user + // + if(BridgeIndex >=3D NumberOfBridges){ + DEBUG ((EFI_D_ERROR, "Cannot Find IRQ Routing for Bus %d, Device %d, F= unction %d\n", *PciBus, *PciDevice, *PciFunction)); + } + + *PirqIndex =3D LocalPirqIndex; + *PciBus =3D BaseBus; + *PciDevice =3D BaseDevice; + *PciFunction =3D BaseFunction; + + return EFI_SUCCESS; +} + + +/** + Copy the $PIR table as required. + + @param Private Legacy BIOS Instance data + @param RoutingTable Pointer to IRQ routing table + @param RoutingTableEntries IRQ routing table entries + @param PirqTable Pointer to $PIR table + @param PirqTableSize Length of table + +**/ +VOID +CopyPirqTable ( + IN LEGACY_BIOS_INSTANCE *Private, + IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable, + IN UINTN RoutingTableEntries, + IN EFI_LEGACY_PIRQ_TABLE_HEADER *PirqTable, + IN UINTN PirqTableSize + ) +{ + EFI_IA32_REGISTER_SET Regs; + UINT32 Granularity; + + // + // Copy $PIR table, if it exists. + // + if (PirqTable !=3D NULL) { + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + + Private->InternalIrqRoutingTable =3D RoutingTable; + Private->NumberIrqRoutingEntries =3D (UINT16) (RoutingTableEntries); + ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); + + Regs.X.AX =3D Legacy16GetTableAddress; + Regs.X.CX =3D (UINT16) PirqTableSize; + // + // Allocate at F segment according to PCI IRQ Routing Table Specificat= ion + // + Regs.X.BX =3D (UINT16) 0x1; + // + // 16-byte boundary alignment requirement according to + // PCI IRQ Routing Table Specification + // + Regs.X.DX =3D 0x10; + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + + Private->Legacy16Table->IrqRoutingTablePointer =3D (UINT32) (Regs.X.DS= * 16 + Regs.X.BX); + if (Regs.X.AX !=3D 0) { + DEBUG ((EFI_D_ERROR, "PIRQ table length insufficient - %x\n", PirqTa= bleSize)); + } else { + DEBUG ((EFI_D_INFO, "PIRQ table in legacy region - %x\n", Private->L= egacy16Table->IrqRoutingTablePointer)); + Private->Legacy16Table->IrqRoutingTableLength =3D (UINT32)PirqTableS= ize; + CopyMem ( + (VOID *) (UINTN)Private->Legacy16Table->IrqRoutingTablePointer, + PirqTable, + PirqTableSize + ); + } + + Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFl= ushTypeWriteBackInvalidate); + Private->LegacyRegion->Lock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + } + + Private->PciInterruptLine =3D TRUE; + mHandleCount =3D 0; +} + +/** + Dump EFI_LEGACY_INSTALL_PCI_HANDLER structure information. + + @param PciHandle The pointer to EFI_LEGACY_INSTALL_PCI_HA= NDLER structure + +**/ +VOID +DumpPciHandle ( + IN EFI_LEGACY_INSTALL_PCI_HANDLER *PciHandle + ) +{ + DEBUG ((EFI_D_INFO, "PciBus - %02x\n", (UINTN)PciHandle->Pci= Bus)); + DEBUG ((EFI_D_INFO, "PciDeviceFun - %02x\n", (UINTN)PciHandle->Pci= DeviceFun)); + DEBUG ((EFI_D_INFO, "PciSegment - %02x\n", (UINTN)PciHandle->Pci= Segment)); + DEBUG ((EFI_D_INFO, "PciClass - %02x\n", (UINTN)PciHandle->Pci= Class)); + DEBUG ((EFI_D_INFO, "PciSubclass - %02x\n", (UINTN)PciHandle->Pci= Subclass)); + DEBUG ((EFI_D_INFO, "PciInterface - %02x\n", (UINTN)PciHandle->Pci= Interface)); + + DEBUG ((EFI_D_INFO, "PrimaryIrq - %02x\n", (UINTN)PciHandle->Pri= maryIrq)); + DEBUG ((EFI_D_INFO, "PrimaryReserved - %02x\n", (UINTN)PciHandle->Pri= maryReserved)); + DEBUG ((EFI_D_INFO, "PrimaryControl - %04x\n", (UINTN)PciHandle->Pri= maryControl)); + DEBUG ((EFI_D_INFO, "PrimaryBase - %04x\n", (UINTN)PciHandle->Pri= maryBase)); + DEBUG ((EFI_D_INFO, "PrimaryBusMaster - %04x\n", (UINTN)PciHandle->Pri= maryBusMaster)); + + DEBUG ((EFI_D_INFO, "SecondaryIrq - %02x\n", (UINTN)PciHandle->Sec= ondaryIrq)); + DEBUG ((EFI_D_INFO, "SecondaryReserved - %02x\n", (UINTN)PciHandle->Sec= ondaryReserved)); + DEBUG ((EFI_D_INFO, "SecondaryControl - %04x\n", (UINTN)PciHandle->Sec= ondaryControl)); + DEBUG ((EFI_D_INFO, "SecondaryBase - %04x\n", (UINTN)PciHandle->Sec= ondaryBase)); + DEBUG ((EFI_D_INFO, "SecondaryBusMaster - %04x\n", (UINTN)PciHandle->Sec= ondaryBusMaster)); + return; +} + +/** + Copy the $PIR table as required. + + @param Private Legacy BIOS Instance data + @param PciIo Pointer to PCI_IO protocol + @param PciIrq Pci IRQ number + @param PciConfigHeader Type00 Pci configuration header + +**/ +VOID +InstallLegacyIrqHandler ( + IN LEGACY_BIOS_INSTANCE *Private, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT8 PciIrq, + IN PCI_TYPE00 *PciConfigHeader + ) +{ + EFI_IA32_REGISTER_SET Regs; + UINT16 LegMask; + UINTN PciSegment; + UINTN PciBus; + UINTN PciDevice; + UINTN PciFunction; + EFI_LEGACY_8259_PROTOCOL *Legacy8259; + UINT16 PrimaryMaster; + UINT16 SecondaryMaster; + UINTN TempData; + UINTN RegisterAddress; + UINT32 Granularity; + + PrimaryMaster =3D 0; + SecondaryMaster =3D 0; + Legacy8259 =3D Private->Legacy8259; + // + // Disable interrupt in PIC, in case shared, to prevent an + // interrupt from occuring. + // + Legacy8259->GetMask ( + Legacy8259, + &LegMask, + NULL, + NULL, + NULL + ); + + LegMask =3D (UINT16) (LegMask | (UINT16) (1 << PciIrq)); + + Legacy8259->SetMask ( + Legacy8259, + &LegMask, + NULL, + NULL, + NULL + ); + + PciIo->GetLocation ( + PciIo, + &PciSegment, + &PciBus, + &PciDevice, + &PciFunction + ); + Private->IntThunk->PciHandler.PciBus =3D (UINT8) PciBus; + Private->IntThunk->PciHandler.PciDeviceFun =3D (UINT8) ((PciDevic= e << 3) + PciFunction); + Private->IntThunk->PciHandler.PciSegment =3D (UINT8) PciSegment; + Private->IntThunk->PciHandler.PciClass =3D PciConfigHeader->H= dr.ClassCode[2]; + Private->IntThunk->PciHandler.PciSubclass =3D PciConfigHeader->H= dr.ClassCode[1]; + Private->IntThunk->PciHandler.PciInterface =3D PciConfigHeader->H= dr.ClassCode[0]; + + // + // Use native mode base address registers in two cases: + // 1. Programming Interface (PI) register indicates Primary Controller is + // in native mode OR + // 2. PCI device Sub Class Code is not IDE + // + Private->IntThunk->PciHandler.PrimaryBusMaster =3D (UINT16)(PciConfigHe= ader->Device.Bar[4] & 0xfffc); + if (((PciConfigHeader->Hdr.ClassCode[0] & 0x01) !=3D 0) || (PciConfigHea= der->Hdr.ClassCode[1] !=3D PCI_CLASS_MASS_STORAGE_IDE)) { + Private->IntThunk->PciHandler.PrimaryIrq =3D PciIrq; + Private->IntThunk->PciHandler.PrimaryBase =3D (UINT16) (PciConfigH= eader->Device.Bar[0] & 0xfffc); + Private->IntThunk->PciHandler.PrimaryControl =3D (UINT16) ((PciConfig= Header->Device.Bar[1] & 0xfffc) + 2); + } else { + Private->IntThunk->PciHandler.PrimaryIrq =3D 14; + Private->IntThunk->PciHandler.PrimaryBase =3D 0x1f0; + Private->IntThunk->PciHandler.PrimaryControl =3D 0x3f6; + } + // + // Secondary controller data + // + if (Private->IntThunk->PciHandler.PrimaryBusMaster !=3D 0) { + Private->IntThunk->PciHandler.SecondaryBusMaster =3D (UINT16) ((PciCo= nfigHeader->Device.Bar[4] & 0xfffc) + 8); + PrimaryMaster =3D (UINT16) (Private->IntThunk->PciHandler.PrimaryBusMa= ster + 2); + SecondaryMaster =3D (UINT16) (Private->IntThunk->PciHandler.SecondaryB= usMaster + 2); + + // + // Clear pending interrupts in Bus Master registers + // + IoWrite16 (PrimaryMaster, 0x04); + IoWrite16 (SecondaryMaster, 0x04); + + } + + // + // Use native mode base address registers in two cases: + // 1. Programming Interface (PI) register indicates Secondary Controller= is + // in native mode OR + // 2. PCI device Sub Class Code is not IDE + // + if (((PciConfigHeader->Hdr.ClassCode[0] & 0x04) !=3D 0) || (PciConfigHea= der->Hdr.ClassCode[1] !=3D PCI_CLASS_MASS_STORAGE_IDE)) { + Private->IntThunk->PciHandler.SecondaryIrq =3D PciIrq; + Private->IntThunk->PciHandler.SecondaryBase =3D (UINT16) (PciConfi= gHeader->Device.Bar[2] & 0xfffc); + Private->IntThunk->PciHandler.SecondaryControl =3D (UINT16) ((PciConf= igHeader->Device.Bar[3] & 0xfffc) + 2); + } else { + + Private->IntThunk->PciHandler.SecondaryIrq =3D 15; + Private->IntThunk->PciHandler.SecondaryBase =3D 0x170; + Private->IntThunk->PciHandler.SecondaryControl =3D 0x376; + } + + // + // Clear pending interrupts in IDE Command Block Status reg before we + // Thunk to CSM16 below. Don't want a pending Interrupt before we + // install the handlers as wierd corruption would occur and hang system. + // + // + // Read IDE CMD blk status reg to clear out any pending interrupts. + // Do here for Primary and Secondary IDE channels + // + RegisterAddress =3D (UINT16)Private->IntThunk->PciHandler.PrimaryBase + = 0x07; + IoRead8 (RegisterAddress); + RegisterAddress =3D (UINT16)Private->IntThunk->PciHandler.SecondaryBase = + 0x07; + IoRead8 (RegisterAddress); + + Private->IntThunk->PciHandler.PrimaryReserved =3D 0; + Private->IntThunk->PciHandler.SecondaryReserved =3D 0; + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + + Regs.X.AX =3D Legacy16InstallPciHandler; + TempData =3D (UINTN) &Private->IntThunk->PciHandler; + Regs.X.ES =3D EFI_SEGMENT ((UINT32) TempData); + Regs.X.BX =3D EFI_OFFSET ((UINT32) TempData); + + DumpPciHandle (&Private->IntThunk->PciHandler); + + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + + Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlus= hTypeWriteBackInvalidate); + Private->LegacyRegion->Lock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + +} + + +/** + Program the interrupt routing register in all the PCI devices. On a PC A= T system + this register contains the 8259 IRQ vector that matches it's PCI interru= pt. + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS Succeed. + @retval EFI_ALREADY_STARTED All PCI devices have been processed. + +**/ +EFI_STATUS +PciProgramAllInterruptLineRegisters ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_LEGACY_8259_PROTOCOL *Legacy8259; + EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt; + EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform; + UINT8 InterruptPin; + UINTN Index; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN MassStorageHandleCount; + EFI_HANDLE *MassStorageHandleBuffer; + UINTN MassStorageHandleIndex; + UINT8 PciIrq; + UINT16 Command; + UINTN PciSegment; + UINTN PciBus; + UINTN PciDevice; + UINTN PciFunction; + EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable; + UINTN RoutingTableEntries; + UINT16 LegMask; + UINT16 LegEdgeLevel; + PCI_TYPE00 PciConfigHeader; + EFI_LEGACY_PIRQ_TABLE_HEADER *PirqTable; + UINTN PirqTableSize; + UINTN Flags; + HDD_INFO *HddInfo; + UINT64 Supports; + + // + // Note - This routine use to return immediately if Private->PciInterrup= tLine + // was true. Routine changed since resets etc can cause not all + // PciIo protocols to be registered the first time through. + // New algorithm is to do the copy $PIR table on first pass and save + // HandleCount on first pass. If subsequent passes LocateHandleBuffer gi= ves + // a larger handle count then proceed with body of function else return + // EFI_ALREADY_STARTED. In addition check if PCI device InterruptLine != =3D 0. + // If zero then function unprogrammed else skip function. + // + Legacy8259 =3D Private->Legacy8259; + LegacyInterrupt =3D Private->LegacyInterrupt; + LegacyBiosPlatform =3D Private->LegacyBiosPlatform; + + LegacyBiosPlatform->GetRoutingTable ( + Private->LegacyBiosPlatform, + (VOID *) &RoutingTable, + &RoutingTableEntries, + (VOID *) &PirqTable, + &PirqTableSize, + NULL, + NULL + ); + CreateBridgeTable (RoutingTable, RoutingTableEntries); + + if (!Private->PciInterruptLine) { + CopyPirqTable ( + Private, + RoutingTable, + RoutingTableEntries, + PirqTable, + PirqTableSize + ); + } + + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + if (HandleCount =3D=3D mHandleCount) { + FreePool (HandleBuffer); + return EFI_ALREADY_STARTED; + } + + if (mHandleCount =3D=3D 0x00) { + mHandleCount =3D HandleCount; + } + + for (Index =3D 0; Index < HandleCount; Index++) { + // + // If VGA then only do VGA to allow drives fore time to spin up + // otherwise assign PCI IRQs to all potential devices. + // + if ((mVgaInstallationInProgress) && (HandleBuffer[Index] !=3D mVgaHand= le)) { + continue; + } else { + // + // Force code to go through all handles next time called if video. + // This will catch case where HandleCount doesn't change but want + // to get drive info etc. + // + mHandleCount =3D 0x00; + } + + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + ASSERT_EFI_ERROR (Status); + + // + // Test whether the device can be enabled or not. + // If it can't be enabled, then just skip it to avoid further operatio= n. + // + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + Command =3D PciConfigHeader.Hdr.Command; + + // + // Note PciIo->Attributes does not program the PCI command register + // + Status =3D PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + if (!EFI_ERROR (Status)) { + Supports &=3D (UINT64)EFI_PCI_DEVICE_ENABLE; + Status =3D PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + Supports, + NULL + ); + } + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x04, 1, &Command); + + if (EFI_ERROR (Status)) { + continue; + } + + InterruptPin =3D PciConfigHeader.Device.InterruptPin; + + if ((InterruptPin !=3D 0) && (PciConfigHeader.Device.InterruptLine =3D= =3D PCI_INT_LINE_UNKNOWN)) { + PciIo->GetLocation ( + PciIo, + &PciSegment, + &PciBus, + &PciDevice, + &PciFunction + ); + // + // Translate PIRQ index back thru busses to slot bus with InterruptP= in + // zero based + // + InterruptPin -=3D 1; + + Status =3D GetBaseBus ( + Private, + PciBus, + PciDevice, + RoutingTable, + RoutingTableEntries + ); + + if (Status =3D=3D EFI_NOT_FOUND) { + TranslateBusPirq ( + Private, + &PciBus, + &PciDevice, + &PciFunction, + &InterruptPin + ); + } + // + // Translate InterruptPin(0-3) into PIRQ + // + Status =3D LegacyBiosPlatform->TranslatePirq ( + LegacyBiosPlatform, + PciBus, + (PciDevice << 3), + PciFunction, + &InterruptPin, + &PciIrq + ); + // + // TranslatePirq() should never fail or we are in trouble + // If it does return failure status, check your PIRQ routing table t= o see if some item is missing or incorrect + // + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Translate Pirq Failed - Status =3D %r\n ", S= tatus)); + continue; + } + + LegacyInterrupt->WritePirq ( + LegacyInterrupt, + InterruptPin, + PciIrq + ); + + // + // Check if device has an OPROM associated with it. + // If not invoke special 16-bit function, to allow 16-bit + // code to install an interrupt handler. + // + Status =3D LegacyBiosCheckPciRom ( + &Private->LegacyBios, + HandleBuffer[Index], + NULL, + NULL, + &Flags + ); + if ((EFI_ERROR (Status)) && (PciConfigHeader.Hdr.ClassCode[2] =3D=3D= PCI_CLASS_MASS_STORAGE)) { + // + // Device has no OPROM associated with it and is a mass storage + // device. It needs to have an PCI IRQ handler installed. To + // correctly install the handler we need to insure device is + // connected. The device may just have register itself but not + // been connected. Re-read PCI config space after as it can + // change + // + // + // Get IDE Handle. If matches handle then skip ConnectController + // since ConnectController may force native mode and we don't + // want that for primary IDE controller + // + MassStorageHandleCount =3D 0; + MassStorageHandleBuffer =3D NULL; + LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformIdeHandle, + 0, + &MassStorageHandleBuffer, + &MassStorageHandleCount, + NULL + ); + + HddInfo =3D &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0]; + + LegacyBiosBuildIdeData (Private, &HddInfo, 0); + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + + for (MassStorageHandleIndex =3D 0; MassStorageHandleIndex < MassSt= orageHandleCount; MassStorageHandleIndex++) { + if (MassStorageHandleBuffer[MassStorageHandleIndex] =3D=3D Handl= eBuffer[Index]) { + // + // InstallLegacyIrqHandler according to Platform requirement + // + InstallLegacyIrqHandler ( + Private, + PciIo, + PciIrq, + &PciConfigHeader + ); + break; + } + } + } + // + // Write InterruptPin and enable 8259. + // + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint8, + 0x3c, + 1, + &PciIrq + ); + Private->IntThunk->EfiToLegacy16BootTable.PciIrqMask =3D (UINT16) (P= rivate->IntThunk->EfiToLegacy16BootTable.PciIrqMask | (UINT16) (1 << PciIrq= )); + + Legacy8259->GetMask ( + Legacy8259, + &LegMask, + &LegEdgeLevel, + NULL, + NULL + ); + + LegMask =3D (UINT16) (LegMask & (UINT16)~(1 << PciIrq)); + LegEdgeLevel =3D (UINT16) (LegEdgeLevel | (UINT16) (1 << PciIrq)); + Legacy8259->SetMask ( + Legacy8259, + &LegMask, + &LegEdgeLevel, + NULL, + NULL + ); + } + } + FreePool (HandleBuffer); + return EFI_SUCCESS; +} + + +/** + Find & verify PnP Expansion header in ROM image + + @param Private Protocol instance pointer. + @param FirstHeader 1 =3D Find first header, 0 =3D Find succe= ssive headers + @param PnpPtr Input Rom start if FirstHeader =3D1, Curr= ent Header + otherwise Output Next header, if it exists + + @retval EFI_SUCCESS Next Header found at BasePnpPtr + @retval EFI_NOT_FOUND No more headers + +**/ +EFI_STATUS +FindNextPnpExpansionHeader ( + IN LEGACY_BIOS_INSTANCE *Private, + IN BOOLEAN FirstHeader, + IN OUT LEGACY_PNP_EXPANSION_HEADER **PnpPtr + + ) +{ + UINTN TempData; + LEGACY_PNP_EXPANSION_HEADER *LocalPnpPtr; + LocalPnpPtr =3D *PnpPtr; + if (FirstHeader =3D=3D FIRST_INSTANCE) { + mBasePnpPtr =3D LocalPnpPtr; + mBbsRomSegment =3D (UINT16) ((UINTN) mBasePnpPtr >> 4); + // + // Offset 0x1a gives offset to PnP expansion header for the first + // instance, there after the structure gives the offset to the next + // structure + // + LocalPnpPtr =3D (LEGACY_PNP_EXPANSION_HEADER *) ((UINT8 *) LocalPnpPtr= + 0x1a); + TempData =3D (*((UINT16 *) LocalPnpPtr)); + } else { + TempData =3D (UINT16) LocalPnpPtr->NextHeader; + } + + LocalPnpPtr =3D (LEGACY_PNP_EXPANSION_HEADER *) (((UINT8 *) mBasePnpPtr = + TempData)); + + // + // Search for PnP table in Shadowed ROM + // + *PnpPtr =3D LocalPnpPtr; + if (*(UINT32 *) LocalPnpPtr =3D=3D SIGNATURE_32 ('$', 'P', 'n', 'P')) { + return EFI_SUCCESS; + } else { + return EFI_NOT_FOUND; + } +} + + +/** + Update list of Bev or BCV table entries. + + @param Private Protocol instance pointer. + @param RomStart Table of ROM start address in RAM/ROM. Pc= iIo _ + Handle to PCI IO for this device + @param PciIo Instance of PCI I/O Protocol + + @retval EFI_SUCCESS Always should succeed. + +**/ +EFI_STATUS +UpdateBevBcvTable ( + IN LEGACY_BIOS_INSTANCE *Private, + IN EFI_LEGACY_EXPANSION_ROM_HEADER *RomStart, + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + VOID *RomEnd; + BBS_TABLE *BbsTable; + UINTN BbsIndex; + EFI_LEGACY_EXPANSION_ROM_HEADER *PciPtr; + LEGACY_PNP_EXPANSION_HEADER *PnpPtr; + BOOLEAN Instance; + EFI_STATUS Status; + UINTN Segment; + UINTN Bus; + UINTN Device; + UINTN Function; + UINT8 Class; + UINT16 DeviceType; + Segment =3D 0; + Bus =3D 0; + Device =3D 0; + Function =3D 0; + Class =3D 0; + DeviceType =3D BBS_UNKNOWN; + + // + // Skip floppy and 2*onboard IDE controller entries(Master/Slave per + // controller). + // + BbsIndex =3D Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries; + + BbsTable =3D (BBS_TABLE*)(UINTN) Private->IntThunk->EfiToLegacy16BootTa= ble.BbsTable; + PnpPtr =3D (LEGACY_PNP_EXPANSION_HEADER *) RomStart; + PciPtr =3D (EFI_LEGACY_EXPANSION_ROM_HEADER *) RomStart; + + RomEnd =3D (VOID *) (PciPtr->Size512 * 512 + (UINTN) PciPtr); + Instance =3D FIRST_INSTANCE; + // + // OPROMs like PXE may not be tied to a piece of hardware and thus + // don't have a PciIo associated with them + // + if (PciIo !=3D NULL) { + PciIo->GetLocation ( + PciIo, + &Segment, + &Bus, + &Device, + &Function + ); + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + 0x0b, + 1, + &Class + ); + + if (Class =3D=3D PCI_CLASS_MASS_STORAGE) { + DeviceType =3D BBS_HARDDISK; + } else { + if (Class =3D=3D PCI_CLASS_NETWORK) { + DeviceType =3D BBS_EMBED_NETWORK; + } + } + } + + while (TRUE) { + Status =3D FindNextPnpExpansionHeader (Private, Instance, &PnpPtr); + Instance =3D NOT_FIRST_INSTANCE; + if (EFI_ERROR (Status)) { + break; + } + // + // There can be additional $PnP headers within the OPROM. + // Example: SCSI can have one per drive. + // + BbsTable[BbsIndex].BootPriority =3D BBS_UNPRIORITIZED_ENTR= Y; + BbsTable[BbsIndex].DeviceType =3D DeviceType; + BbsTable[BbsIndex].Bus =3D (UINT32) Bus; + BbsTable[BbsIndex].Device =3D (UINT32) Device; + BbsTable[BbsIndex].Function =3D (UINT32) Function; + BbsTable[BbsIndex].StatusFlags.OldPosition =3D 0; + BbsTable[BbsIndex].StatusFlags.Reserved1 =3D 0; + BbsTable[BbsIndex].StatusFlags.Enabled =3D 0; + BbsTable[BbsIndex].StatusFlags.Failed =3D 0; + BbsTable[BbsIndex].StatusFlags.MediaPresent =3D 0; + BbsTable[BbsIndex].StatusFlags.Reserved2 =3D 0; + BbsTable[BbsIndex].Class =3D PnpPtr->Class; + BbsTable[BbsIndex].SubClass =3D PnpPtr->SubClass; + BbsTable[BbsIndex].DescStringOffset =3D PnpPtr->ProductNamePoi= nter; + BbsTable[BbsIndex].DescStringSegment =3D mBbsRomSegment; + BbsTable[BbsIndex].MfgStringOffset =3D PnpPtr->MfgPointer; + BbsTable[BbsIndex].MfgStringSegment =3D mBbsRomSegment; + BbsTable[BbsIndex].BootHandlerSegment =3D mBbsRomSegment; + + // + // Have seen case where PXE base code have PnP expansion ROM + // header but no Bcv or Bev vectors. + // + if (PnpPtr->Bcv !=3D 0) { + BbsTable[BbsIndex].BootHandlerOffset =3D PnpPtr->Bcv; + ++BbsIndex; + } + + if (PnpPtr->Bev !=3D 0) { + BbsTable[BbsIndex].BootHandlerOffset =3D PnpPtr->Bev; + BbsTable[BbsIndex].DeviceType =3D BBS_BEV_DEVICE; + ++BbsIndex; + } + + if ((PnpPtr =3D=3D (LEGACY_PNP_EXPANSION_HEADER *) PciPtr) || (PnpPtr = > (LEGACY_PNP_EXPANSION_HEADER *) RomEnd)) { + break; + } + } + + BbsTable[BbsIndex].BootPriority =3D BBS_IGNORE_ENTRY; + Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries =3D (UINT32) = BbsIndex; + return EFI_SUCCESS; +} + + +/** + Shadow all the PCI legacy ROMs. Use data from the Legacy BIOS Protocol + to chose the order. Skip any devices that have already have legacy + BIOS run. + + @param Private Protocol instance pointer. + + @retval EFI_SUCCESS Succeed. + @retval EFI_UNSUPPORTED Cannot get VGA device handle. + +**/ +EFI_STATUS +PciShadowRoms ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + UINTN Index; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_HANDLE VgaHandle; + EFI_HANDLE FirstHandle; + VOID **RomStart; + UINTN Flags; + PCI_TYPE00 PciConfigHeader; + UINT16 *Command; + UINT64 Supports; + + // + // Make the VGA device first + // + Status =3D Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformVgaHandle, + 0, + &HandleBuffer, + &HandleCount, + NULL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + VgaHandle =3D HandleBuffer[0]; + + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Place the VGA handle as first. + // + for (Index =3D 0; Index < HandleCount; Index++) { + if (HandleBuffer[Index] =3D=3D VgaHandle) { + FirstHandle =3D HandleBuffer[0]; + HandleBuffer[0] =3D HandleBuffer[Index]; + HandleBuffer[Index] =3D FirstHandle; + break; + } + } + // + // Allocate memory to save Command WORD from each device. We do this + // to restore devices to same state as EFI after switching to legacy. + // + Command =3D (UINT16 *) AllocatePool ( + sizeof (UINT16) * (HandleCount + 1) + ); + if (NULL =3D=3D Command) { + FreePool (HandleBuffer); + return EFI_OUT_OF_RESOURCES; + } + // + // Disconnect all EFI devices first. This covers cases where alegacy BIOS + // may control multiple PCI devices. + // + for (Index =3D 0; Index < HandleCount; Index++) { + + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + ASSERT_EFI_ERROR (Status); + + // + // Save command register for "connect" loop + // + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + Command[Index] =3D PciConfigHeader.Hdr.Command; + // + // Skip any device that already has a legacy ROM run + // + Status =3D IsLegacyRom (HandleBuffer[Index]); + if (!EFI_ERROR (Status)) { + continue; + } + // + // Stop EFI Drivers with oprom. + // + gBS->DisconnectController ( + HandleBuffer[Index], + NULL, + NULL + ); + } + // + // For every device that has not had a legacy ROM started. Start a legac= y ROM. + // + for (Index =3D 0; Index < HandleCount; Index++) { + + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + + ASSERT_EFI_ERROR (Status); + + // + // Here make sure if one VGA have been shadowed, + // then wil not shadowed another one. + // + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + + // + // Only one Video OPROM can be given control in BIOS phase. If there a= re multiple Video devices, + // one will work in legacy mode (OPROM will be given control) and + // other Video devices will work in native mode (OS driver will handle= these devices). + // + if (IS_PCI_DISPLAY (&Pci) && Index !=3D 0) { + continue; + } + // + // Skip any device that already has a legacy ROM run + // + Status =3D IsLegacyRom (HandleBuffer[Index]); + if (!EFI_ERROR (Status)) { + continue; + } + + // + // If legacy VBIOS Oprom has not been dispatched before, install legac= y VBIOS here. + // + if (IS_PCI_DISPLAY (&Pci) && Index =3D=3D 0) { + Status =3D LegacyBiosInstallVgaRom (Private); + // + // A return status of EFI_NOT_FOUND is considered valid (No EFI + // driver is controlling video). + // + ASSERT ((Status =3D=3D EFI_SUCCESS) || (Status =3D=3D EFI_NOT_FOUND)= ); + continue; + } + + // + // Install legacy ROM + // + Status =3D LegacyBiosInstallPciRom ( + &Private->LegacyBios, + HandleBuffer[Index], + NULL, + &Flags, + NULL, + NULL, + (VOID **) &RomStart, + NULL + ); + if (EFI_ERROR (Status)) { + if (!((Status =3D=3D EFI_UNSUPPORTED) && (Flags =3D=3D NO_ROM))) { + continue; + } + } + // + // Restore Command register so legacy has same devices enabled or disa= bled + // as EFI. + // If Flags =3D NO_ROM use command register as is. This covers the + // following cases: + // Device has no ROMs associated with it. + // Device has ROM associated with it but was already + // installed. + // =3D ROM_FOUND but not VALID_LEGACY_ROM, disable it. + // =3D ROM_FOUND and VALID_LEGACY_ROM, enable it. + // + if ((Flags & ROM_FOUND) =3D=3D ROM_FOUND) { + if ((Flags & VALID_LEGACY_ROM) =3D=3D 0) { + Command[Index] =3D 0; + } else { + // + // For several VGAs, only one of them can be enabled. + // + Status =3D PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + if (!EFI_ERROR (Status)) { + Supports &=3D (UINT64)EFI_PCI_DEVICE_ENABLE; + Status =3D PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + Supports, + NULL + ); + } + if (!EFI_ERROR (Status)) { + Command[Index] =3D 0x1f; + } + } + } + + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + 0x04, + 1, + &Command[Index] + ); + } + + FreePool (Command); + FreePool (HandleBuffer); + return EFI_SUCCESS; +} + + +/** + Test to see if a legacy PCI ROM exists for this device. Optionally return + the Legacy ROM instance for this PCI device. + + @param This Protocol instance pointer. + @param PciHandle The PCI PC-AT OPROM from this devices ROM= BAR will + be loaded + @param RomImage Return the legacy PCI ROM for this device + @param RomSize Size of ROM Image + @param Flags Indicates if ROM found and if PC-AT. + + @retval EFI_SUCCESS Legacy Option ROM available for this devi= ce + @retval EFI_UNSUPPORTED Legacy Option ROM not supported. + +**/ +EFI_STATUS +EFIAPI +LegacyBiosCheckPciRom ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, OPTIONAL + OUT UINTN *RomSize, OPTIONAL + OUT UINTN *Flags + ) +{ + return LegacyBiosCheckPciRomEx ( + This, + PciHandle, + RomImage, + RomSize, + NULL, + Flags, + NULL, + NULL + ); + +} + +/** + + Routine Description: + Test to see if a legacy PCI ROM exists for this device. Optionally ret= urn + the Legacy ROM instance for this PCI device. + + @param[in] This Protocol instance pointer. + @param[in] PciHandle The PCI PC-AT OPROM from this devic= es ROM BAR will be loaded + @param[out] RomImage Return the legacy PCI ROM for this = device + @param[out] RomSize Size of ROM Image + @param[out] RuntimeImageLength Runtime size of ROM Image + @param[out] Flags Indicates if ROM found and if PC-AT. + @param[out] OpromRevision Revision of the PCI Rom + @param[out] ConfigUtilityCodeHeaderPointer of Configuration Utility Co= de Header + + @return EFI_SUCCESS Legacy Option ROM available for this de= vice + @return EFI_ALREADY_STARTED This device is already managed by its O= prom + @return EFI_UNSUPPORTED Legacy Option ROM not supported. + +**/ +EFI_STATUS +LegacyBiosCheckPciRomEx ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, OPTIONAL + OUT UINTN *RomSize, OPTIONAL + OUT UINTN *RuntimeImageLength, OPTIONAL + OUT UINTN *Flags, OPTIONAL + OUT UINT8 *OpromRevision, OPTIONAL + OUT VOID **ConfigUtilityCodeHeader OPTIONAL + ) +{ + EFI_STATUS Status; + LEGACY_BIOS_INSTANCE *Private; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN LocalRomSize; + VOID *LocalRomImage; + PCI_TYPE00 PciConfigHeader; + VOID *LocalConfigUtilityCodeHeader; + + LocalConfigUtilityCodeHeader =3D NULL; + *Flags =3D NO_ROM; + Status =3D gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // See if the option ROM for PciHandle has already been executed + // + Status =3D IsLegacyRom (PciHandle); + if (!EFI_ERROR (Status)) { + *Flags |=3D (UINTN)(ROM_FOUND | VALID_LEGACY_ROM); + return EFI_SUCCESS; + } + // + // Check for PCI ROM Bar + // + LocalRomSize =3D (UINTN) PciIo->RomSize; + LocalRomImage =3D PciIo->RomImage; + if (LocalRomSize !=3D 0) { + *Flags |=3D ROM_FOUND; + } + + // + // PCI specification states you should check VendorId and Device Id. + // + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + + Private =3D LEGACY_BIOS_INSTANCE_FROM_THIS (This); + Status =3D GetPciLegacyRom ( + Private->Csm16PciInterfaceVersion, + PciConfigHeader.Hdr.VendorId, + PciConfigHeader.Hdr.DeviceId, + &LocalRomImage, + &LocalRomSize, + RuntimeImageLength, + OpromRevision, + &LocalConfigUtilityCodeHeader + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + *Flags |=3D VALID_LEGACY_ROM; + + // + // See if Configuration Utility Code Header valid + // + if (LocalConfigUtilityCodeHeader !=3D NULL) { + *Flags |=3D ROM_WITH_CONFIG; + } + + if (ConfigUtilityCodeHeader !=3D NULL) { + *ConfigUtilityCodeHeader =3D LocalConfigUtilityCodeHeader; + } + + if (RomImage !=3D NULL) { + *RomImage =3D LocalRomImage; + } + + if (RomSize !=3D NULL) { + *RomSize =3D LocalRomSize; + } + + return EFI_SUCCESS; +} + +/** + Load a legacy PC-AT OPROM on the PciHandle device. Return information + about how many disks were added by the OPROM and the shadow address and + size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C: + + @retval EFI_SUCCESS Legacy ROM loaded for this device + @retval EFI_NOT_FOUND No PS2 Keyboard found + +**/ +EFI_STATUS +EnablePs2Keyboard ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + EFI_ISA_IO_PROTOCOL *IsaIo; + UINTN Index; + + // + // Get SimpleTextIn and find PS2 controller + // + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleTextInProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + for (Index =3D 0; Index < HandleCount; Index++) { + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status =3D gBS->OpenProtocol ( + HandleBuffer[Index], + &gEfiIsaIoProtocolGuid, + (VOID **) &IsaIo, + NULL, + HandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + ); + + if (!EFI_ERROR (Status)) { + // + // Use the ISA I/O Protocol to see if Controller is the Keyboard + // controller + // + if (IsaIo->ResourceList->Device.HID !=3D EISA_PNP_ID (0x303) || IsaI= o->ResourceList->Device.UID !=3D 0) { + Status =3D EFI_UNSUPPORTED; + } + + gBS->CloseProtocol ( + HandleBuffer[Index], + &gEfiIsaIoProtocolGuid, + NULL, + HandleBuffer[Index] + ); + } + + if (!EFI_ERROR (Status)) { + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE); + } + } + FreePool (HandleBuffer); + return EFI_SUCCESS; +} + + +/** + Load a legacy PC-AT OpROM for VGA controller. + + @param Private Driver private data. + + @retval EFI_SUCCESS Legacy ROM successfully installed for thi= s device. + @retval EFI_DEVICE_ERROR No VGA device handle found, or native EFI= video + driver cannot be successfully disconnecte= d, or VGA + thunk driver cannot be successfully conne= cted. + +**/ +EFI_STATUS +LegacyBiosInstallVgaRom ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + EFI_HANDLE VgaHandle; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_HANDLE *ConnectHandleBuffer; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 PciConfigHeader; + UINT64 Supports; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + UINTN EntryCount; + UINTN Index; + VOID *Interface; + + // + // EfiLegacyBiosGuild attached to a device implies that there is a legacy + // BIOS associated with that device. + // + // There are 3 cases to consider. + // Case 1: No EFI driver is controlling the video. + // Action: Return EFI_SUCCESS from DisconnectController, search + // video thunk driver, and connect it. + // Case 2: EFI driver is controlling the video and EfiLegacyBiosGuid is + // not on the image handle. + // Action: Disconnect EFI driver. + // ConnectController for video thunk + // Case 3: EFI driver is controlling the video and EfiLegacyBiosGuid is + // on the image handle. + // Action: Do nothing and set Private->VgaInstalled =3D TRUE. + // Then this routine is not called any more. + // + // + // Get the VGA device. + // + Status =3D Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformVgaHandle, + 0, + &HandleBuffer, + &HandleCount, + NULL + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + VgaHandle =3D HandleBuffer[0]; + + // + // Check whether video thunk driver already starts. + // + Status =3D gBS->OpenProtocolInformation ( + VgaHandle, + &gEfiPciIoProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index =3D 0; Index < EntryCount; Index++) { + if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != =3D 0) { + Status =3D gBS->HandleProtocol ( + OpenInfoBuffer[Index].AgentHandle, + &gEfiLegacyBiosGuid, + (VOID **) &Interface + ); + if (!EFI_ERROR (Status)) { + // + // This should be video thunk driver which is managing video device + // So it need not start again + // + DEBUG ((EFI_D_INFO, "Video thunk driver already start! Return!\n")= ); + Private->VgaInstalled =3D TRUE; + return EFI_SUCCESS; + } + } + } + + // + // Kick off the native EFI driver + // + Status =3D gBS->DisconnectController ( + VgaHandle, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + if (Status !=3D EFI_NOT_FOUND) { + return EFI_DEVICE_ERROR; + } else { + return Status; + } + } + // + // Find all the Thunk Driver + // + HandleBuffer =3D NULL; + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiLegacyBiosGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + ASSERT_EFI_ERROR (Status); + ConnectHandleBuffer =3D (EFI_HANDLE *) AllocatePool (sizeof (EFI_HANDLE)= * (HandleCount + 1)); + ASSERT (ConnectHandleBuffer !=3D NULL); + + CopyMem ( + ConnectHandleBuffer, + HandleBuffer, + sizeof (EFI_HANDLE) * HandleCount + ); + ConnectHandleBuffer[HandleCount] =3D NULL; + + FreePool (HandleBuffer); + + // + // Enable the device and make sure VGA cycles are being forwarded to thi= s VGA device + // + Status =3D gBS->HandleProtocol ( + VgaHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + ASSERT_EFI_ERROR (Status); + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + + Status =3D PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + if (!EFI_ERROR (Status)) { + Supports &=3D (UINT64)(EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VG= A_MEMORY | \ + EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUT= E_VGA_IO_16); + Status =3D PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + Supports, + NULL + ); + } + + if (Status =3D=3D EFI_SUCCESS) { + Private->VgaInstalled =3D TRUE; + + // + // Attach the VGA thunk driver. + // Assume the video is installed. This prevents potential of infinite = recursion. + // + Status =3D gBS->ConnectController ( + VgaHandle, + ConnectHandleBuffer, + NULL, + TRUE + ); + } + + FreePool (ConnectHandleBuffer); + + if (EFI_ERROR (Status)) { + + Private->VgaInstalled =3D FALSE; + + // + // Reconnect the EFI VGA driver. + // + gBS->ConnectController (VgaHandle, NULL, NULL, TRUE); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Load a legacy PC-AT OpROM. + + @param This Protocol instance pointer. + @param Private Driver's private data. + @param PciHandle The EFI handle for the PCI device= . It could be + NULL if the OpROM ima= ge is not associated with + any device. + @param OpromRevision The revision of PCI PC-AT ROM image. + @param RomImage Pointer to PCI PC-AT ROM image heade= r. It must not + be NULL. + @param ImageSize Size of the PCI PC-AT ROM image. + @param RuntimeImageLength On input is the max runtime image length= indicated by the PCIR structure + On output is the actua= l runtime image length + @param DiskStart Disk number of first device hook= ed by the ROM. If + DiskStart is the same = as DiskEnd no disked were + hooked. + @param DiskEnd Disk number of the last device h= ooked by the ROM. + @param RomShadowAddress Shadow address of PC-AT ROM + + @retval EFI_SUCCESS Legacy ROM loaded for this device + @retval EFI_OUT_OF_RESOURCES No more space for this ROM + +**/ +EFI_STATUS +EFIAPI +LegacyBiosInstallRom ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN LEGACY_BIOS_INSTANCE *Private, + IN EFI_HANDLE PciHandle, + IN UINT8 OpromRevision, + IN VOID *RomImage, + IN UINTN ImageSize, + IN OUT UINTN *RuntimeImageLength, + OUT UINT8 *DiskStart, OPTIONAL + OUT UINT8 *DiskEnd, OPTIONAL + OUT VOID **RomShadowAddress OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_STATUS PciEnableStatus; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 LocalDiskStart; + UINT8 LocalDiskEnd; + UINTN Segment; + UINTN Bus; + UINTN Device; + UINTN Function; + EFI_IA32_REGISTER_SET Regs; + UINT8 VideoMode; + UINT8 OldVideoMode; + EFI_TIME BootTime; + UINT32 *BdaPtr; + UINT32 LocalTime; + UINT32 StartBbsIndex; + UINT32 EndBbsIndex; + UINT32 MaxRomAddr; + UINTN TempData; + UINTN InitAddress; + UINTN RuntimeAddress; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + UINT32 Granularity; + + PciIo =3D NULL; + LocalDiskStart =3D 0; + LocalDiskEnd =3D 0; + Segment =3D 0; + Bus =3D 0; + Device =3D 0; + Function =3D 0; + VideoMode =3D 0; + OldVideoMode =3D 0; + PhysicalAddress =3D 0; + MaxRomAddr =3D PcdGet32 (PcdEndOpromShadowAddress); + + if ((Private->Legacy16Table->TableLength >=3D OFFSET_OF(EFI_COMPATIBILIT= Y16_TABLE, HiPermanentMemoryAddress)) && + (Private->Legacy16Table->UmaAddress !=3D 0) && + (Private->Legacy16Table->UmaSize !=3D 0) && + (MaxRomAddr > (Private->Legacy16Table->UmaAddress))) { + MaxRomAddr =3D Private->Legacy16Table->UmaAddress; + } + + + PciProgramAllInterruptLineRegisters (Private); + + if ((OpromRevision >=3D 3) && (Private->Csm16PciInterfaceVersion >=3D 0x= 0300)) { + // + // CSM16 3.0 meets PCI 3.0 OpROM + // first test if there is enough space for its INIT code + // + PhysicalAddress =3D CONVENTIONAL_MEMORY_TOP; + Status =3D gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesCode, + EFI_SIZE_TO_PAGES (ImageSize), + &PhysicalAddress + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RE= SOURCES (no more space for OpROM)\n", __LINE__)); + // + // Report Status Code to indicate that there is no enough space for = OpROM + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPA= CE) + ); + return EFI_OUT_OF_RESOURCES; + } + InitAddress =3D (UINTN) PhysicalAddress; + // + // then test if there is enough space for its RT code + // + RuntimeAddress =3D Private->OptionRom; + if (RuntimeAddress + *RuntimeImageLength > MaxRomAddr) { + DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RE= SOURCES (no more space for OpROM)\n", __LINE__)); + gBS->FreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (ImageSize)); + // + // Report Status Code to indicate that there is no enough space for = OpROM + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPA= CE) + ); + return EFI_OUT_OF_RESOURCES; + } + } else { + // CSM16 3.0 meets PCI 2.x OpROM + // CSM16 2.x meets PCI 2.x/3.0 OpROM + // test if there is enough space for its INIT code + // + InitAddress =3D PCI_START_ADDRESS (Private->OptionRom); + if (InitAddress + ImageSize > MaxRomAddr) { + DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RE= SOURCES (no more space for OpROM)\n", __LINE__)); + // + // Report Status Code to indicate that there is no enough space for = OpROM + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPA= CE) + ); + return EFI_OUT_OF_RESOURCES; + } + + RuntimeAddress =3D InitAddress; + } + + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + (UINT32) RuntimeAddress, + (UINT32) ImageSize, + &Granularity + ); + + DEBUG ((EFI_D_INFO, " Shadowing OpROM init/runtime/isize =3D %x/%x/%x\n"= , InitAddress, RuntimeAddress, ImageSize)); + + CopyMem ((VOID *) InitAddress, RomImage, ImageSize); + + // + // Read the highest disk number "installed: and assume a new disk will + // show up on the first drive past the current value. + // There are several considerations here: + // 1. Non-BBS compliant drives will change 40:75 but 16-bit CSM will undo + // the change until boot selection time frame. + // 2. BBS compliants drives will not change 40:75 until boot time. + // 3. Onboard IDE controllers will change 40:75 + // + ACCESS_PAGE0_CODE ( + LocalDiskStart =3D (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80); + if ((Private->Disk4075 + 0x80) < LocalDiskStart) { + // + // Update table since onboard IDE drives found + // + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegme= nt =3D 0xff; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus = =3D 0xff; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevic= e =3D 0xff; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunct= ion =3D 0xff; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDri= veNumber =3D (UINT8) (Private->Disk4075 + 0x80); + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDrive= Number =3D LocalDiskStart; + Private->LegacyEfiHddTableIndex ++; + Private->Disk4075 =3D (UINT8) (LocalDiskStart & 0x7f); + Private->DiskEnd =3D LocalDiskStart; + } + + if (PciHandle !=3D mVgaHandle) { + + EnablePs2Keyboard (); + + // + // Store current mode settings since PrepareToScanRom may change mod= e. + // + VideoMode =3D *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE)); + } + ); + + // + // Notify the platform that we are about to scan the ROM + // + Status =3D Private->LegacyBiosPlatform->PlatformHooks ( + Private->LegacyBiosPlatform, + EfiPlatformHookPrepareToScanRom, + 0, + PciHandle, + &InitAddress, + NULL, + NULL + ); + + // + // If Status returned is EFI_UNSUPPORTED then abort due to platform + // policy. + // + if (Status =3D=3D EFI_UNSUPPORTED) { + goto Done; + } + + // + // Report corresponding status code + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_CSM_LEGACY_ROM_INIT) + ); + + // + // Generate number of ticks since midnight for BDA. Some OPROMs require + // this. Place result in 40:6C-6F + // + gRT->GetTime (&BootTime, NULL); + LocalTime =3D BootTime.Hour * 3600 + BootTime.Minute * 60 + BootTime.Sec= ond; + + // + // Multiply result by 18.2 for number of ticks since midnight. + // Use 182/10 to avoid floating point math. + // + ACCESS_PAGE0_CODE ( + LocalTime =3D (LocalTime * 182) / 10; + BdaPtr =3D (UINT32 *) ((UINTN) 0x46C); + *BdaPtr =3D LocalTime; + ); + + // + // Pass in handoff data + // + PciEnableStatus =3D EFI_UNSUPPORTED; + ZeroMem (&Regs, sizeof (Regs)); + if (PciHandle !=3D NULL) { + + Status =3D gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + ASSERT_EFI_ERROR (Status); + + // + // Enable command register. + // + PciEnableStatus =3D PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + + PciIo->GetLocation ( + PciIo, + &Segment, + &Bus, + &Device, + &Function + ); + DEBUG ((EFI_D_INFO, "Shadowing OpROM on the PCI device %x/%x/%x\n", Bu= s, Device, Function)); + } + + mIgnoreBbsUpdateFlag =3D FALSE; + Regs.X.AX =3D Legacy16DispatchOprom; + + // + // Generate DispatchOpRomTable data + // + Private->IntThunk->DispatchOpromTable.PnPInstallationCheckSegment =3D Pr= ivate->Legacy16Table->PnPInstallationCheckSegment; + Private->IntThunk->DispatchOpromTable.PnPInstallationCheckOffset =3D Pr= ivate->Legacy16Table->PnPInstallationCheckOffset; + Private->IntThunk->DispatchOpromTable.OpromSegment =3D (U= INT16) (InitAddress >> 4); + Private->IntThunk->DispatchOpromTable.PciBus =3D (U= INT8) Bus; + Private->IntThunk->DispatchOpromTable.PciDeviceFunction =3D (U= INT8) ((Device << 3) | Function); + Private->IntThunk->DispatchOpromTable.NumberBbsEntries =3D (U= INT8) Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries; + Private->IntThunk->DispatchOpromTable.BbsTablePointer =3D (U= INT32) (UINTN) Private->BbsTablePtr; + Private->IntThunk->DispatchOpromTable.RuntimeSegment =3D (U= INT16)((OpromRevision < 3) ? 0xffff : (RuntimeAddress >> 4)); + TempData =3D (UINTN) &Private->IntThunk->DispatchOpromTable; + Regs.X.ES =3D EFI_SEGMENT ((UINT32) TempData); + Regs.X.BX =3D EFI_OFFSET ((UINT32) TempData); + // + // Skip dispatching ROM for those PCI devices that can not be enabled by= PciIo->Attributes + // Otherwise, it may cause the system to hang in some cases + // + if (!EFI_ERROR (PciEnableStatus)) { + DEBUG ((EFI_D_INFO, " Legacy16DispatchOprom - %02x/%02x/%02x\n", Bus, = Device, Function)); + Private->LegacyBios.FarCall86 ( + &Private->LegacyBios, + Private->Legacy16CallSegment, + Private->Legacy16CallOffset, + &Regs, + NULL, + 0 + ); + } else { + Regs.X.BX =3D 0; + } + + if (Private->IntThunk->DispatchOpromTable.NumberBbsEntries !=3D (UINT8) = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries) { + Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries =3D (UINT8= ) Private->IntThunk->DispatchOpromTable.NumberBbsEntries; + mIgnoreBbsUpdateFlag =3D TRUE; + } + // + // Check if non-BBS compliant drives found + // + if (Regs.X.BX !=3D 0) { + LocalDiskEnd =3D (UINT8) (LocalDiskStart + Regs.H.BL); + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment= =3D (UINT8) Segment; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus = =3D (UINT8) Bus; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice = =3D (UINT8) Device; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunctio= n =3D (UINT8) Function; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDrive= Number =3D Private->DiskEnd; + Private->DiskEnd =3D LocalDiskEnd; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNu= mber =3D Private->DiskEnd; + Private->LegacyEfiHddTableIndex +=3D 1; + } + // + // Skip video mode set, if installing VGA + // + if (PciHandle !=3D mVgaHandle) { + // + // Set mode settings since PrepareToScanRom may change mode + // + ACCESS_PAGE0_CODE ({ + OldVideoMode =3D *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE)); + }); + + if (VideoMode !=3D OldVideoMode) { + // + // The active video mode is changed, restore it to original mode. + // + Regs.H.AH =3D 0x00; + Regs.H.AL =3D VideoMode; + Private->LegacyBios.Int86 (&Private->LegacyBios, 0x10, &Regs); + } + } + // + // Regs.X.AX from the adapter initializion is ignored since some adapters + // do not follow the standard of setting AX =3D 0 on success. + // + // + // The ROM could have updated it's size so we need to read again. + // + if (((EFI_LEGACY_EXPANSION_ROM_HEADER *) RuntimeAddress)->Signature !=3D= PCI_EXPANSION_ROM_HEADER_SIGNATURE) { + // + // Now we check the signature (0xaa55) to judge whether the run-time c= ode is truly generated by INIT function. + // If signature is not valid, that means the INIT function didn't copy= the run-time code to RuntimeAddress. + // + *RuntimeImageLength =3D 0; + } else { + *RuntimeImageLength =3D ((EFI_LEGACY_EXPANSION_ROM_HEADER *) RuntimeAd= dress)->Size512 * 512; + } + + DEBUG ((EFI_D_INFO, " fsize =3D %x\n", *RuntimeImageLength)); + + // + // If OpROM runs in 2.0 mode + // + if (PhysicalAddress =3D=3D 0) { + if (*RuntimeImageLength < ImageSize) { + // + // Make area from end of shadowed rom to end of original rom all ffs + // + gBS->SetMem ((VOID *) (InitAddress + *RuntimeImageLength), ImageSize= - *RuntimeImageLength, 0xff); + } + } + + ACCESS_PAGE0_CODE ( + LocalDiskEnd =3D (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80); + ); + + // + // Allow platform to perform any required actions after the + // OPROM has been initialized. + // + Status =3D Private->LegacyBiosPlatform->PlatformHooks ( + Private->LegacyBiosPlatform, + EfiPlatformHookAfterRomInit, + 0, + PciHandle, + &RuntimeAddress, + NULL, + NULL + ); + if (PciHandle !=3D NULL) { + // + // If no PCI Handle then no header or Bevs. + // + if ((*RuntimeImageLength !=3D 0) && (!mIgnoreBbsUpdateFlag)) { + StartBbsIndex =3D Private->IntThunk->EfiToLegacy16BootTable.NumberBb= sEntries; + TempData =3D RuntimeAddress; + UpdateBevBcvTable ( + Private, + (EFI_LEGACY_EXPANSION_ROM_HEADER *) TempData, + PciIo + ); + EndBbsIndex =3D Private->IntThunk->EfiToLegacy16BootTable.NumberBb= sEntries; + LocalDiskEnd =3D (UINT8) (LocalDiskStart + (UINT8) (EndBbsIndex - S= tartBbsIndex)); + if (LocalDiskEnd !=3D LocalDiskStart) { + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSeg= ment =3D (UINT8) Segment; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus= =3D (UINT8) Bus; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDev= ice =3D (UINT8) Device; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFun= ction =3D (UINT8) Function; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartD= riveNumber =3D Private->DiskEnd; + Private->DiskEnd =3D LocalDiskEnd; + Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDri= veNumber =3D Private->DiskEnd; + Private->LegacyEfiHddTableIndex +=3D 1; + } + } + // + // Mark PCI device as having a legacy BIOS ROM loaded. + // + RomShadow ( + PciHandle, + (UINT32) RuntimeAddress, + (UINT32) *RuntimeImageLength, + LocalDiskStart, + LocalDiskEnd + ); + } + + // + // Stuff caller's OPTIONAL return parameters. + // + if (RomShadowAddress !=3D NULL) { + *RomShadowAddress =3D (VOID *) RuntimeAddress; + } + + if (DiskStart !=3D NULL) { + *DiskStart =3D LocalDiskStart; + } + + if (DiskEnd !=3D NULL) { + *DiskEnd =3D LocalDiskEnd; + } + + Private->OptionRom =3D (UINT32) (RuntimeAddress + *RuntimeImageLength); + + Status =3D EFI_SUCCESS; + +Done: + if (PhysicalAddress !=3D 0) { + // + // Free pages when OpROM is 3.0 + // + gBS->FreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (ImageSize)); + } + + // + // Insure all shadowed areas are locked + // + Private->LegacyRegion->Lock ( + Private->LegacyRegion, + 0xC0000, + 0x40000, + &Granularity + ); + + return Status; +} + +/** + Let IOMMU grant DMA access for the PCI device. + + @param PciHandle The EFI handle for the PCI device. + @param HostAddress The system memory address to map to the PC= I controller. + @param NumberOfBytes The number of bytes to map. + + @retval EFI_SUCCESS The DMA access is granted. +**/ +EFI_STATUS +IoMmuGrantAccess ( + IN EFI_HANDLE PciHandle, + IN EFI_PHYSICAL_ADDRESS HostAddress, + IN UINTN NumberOfBytes + ) +{ + EFI_PHYSICAL_ADDRESS DeviceAddress; + VOID *Mapping; + EFI_STATUS Status; + + if (PciHandle =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + Status =3D EFI_SUCCESS; + if (mIoMmu =3D=3D NULL) { + gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmu); + } + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->Map ( + mIoMmu, + EdkiiIoMmuOperationBusMasterCommonBuffer, + (VOID *)(UINTN)HostAddress, + &NumberOfBytes, + &DeviceAddress, + &Mapping + ); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "LegacyPci - IoMmuMap - %r\n", Status)); + } else { + ASSERT (DeviceAddress =3D=3D HostAddress); + Status =3D mIoMmu->SetAttribute ( + mIoMmu, + PciHandle, + Mapping, + EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE + ); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "LegacyPci - IoMmuSetAttribute - %r\n", Statu= s)); + } + } + } + return Status; +} + +/** + Load a legacy PC-AT OPROM on the PciHandle device. Return information + about how many disks were added by the OPROM and the shadow address and + size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C: + + @param This Protocol instance pointer. + @param PciHandle The PCI PC-AT OPROM from this devices ROM= BAR will + be loaded. This value is NULL if RomImage= is + non-NULL. This is the normal case. + @param RomImage A PCI PC-AT ROM image. This argument is n= on-NULL + if there is no hardware associated with t= he ROM + and thus no PciHandle, otherwise is must = be NULL. + Example is PXE base code. + @param Flags Indicates if ROM found and if PC-AT. + @param DiskStart Disk number of first device hooked by the= ROM. If + DiskStart is the same as DiskEnd no diske= d were + hooked. + @param DiskEnd Disk number of the last device hooked by = the ROM. + @param RomShadowAddress Shadow address of PC-AT ROM + @param RomShadowedSize Size of RomShadowAddress in bytes + + @retval EFI_SUCCESS Legacy ROM loaded for this device + @retval EFI_INVALID_PARAMETER PciHandle not found + @retval EFI_UNSUPPORTED There is no PCI ROM in the ROM BAR or no = onboard + ROM + +**/ +EFI_STATUS +EFIAPI +LegacyBiosInstallPciRom ( + IN EFI_LEGACY_BIOS_PROTOCOL * This, + IN EFI_HANDLE PciHandle, + IN VOID **RomImage, + OUT UINTN *Flags, + OUT UINT8 *DiskStart, OPTIONAL + OUT UINT8 *DiskEnd, OPTIONAL + OUT VOID **RomShadowAddress, OPTIONAL + OUT UINT32 *RomShadowedSize OPTIONAL + ) +{ + EFI_STATUS Status; + LEGACY_BIOS_INSTANCE *Private; + VOID *LocalRomImage; + UINTN ImageSize; + UINTN RuntimeImageLength; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE01 PciConfigHeader; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN PciSegment; + UINTN PciBus; + UINTN PciDevice; + UINTN PciFunction; + UINTN LastBus; + UINTN Index; + UINT8 OpromRevision; + UINT32 Granularity; + PCI_3_0_DATA_STRUCTURE *Pcir; + + OpromRevision =3D 0; + + Private =3D LEGACY_BIOS_INSTANCE_FROM_THIS (This); + if (Private->Legacy16Table->LastPciBus =3D=3D 0) { + // + // Get last bus number if not already found + // + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + + LastBus =3D 0; + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + if (EFI_ERROR (Status)) { + continue; + } + + Status =3D PciIo->GetLocation ( + PciIo, + &PciSegment, + &PciBus, + &PciDevice, + &PciFunction + ); + if (PciBus > LastBus) { + LastBus =3D PciBus; + } + } + + Private->LegacyRegion->UnLock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + Private->Legacy16Table->LastPciBus =3D (UINT8) LastBus; + Private->LegacyRegion->Lock ( + Private->LegacyRegion, + 0xE0000, + 0x20000, + &Granularity + ); + } + + *Flags =3D 0; + if ((PciHandle !=3D NULL) && (RomImage =3D=3D NULL)) { + // + // If PciHandle has OpRom to Execute + // and OpRom are all associated with Hardware + // + Status =3D gBS->HandleProtocol ( + PciHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo + ); + + if (!EFI_ERROR (Status)) { + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (PciConfigHeader) / sizeof (UINT32), + &PciConfigHeader + ); + + // + // if video installed & OPROM is video return + // + if ( + ( + ((PciConfigHeader.Hdr.ClassCode[2] =3D=3D PCI_CLASS_OLD) && + (PciConfigHeader.Hdr.ClassCode[1] =3D=3D PCI_CLASS_OLD_VGA)) + || + ((PciConfigHeader.Hdr.ClassCode[2] =3D=3D PCI_CLASS_DISPLAY) && + (PciConfigHeader.Hdr.ClassCode[1] =3D=3D PCI_CLASS_DISPLAY_VGA= )) + ) + && + (!Private->VgaInstalled) + ) { + mVgaInstallationInProgress =3D TRUE; + + // + // return EFI_UNSUPPORTED; + // + } + } + // + // To run any legacy image, the VGA needs to be installed first. + // if installing the video, then don't need the thunk as already insta= lled. + // + Status =3D Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformVgaHandle, + 0, + &HandleBuffer, + &HandleCount, + NULL + ); + + if (!EFI_ERROR (Status)) { + mVgaHandle =3D HandleBuffer[0]; + if ((!Private->VgaInstalled) && (PciHandle !=3D mVgaHandle)) { + // + // A return status of EFI_NOT_FOUND is considered valid (No EFI + // driver is controlling video. + // + mVgaInstallationInProgress =3D TRUE; + Status =3D LegacyBiosInstallVgaRom (Private); + if (EFI_ERROR (Status)) { + if (Status !=3D EFI_NOT_FOUND) { + mVgaInstallationInProgress =3D FALSE; + return Status; + } + } else { + mVgaInstallationInProgress =3D FALSE; + } + } + } + // + // See if the option ROM for PciHandle has already been executed + // + Status =3D IsLegacyRom (PciHandle); + + if (!EFI_ERROR (Status)) { + mVgaInstallationInProgress =3D FALSE; + GetShadowedRomParameters ( + PciHandle, + DiskStart, + DiskEnd, + RomShadowAddress, + (UINTN *) RomShadowedSize + ); + return EFI_SUCCESS; + } + + Status =3D LegacyBiosCheckPciRomEx ( + &Private->LegacyBios, + PciHandle, + &LocalRomImage, + &ImageSize, + &RuntimeImageLength, + Flags, + &OpromRevision, + NULL + ); + if (EFI_ERROR (Status)) { + // + // There is no PCI ROM in the ROM BAR or no onboard ROM + // + mVgaInstallationInProgress =3D FALSE; + return EFI_UNSUPPORTED; + } + } else { + if ((RomImage =3D=3D NULL) || (*RomImage =3D=3D NULL)) { + // + // If PciHandle is NULL, and no OpRom is to be associated + // + mVgaInstallationInProgress =3D FALSE; + return EFI_UNSUPPORTED; + } + + Status =3D Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformVgaHandle, + 0, + &HandleBuffer, + &HandleCount, + NULL + ); + if ((!EFI_ERROR (Status)) && (!Private->VgaInstalled)) { + // + // A return status of EFI_NOT_FOUND is considered valid (No EFI + // driver is controlling video. + // + mVgaInstallationInProgress =3D TRUE; + Status =3D LegacyBiosInstallVgaRom (Private); + if (EFI_ERROR (Status)) { + if (Status !=3D EFI_NOT_FOUND) { + mVgaInstallationInProgress =3D FALSE; + return Status; + } + } else { + mVgaInstallationInProgress =3D FALSE; + } + } + + LocalRomImage =3D *RomImage; + if (((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->Signature !=3D PCI_E= XPANSION_ROM_HEADER_SIGNATURE || + ((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset =3D=3D 0 = || + (((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset & 3 ) != =3D 0) { + mVgaInstallationInProgress =3D FALSE; + return EFI_UNSUPPORTED; + } + + Pcir =3D (PCI_3_0_DATA_STRUCTURE *) + ((UINT8 *) LocalRomImage + ((PCI_EXPANSION_ROM_HEADER *) LocalR= omImage)->PcirOffset); + + if ((Pcir->Signature !=3D PCI_DATA_STRUCTURE_SIGNATURE) || (Pcir->Code= Type !=3D PCI_CODE_TYPE_PCAT_IMAGE)) { + mVgaInstallationInProgress =3D FALSE; + return EFI_UNSUPPORTED; + } + + ImageSize =3D Pcir->ImageLength * 512; + if (Pcir->Length >=3D 0x1C) { + OpromRevision =3D Pcir->Revision; + } else { + OpromRevision =3D 0; + } + if (Pcir->Revision < 3) { + RuntimeImageLength =3D 0; + } else { + RuntimeImageLength =3D Pcir->MaxRuntimeImageLength * 512; + } + } + + // + // Grant access for below 1M + // BDA/EBDA/LowPMM and scratch memory for OPROM. + // + IoMmuGrantAccess (PciHandle, 0, SIZE_1MB); + // + // Grant access for HiPmm + // + IoMmuGrantAccess ( + PciHandle, + Private->IntThunk->EfiToLegacy16InitTable.HiPmmMemory, + Private->IntThunk->EfiToLegacy16InitTable.HiPmmMemorySizeInBytes + ); + + // + // Shadow and initialize the OpROM. + // + ASSERT (Private->TraceIndex < 0x200); + Private->Trace[Private->TraceIndex] =3D LEGACY_PCI_TRACE_000; + Private->TraceIndex ++; + Private->TraceIndex =3D (UINT16) (Private->TraceIndex % 0x200); + Status =3D LegacyBiosInstallRom ( + This, + Private, + PciHandle, + OpromRevision, + LocalRomImage, + ImageSize, + &RuntimeImageLength, + DiskStart, + DiskEnd, + RomShadowAddress + ); + if (RomShadowedSize !=3D NULL) { + *RomShadowedSize =3D (UINT32) RuntimeImageLength; + } + + mVgaInstallationInProgress =3D FALSE; + return Status; +} + diff --git a/OvmfPkg/Csm/LegacyBiosDxe/LegacySio.c b/OvmfPkg/Csm/LegacyBios= Dxe/LegacySio.c new file mode 100644 index 0000000000..17720a74f7 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/LegacySio.c @@ -0,0 +1,477 @@ +/** @file + Collect Sio information from Native EFI Drivers. + Sio is floppy, parallel, serial, ... hardware + +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "LegacyBiosInterface.h" + +/** + Collect EFI Info about legacy devices through Super IO interface. + + @param SioPtr Pointer to SIO data. + + @retval EFI_SUCCESS When SIO data is got successfully. + @retval EFI_NOT_FOUND When ISA IO interface is absent. + +**/ +EFI_STATUS +LegacyBiosBuildSioDataFromSio ( + IN DEVICE_PRODUCER_DATA_HEADER *SioPtr + ) +{ + EFI_STATUS Status; + DEVICE_PRODUCER_SERIAL *SioSerial; + DEVICE_PRODUCER_PARALLEL *SioParallel; + DEVICE_PRODUCER_FLOPPY *SioFloppy; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + UINTN ChildIndex; + EFI_SIO_PROTOCOL *Sio; + ACPI_RESOURCE_HEADER_PTR Resources; + EFI_ACPI_IO_PORT_DESCRIPTOR *IoResource; + EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *FixedIoResource; + EFI_ACPI_DMA_DESCRIPTOR *DmaResource; + EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR *IrqResource; + UINT16 Address; + UINT8 Dma; + UINT8 Irq; + UINTN EntryCount; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + ACPI_HID_DEVICE_PATH *Acpi; + + // + // Get the list of ISA controllers in the system + // + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSioProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + // + // Collect legacy information from each of the ISA controllers in the sy= stem + // + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol (HandleBuffer[Index], &gEfiSioProtocolG= uid, (VOID **) &Sio); + if (EFI_ERROR (Status)) { + continue; + } + + Address =3D MAX_UINT16; + Dma =3D MAX_UINT8; + Irq =3D MAX_UINT8; + Status =3D Sio->GetResources (Sio, &Resources); + if (!EFI_ERROR (Status)) { + // + // Get the base address information from ACPI resource descriptor. + // + while (Resources.SmallHeader->Byte !=3D ACPI_END_TAG_DESCRIPTOR) { + switch (Resources.SmallHeader->Byte) { + case ACPI_IO_PORT_DESCRIPTOR: + IoResource =3D (EFI_ACPI_IO_PORT_DESCRIPTOR *) Resources.SmallHe= ader; + Address =3D IoResource->BaseAddressMin; + break; + + case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR: + FixedIoResource =3D (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR = *) Resources.SmallHeader; + Address =3D FixedIoResource->BaseAddress; + break; + + case ACPI_DMA_DESCRIPTOR: + DmaResource =3D (EFI_ACPI_DMA_DESCRIPTOR *) Resources.SmallHeade= r; + Dma =3D (UINT8) LowBitSet32 (DmaResource->ChannelMask); + break; + + case ACPI_IRQ_DESCRIPTOR: + case ACPI_IRQ_NOFLAG_DESCRIPTOR: + IrqResource =3D (EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR *) Resources.Sma= llHeader; + Irq =3D (UINT8) LowBitSet32 (IrqResource->Mask); + break; + + default: + break; + } + + if (Resources.SmallHeader->Bits.Type =3D=3D 0) { + Resources.SmallHeader =3D (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8= *) Resources.SmallHeader + + Resour= ces.SmallHeader->Bits.Length + + sizeof= (*Resources.SmallHeader)); + } else { + Resources.LargeHeader =3D (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8= *) Resources.LargeHeader + + Resour= ces.LargeHeader->Length + + sizeof= (*Resources.LargeHeader)); + } + } + } + + DEBUG ((EFI_D_INFO, "LegacySio: Address/Dma/Irq =3D %x/%d/%d\n", Addre= ss, Dma, Irq)); + + DevicePath =3D DevicePathFromHandle (HandleBuffer[Index]); + if (DevicePath =3D=3D NULL) { + continue; + } + + Acpi =3D NULL; + while (!IsDevicePathEnd (DevicePath)) { + Acpi =3D (ACPI_HID_DEVICE_PATH *) DevicePath; + DevicePath =3D NextDevicePathNode (DevicePath); + } + + if ((Acpi =3D=3D NULL) || (DevicePathType (Acpi) !=3D ACPI_DEVICE_PATH= ) || + ((DevicePathSubType (Acpi) !=3D ACPI_DP) && (DevicePathSubType (Ac= pi) !=3D ACPI_EXTENDED_DP)) + ) { + continue; + } + + // + // See if this is an ISA serial port + // + // Ignore DMA resource since it is always returned NULL + // + if (Acpi->HID =3D=3D EISA_PNP_ID (0x500) || Acpi->HID =3D=3D EISA_PNP_= ID (0x501)) { + + if (Acpi->UID < 4 && Address !=3D MAX_UINT16 && Irq !=3D MAX_UINT8) { + // + // Get the handle of the child device that has opened the Super I/= O Protocol + // + Status =3D gBS->OpenProtocolInformation ( + HandleBuffer[Index], + &gEfiSioProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (EFI_ERROR (Status)) { + continue; + } + for (ChildIndex =3D 0; ChildIndex < EntryCount; ChildIndex++) { + if ((OpenInfoBuffer[ChildIndex].Attributes & EFI_OPEN_PROTOCOL_B= Y_CHILD_CONTROLLER) !=3D 0) { + Status =3D gBS->HandleProtocol (OpenInfoBuffer[ChildIndex].Con= trollerHandle, &gEfiSerialIoProtocolGuid, (VOID **) &SerialIo); + if (!EFI_ERROR (Status)) { + SioSerial =3D &SioPtr->Serial[Acpi->UID]; + SioSerial->Address =3D Address; + SioSerial->Irq =3D Irq; + SioSerial->Mode =3D DEVICE_SERIAL_MODE_NORMAL | DEVICE_S= ERIAL_MODE_DUPLEX_HALF; + break; + } + } + } + + FreePool (OpenInfoBuffer); + } + } + // + // See if this is an ISA parallel port + // + // Ignore DMA resource since it is always returned NULL, port + // only used in output mode. + // + if (Acpi->HID =3D=3D EISA_PNP_ID (0x400) || Acpi->HID =3D=3D EISA_PNP_= ID (0x401)) { + if (Acpi->UID < 3 && Address !=3D MAX_UINT16 && Irq !=3D MAX_UINT8 &= & Dma !=3D MAX_UINT8) { + SioParallel =3D &SioPtr->Parallel[Acpi->UID]; + SioParallel->Address =3D Address; + SioParallel->Irq =3D Irq; + SioParallel->Dma =3D Dma; + SioParallel->Mode =3D DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY; + } + } + // + // See if this is an ISA floppy controller + // + if (Acpi->HID =3D=3D EISA_PNP_ID (0x604)) { + if (Address !=3D MAX_UINT16 && Irq !=3D MAX_UINT8 && Dma !=3D MAX_UI= NT8) { + Status =3D gBS->HandleProtocol (HandleBuffer[Index], &gEfiBlockIoP= rotocolGuid, (VOID **) &BlockIo); + if (!EFI_ERROR (Status)) { + SioFloppy =3D &SioPtr->Floppy; + SioFloppy->Address =3D Address; + SioFloppy->Irq =3D Irq; + SioFloppy->Dma =3D Dma; + SioFloppy->NumberOfFloppy++; + } + } + } + // + // See if this is a mouse + // Always set mouse found so USB hot plug will work + // + // Ignore lower byte of HID. Pnp0fxx is any type of mouse. + // + // Hid =3D ResourceList->Device.HID & 0xff00ffff; + // PnpId =3D EISA_PNP_ID(0x0f00); + // if (Hid =3D=3D PnpId) { + // if (ResourceList->Device.UID =3D=3D 1) { + // Status =3D gBS->HandleProtocol (HandleBuffer[Index], &gEfiSi= mplePointerProtocolGuid, &SimplePointer); + // if (!EFI_ERROR (Status)) { + // + SioPtr->MousePresent =3D 0x01; + // + // } + // } + // } + // + } + + FreePool (HandleBuffer); + return EFI_SUCCESS; + +} + +/** + Collect EFI Info about legacy devices through ISA IO interface. + + @param SioPtr Pointer to SIO data. + + @retval EFI_SUCCESS When SIO data is got successfully. + @retval EFI_NOT_FOUND When ISA IO interface is absent. + +**/ +EFI_STATUS +LegacyBiosBuildSioDataFromIsaIo ( + IN DEVICE_PRODUCER_DATA_HEADER *SioPtr + ) +{ + EFI_STATUS Status; + DEVICE_PRODUCER_SERIAL *SioSerial; + DEVICE_PRODUCER_PARALLEL *SioParallel; + DEVICE_PRODUCER_FLOPPY *SioFloppy; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + UINTN ResourceIndex; + UINTN ChildIndex; + EFI_ISA_IO_PROTOCOL *IsaIo; + EFI_ISA_ACPI_RESOURCE_LIST *ResourceList; + EFI_ISA_ACPI_RESOURCE *IoResource; + EFI_ISA_ACPI_RESOURCE *DmaResource; + EFI_ISA_ACPI_RESOURCE *InterruptResource; + UINTN EntryCount; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + + // + // Get the list of ISA controllers in the system + // + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiIsaIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + // + // Collect legacy information from each of the ISA controllers in the sy= stem + // + for (Index =3D 0; Index < HandleCount; Index++) { + + Status =3D gBS->HandleProtocol (HandleBuffer[Index], &gEfiIsaIoProtoco= lGuid, (VOID **) &IsaIo); + if (EFI_ERROR (Status)) { + continue; + } + + ResourceList =3D IsaIo->ResourceList; + + if (ResourceList =3D=3D NULL) { + continue; + } + // + // Collect the resource types neededto fill in the SIO data structure + // + IoResource =3D NULL; + DmaResource =3D NULL; + InterruptResource =3D NULL; + for (ResourceIndex =3D 0; + ResourceList->ResourceItem[ResourceIndex].Type !=3D EfiIsaAcpiRes= ourceEndOfList; + ResourceIndex++ + ) { + switch (ResourceList->ResourceItem[ResourceIndex].Type) { + case EfiIsaAcpiResourceIo: + IoResource =3D &ResourceList->ResourceItem[ResourceIndex]; + break; + + case EfiIsaAcpiResourceMemory: + break; + + case EfiIsaAcpiResourceDma: + DmaResource =3D &ResourceList->ResourceItem[ResourceIndex]; + break; + + case EfiIsaAcpiResourceInterrupt: + InterruptResource =3D &ResourceList->ResourceItem[ResourceIndex]; + break; + + default: + break; + } + } + // + // See if this is an ISA serial port + // + // Ignore DMA resource since it is always returned NULL + // + if (ResourceList->Device.HID =3D=3D EISA_PNP_ID (0x500) || ResourceLis= t->Device.HID =3D=3D EISA_PNP_ID (0x501)) { + + if (ResourceList->Device.UID <=3D 3 && + IoResource !=3D NULL && + InterruptResource !=3D NULL + ) { + // + // Get the handle of the child device that has opened the ISA I/O = Protocol + // + Status =3D gBS->OpenProtocolInformation ( + HandleBuffer[Index], + &gEfiIsaIoProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (EFI_ERROR (Status)) { + continue; + } + // + // We want resource for legacy even if no 32-bit driver installed + // + for (ChildIndex =3D 0; ChildIndex < EntryCount; ChildIndex++) { + if ((OpenInfoBuffer[ChildIndex].Attributes & EFI_OPEN_PROTOCOL_B= Y_CHILD_CONTROLLER) !=3D 0) { + Status =3D gBS->HandleProtocol (OpenInfoBuffer[ChildIndex].Con= trollerHandle, &gEfiSerialIoProtocolGuid, (VOID **) &SerialIo); + if (!EFI_ERROR (Status)) { + SioSerial =3D &SioPtr->Serial[ResourceList->Device= .UID]; + SioSerial->Address =3D (UINT16) IoResource->StartRange; + SioSerial->Irq =3D (UINT8) InterruptResource->StartRang= e; + SioSerial->Mode =3D DEVICE_SERIAL_MODE_NORMAL | DEVICE_S= ERIAL_MODE_DUPLEX_HALF; + break; + } + } + } + + FreePool (OpenInfoBuffer); + } + } + // + // See if this is an ISA parallel port + // + // Ignore DMA resource since it is always returned NULL, port + // only used in output mode. + // + if (ResourceList->Device.HID =3D=3D EISA_PNP_ID (0x400) || ResourceLis= t->Device.HID =3D=3D EISA_PNP_ID (0x401)) { + if (ResourceList->Device.UID <=3D 2 && + IoResource !=3D NULL && + InterruptResource !=3D NULL && + DmaResource !=3D NULL + ) { + SioParallel =3D &SioPtr->Parallel[ResourceList->Device.U= ID]; + SioParallel->Address =3D (UINT16) IoResource->StartRange; + SioParallel->Irq =3D (UINT8) InterruptResource->StartRange; + SioParallel->Dma =3D (UINT8) DmaResource->StartRange; + SioParallel->Mode =3D DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY; + } + } + // + // See if this is an ISA floppy controller + // + if (ResourceList->Device.HID =3D=3D EISA_PNP_ID (0x604)) { + if (IoResource !=3D NULL && InterruptResource !=3D NULL && DmaResour= ce !=3D NULL) { + Status =3D gBS->HandleProtocol (HandleBuffer[Index], &gEfiBlockIoP= rotocolGuid, (VOID **) &BlockIo); + if (!EFI_ERROR (Status)) { + SioFloppy =3D &SioPtr->Floppy; + SioFloppy->Address =3D (UINT16) IoResource->StartRange; + SioFloppy->Irq =3D (UINT8) InterruptResource->StartRange; + SioFloppy->Dma =3D (UINT8) DmaResource->StartRange; + SioFloppy->NumberOfFloppy++; + } + } + } + // + // See if this is a mouse + // Always set mouse found so USB hot plug will work + // + // Ignore lower byte of HID. Pnp0fxx is any type of mouse. + // + // Hid =3D ResourceList->Device.HID & 0xff00ffff; + // PnpId =3D EISA_PNP_ID(0x0f00); + // if (Hid =3D=3D PnpId) { + // if (ResourceList->Device.UID =3D=3D 1) { + // Status =3D gBS->HandleProtocol (HandleBuffer[Index], &gEfiSi= mplePointerProtocolGuid, &SimplePointer); + // if (!EFI_ERROR (Status)) { + // + SioPtr->MousePresent =3D 0x01; + // + // } + // } + // } + // + } + + FreePool (HandleBuffer); + return EFI_SUCCESS; +} + +/** + Collect EFI Info about legacy devices. + + @param Private Legacy BIOS Instance data + + @retval EFI_SUCCESS It should always work. + +**/ +EFI_STATUS +LegacyBiosBuildSioData ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + DEVICE_PRODUCER_DATA_HEADER *SioPtr; + EFI_HANDLE IsaBusController; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + + // + // Get the pointer to the SIO data structure + // + SioPtr =3D &Private->IntThunk->EfiToLegacy16BootTable.SioData; + + // + // Zero the data in the SIO data structure + // + gBS->SetMem (SioPtr, sizeof (DEVICE_PRODUCER_DATA_HEADER), 0); + + // + // Find the ISA Bus Controller used for legacy + // + Status =3D Private->LegacyBiosPlatform->GetPlatformHandle ( + Private->LegacyBiosPlatform, + EfiGetPlatformIsaBusHandle, + 0, + &HandleBuffer, + &HandleCount, + NULL + ); + IsaBusController =3D HandleBuffer[0]; + if (!EFI_ERROR (Status)) { + // + // Force ISA Bus Controller to produce all ISA devices + // + gBS->ConnectController (IsaBusController, NULL, NULL, TRUE); + } + + Status =3D LegacyBiosBuildSioDataFromIsaIo (SioPtr); + if (EFI_ERROR (Status)) { + LegacyBiosBuildSioDataFromSio (SioPtr); + } + + return EFI_SUCCESS; +} diff --git a/OvmfPkg/Csm/LegacyBiosDxe/Thunk.c b/OvmfPkg/Csm/LegacyBiosDxe/= Thunk.c new file mode 100644 index 0000000000..a4985ede77 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/Thunk.c @@ -0,0 +1,419 @@ +/** @file + Call into 16-bit BIOS code, Use AsmThunk16 function of BaseLib. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "LegacyBiosInterface.h" + +THUNK_CONTEXT mThunkContext; + +/** + Sets the counter value for Timer #0 in a legacy 8254 timer. + + @param Count - The 16-bit counter value to program into Timer #0 of the= legacy 8254 timer. + +**/ +VOID +SetPitCount ( + IN UINT16 Count + ) +{ + IoWrite8 (TIMER_CONTROL_PORT, TIMER0_CONTROL_WORD); + IoWrite8 (TIMER0_COUNT_PORT, (UINT8) (Count & 0xFF)); + IoWrite8 (TIMER0_COUNT_PORT, (UINT8) ((Count>>8) & 0xFF)); +} + +/** + Thunk to 16-bit real mode and execute a software interrupt with a vector + of BiosInt. Regs will contain the 16-bit register context on entry and + exit. + + @param This Protocol instance pointer. + @param BiosInt Processor interrupt vector to invoke + @param Regs Register contexted passed into (and returned) from thunk= to + 16-bit mode + + @retval FALSE Thunk completed, and there were no BIOS errors in the ta= rget code. + See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +BOOLEAN +EFIAPI +LegacyBiosInt86 ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 BiosInt, + IN EFI_IA32_REGISTER_SET *Regs + ) +{ + UINT16 Segment; + UINT16 Offset; + + Regs->X.Flags.Reserved1 =3D 1; + Regs->X.Flags.Reserved2 =3D 0; + Regs->X.Flags.Reserved3 =3D 0; + Regs->X.Flags.Reserved4 =3D 0; + Regs->X.Flags.IOPL =3D 3; + Regs->X.Flags.NT =3D 0; + Regs->X.Flags.IF =3D 0; + Regs->X.Flags.TF =3D 0; + Regs->X.Flags.CF =3D 0; + // + // The base address of legacy interrupt vector table is 0. + // We use this base address to get the legacy interrupt handler. + // + ACCESS_PAGE0_CODE ( + Segment =3D (UINT16)(((UINT32 *)0)[BiosInt] >> 16); + Offset =3D (UINT16)((UINT32 *)0)[BiosInt]; + ); + + return InternalLegacyBiosFarCall ( + This, + Segment, + Offset, + Regs, + &Regs->X.Flags, + sizeof (Regs->X.Flags) + ); +} + +/** + Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the + 16-bit register context on entry and exit. Arguments can be passed on + the Stack argument + + @param This Protocol instance pointer. + @param Segment Segemnt of 16-bit mode call + @param Offset Offset of 16-bit mdoe call + @param Regs Register contexted passed into (and retur= ned) from + thunk to 16-bit mode + @param Stack Caller allocated stack used to pass argum= ents + @param StackSize Size of Stack in bytes + + @retval FALSE Thunk completed, and there were no BIOS e= rrors in + the target code. See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +BOOLEAN +EFIAPI +LegacyBiosFarCall86 ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT16 Segment, + IN UINT16 Offset, + IN EFI_IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize + ) +{ + Regs->X.Flags.Reserved1 =3D 1; + Regs->X.Flags.Reserved2 =3D 0; + Regs->X.Flags.Reserved3 =3D 0; + Regs->X.Flags.Reserved4 =3D 0; + Regs->X.Flags.IOPL =3D 3; + Regs->X.Flags.NT =3D 0; + Regs->X.Flags.IF =3D 1; + Regs->X.Flags.TF =3D 0; + Regs->X.Flags.CF =3D 0; + + return InternalLegacyBiosFarCall (This, Segment, Offset, Regs, Stack, St= ackSize); +} + +/** + Provide NULL interrupt handler which is used to check + if there is more than one HW interrupt registers with the CPU AP. + + @param InterruptType - The type of interrupt that occured + @param SystemContext - A pointer to the system context when the interru= pt occured + +**/ +VOID +EFIAPI +LegacyBiosNullInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ +} + +/** + Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the + 16-bit register context on entry and exit. Arguments can be passed on + the Stack argument + + @param This Protocol instance pointer. + @param Segment Segemnt of 16-bit mode call + @param Offset Offset of 16-bit mdoe call + @param Regs Register contexted passed into (and returned) from th= unk to + 16-bit mode + @param Stack Caller allocated stack used to pass arguments + @param StackSize Size of Stack in bytes + + @retval FALSE Thunk completed, and there were no BIOS errors in the= target code. + See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +BOOLEAN +EFIAPI +InternalLegacyBiosFarCall ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT16 Segment, + IN UINT16 Offset, + IN EFI_IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize + ) +{ + UINTN Status; + LEGACY_BIOS_INSTANCE *Private; + UINT16 *Stack16; + EFI_TPL OriginalTpl; + IA32_REGISTER_SET ThunkRegSet; + BOOLEAN InterruptState; + UINT64 TimerPeriod; + + Private =3D LEGACY_BIOS_INSTANCE_FROM_THIS (This); + + ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet)); + ThunkRegSet.X.DI =3D Regs->X.DI; + ThunkRegSet.X.SI =3D Regs->X.SI; + ThunkRegSet.X.BP =3D Regs->X.BP; + ThunkRegSet.X.BX =3D Regs->X.BX; + ThunkRegSet.X.DX =3D Regs->X.DX; + // + // Sometimes, ECX is used to pass in 32 bit data. For example, INT 1Ah, = AX =3D B10Dh is + // "PCI BIOS v2.0c + Write Configuration DWORD" and ECX has the dword to= write. + // + ThunkRegSet.E.ECX =3D Regs->E.ECX; + ThunkRegSet.X.AX =3D Regs->X.AX; + ThunkRegSet.E.DS =3D Regs->X.DS; + ThunkRegSet.E.ES =3D Regs->X.ES; + + CopyMem (&(ThunkRegSet.E.EFLAGS.UintN), &(Regs->X.Flags), sizeof (Regs->= X.Flags)); + + // + // Clear the error flag; thunk code may set it. Stack16 should be the hi= gh address + // Make Statk16 address the low 16 bit must be not zero. + // + Stack16 =3D (UINT16 *)((UINT8 *) mThunkContext.RealModeBuffer + mThunkCo= ntext.RealModeBufferSize - sizeof (UINT16)); + + // + // Save current rate of DXE Timer + // + Private->Timer->GetTimerPeriod (Private->Timer, &TimerPeriod); + + // + // Disable DXE Timer while executing in real mode + // + Private->Timer->SetTimerPeriod (Private->Timer, 0); + + // + // Save and disable interrupt of debug timer + // + InterruptState =3D SaveAndSetDebugTimerInterrupt (FALSE); + + // + // The call to Legacy16 is a critical section to EFI + // + OriginalTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + // + // Check to see if there is more than one HW interrupt registers with th= e CPU AP. + // If there is, then ASSERT() since that is not compatible with the CSM = because + // interupts other than the Timer interrupt that was disabled above can = not be + // handled properly from real mode. + // + DEBUG_CODE ( + UINTN Vector; + UINTN Count; + + for (Vector =3D 0x20, Count =3D 0; Vector < 0x100; Vector++) { + Status =3D Private->Cpu->RegisterInterruptHandler (Private->Cpu, Vec= tor, LegacyBiosNullInterruptHandler); + if (Status =3D=3D EFI_ALREADY_STARTED) { + Count++; + } + if (Status =3D=3D EFI_SUCCESS) { + Private->Cpu->RegisterInterruptHandler (Private->Cpu, Vector, NULL= ); + } + } + if (Count >=3D 2) { + DEBUG ((EFI_D_ERROR, "ERROR: More than one HW interrupt active with = CSM enabled\n")); + } + ASSERT (Count < 2); + ); + + // + // If the Timer AP has enabled the 8254 timer IRQ and the current 8254 t= imer + // period is less than the CSM required rate of 54.9254, then force the = 8254 + // PIT counter to 0, which is the CSM required rate of 54.9254 ms + // + if (Private->TimerUses8254 && TimerPeriod < 549254) { + SetPitCount (0); + } + + if (Stack !=3D NULL && StackSize !=3D 0) { + // + // Copy Stack to low memory stack + // + Stack16 -=3D StackSize / sizeof (UINT16); + CopyMem (Stack16, Stack, StackSize); + } + + ThunkRegSet.E.SS =3D (UINT16) (((UINTN) Stack16 >> 16) << 12); + ThunkRegSet.E.ESP =3D (UINT16) (UINTN) Stack16; + ThunkRegSet.E.CS =3D Segment; + ThunkRegSet.E.Eip =3D Offset; + + mThunkContext.RealModeState =3D &ThunkRegSet; + + // + // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. + // + Status =3D Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259Leg= acyMode, NULL, NULL); + ASSERT_EFI_ERROR (Status); + + AsmThunk16 (&mThunkContext); + + if (Stack !=3D NULL && StackSize !=3D 0) { + // + // Copy low memory stack to Stack + // + CopyMem (Stack, Stack16, StackSize); + } + + // + // Restore protected mode interrupt state + // + Status =3D Private->Legacy8259->SetMode (Private->Legacy8259, Efi8259Pro= tectedMode, NULL, NULL); + ASSERT_EFI_ERROR (Status); + + mThunkContext.RealModeState =3D NULL; + + // + // Enable and restore rate of DXE Timer + // + Private->Timer->SetTimerPeriod (Private->Timer, TimerPeriod); + + // + // End critical section + // + gBS->RestoreTPL (OriginalTpl); + + // + // OPROM may allocate EBDA range by itself and change EBDA base and EBDA= size. + // Get the current EBDA base address, and compared with pre-allocate min= imum + // EBDA base address, if the current EBDA base address is smaller, it in= dicates + // PcdEbdaReservedMemorySize should be adjusted to larger for more OPROM= s. + // + DEBUG_CODE ( + { + UINTN EbdaBaseAddress; + UINTN ReservedEbdaBaseAddress; + + ACCESS_PAGE0_CODE ( + EbdaBaseAddress =3D (*(UINT16 *) (UINTN) 0x40E) << 4; + ReservedEbdaBaseAddress =3D CONVENTIONAL_MEMORY_TOP + - PcdGet32 (PcdEbdaReservedMemorySize); + ASSERT (ReservedEbdaBaseAddress <=3D EbdaBaseAddress); + ); + } + ); + + // + // Restore interrupt of debug timer + // + SaveAndSetDebugTimerInterrupt (InterruptState); + + Regs->E.EDI =3D ThunkRegSet.E.EDI; + Regs->E.ESI =3D ThunkRegSet.E.ESI; + Regs->E.EBP =3D ThunkRegSet.E.EBP; + Regs->E.EBX =3D ThunkRegSet.E.EBX; + Regs->E.EDX =3D ThunkRegSet.E.EDX; + Regs->E.ECX =3D ThunkRegSet.E.ECX; + Regs->E.EAX =3D ThunkRegSet.E.EAX; + Regs->X.SS =3D ThunkRegSet.E.SS; + Regs->X.CS =3D ThunkRegSet.E.CS; + Regs->X.DS =3D ThunkRegSet.E.DS; + Regs->X.ES =3D ThunkRegSet.E.ES; + + CopyMem (&(Regs->X.Flags), &(ThunkRegSet.E.EFLAGS.UintN), sizeof (Regs->= X.Flags)); + + return (BOOLEAN) (Regs->X.Flags.CF =3D=3D 1); +} + +/** + Allocate memory < 1 MB and copy the thunker code into low memory. Se up + all the descriptors. + + @param Private Private context for Legacy BIOS + + @retval EFI_SUCCESS Should only pass. + +**/ +EFI_STATUS +LegacyBiosInitializeThunk ( + IN LEGACY_BIOS_INSTANCE *Private + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS MemoryAddress; + UINT8 TimerVector; + + MemoryAddress =3D (EFI_PHYSICAL_ADDRESS) (UINTN) Private->IntThunk; + + mThunkContext.RealModeBuffer =3D (VOID *) (UINTN) (MemoryAddress + (= (sizeof (LOW_MEMORY_THUNK) / EFI_PAGE_SIZE) + 1) * EFI_PAGE_SIZE); + mThunkContext.RealModeBufferSize =3D EFI_PAGE_SIZE; + mThunkContext.ThunkAttributes =3D THUNK_ATTRIBUTE_BIG_REAL_MODE | THU= NK_ATTRIBUTE_DISABLE_A20_MASK_INT_15; + + AsmPrepareThunk16 (&mThunkContext); + + // + // Get the interrupt vector number corresponding to IRQ0 from the 8259 d= river + // + TimerVector =3D 0; + Status =3D Private->Legacy8259->GetVector (Private->Legacy8259, Efi8259I= rq0, &TimerVector); + ASSERT_EFI_ERROR (Status); + + // + // Check to see if the Timer AP has hooked the IRQ0 from the 8254 PIT + // + Status =3D Private->Cpu->RegisterInterruptHandler ( + Private->Cpu, + TimerVector, + LegacyBiosNullInterruptHandler + ); + if (Status =3D=3D EFI_SUCCESS) { + // + // If the Timer AP has not enabled the 8254 timer IRQ, then force the = 8254 PIT + // counter to 0, which is the CSM required rate of 54.9254 ms + // + Private->Cpu->RegisterInterruptHandler ( + Private->Cpu, + TimerVector, + NULL + ); + SetPitCount (0); + + // + // Save status that the Timer AP is not using the 8254 PIT + // + Private->TimerUses8254 =3D FALSE; + } else if (Status =3D=3D EFI_ALREADY_STARTED) { + // + // Save status that the Timer AP is using the 8254 PIT + // + Private->TimerUses8254 =3D TRUE; + } else { + // + // Unexpected status from CPU AP RegisterInterruptHandler() + // + ASSERT (FALSE); + } + + return EFI_SUCCESS; +} diff --git a/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUi.c b/OvmfPkg= /Csm/LegacyBootMaintUiLib/LegacyBootMaintUi.c new file mode 100644 index 0000000000..af7d80eb5f --- /dev/null +++ b/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUi.c @@ -0,0 +1,1505 @@ +/** @file + Legacy Boot Maintainence UI implementation. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+(C) Copyright 2018 Hewlett Packard Enterprise Development LP
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "LegacyBootMaintUi.h" + +LEGACY_BOOT_OPTION_CALLBACK_DATA *mLegacyBootOptionPrivate =3D NULL; +EFI_GUID mLegacyBootOptionGuid =3D LEGACY_BOOT_OPTION_FORMSET_GUID; +CHAR16 mLegacyBootStorageName[] =3D L"LegacyBootData"; +BBS_TYPE mBbsType[] =3D {BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM, BBS_EMBED_N= ETWORK, BBS_BEV_DEVICE, BBS_UNKNOWN}; +BOOLEAN mFirstEnterLegacyForm =3D FALSE; + + +/// +/// Legacy FD Info from LegacyBios.GetBbsInfo() +/// +LEGACY_MENU_OPTION LegacyFDMenu =3D { + LEGACY_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Legacy HD Info from LegacyBios.GetBbsInfo() +/// +LEGACY_MENU_OPTION LegacyHDMenu =3D { + LEGACY_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Legacy CD Info from LegacyBios.GetBbsInfo() +/// +LEGACY_MENU_OPTION LegacyCDMenu =3D { + LEGACY_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Legacy NET Info from LegacyBios.GetBbsInfo() +/// +LEGACY_MENU_OPTION LegacyNETMenu =3D { + LEGACY_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + +/// +/// Legacy NET Info from LegacyBios.GetBbsInfo() +/// +LEGACY_MENU_OPTION LegacyBEVMenu =3D { + LEGACY_MENU_OPTION_SIGNATURE, + {NULL}, + 0 +}; + + +VOID *mLegacyStartOpCodeHandle =3D NULL; +VOID *mLegacyEndOpCodeHandle =3D NULL; +EFI_IFR_GUID_LABEL *mLegacyStartLabel =3D NULL; +EFI_IFR_GUID_LABEL *mLegacyEndLabel =3D NULL; + + +HII_VENDOR_DEVICE_PATH mLegacyBootOptionHiiVendorDevicePath =3D { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + { 0x6bc75598, 0x89b4, 0x483d, { 0x91, 0x60, 0x7f, 0x46, 0x9a, 0x96, 0x= 35, 0x31 } } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +/** + + Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios= .GetBbsInfo(). + +**/ +VOID +GetLegacyOptions ( + VOID + ); + + +/** + + Base on the L"LegacyDevOrder" variable to build the current order data. + +**/ +VOID +GetLegacyOptionsOrder ( + VOID + ); + +/** + Re-order the Boot Option according to the DevOrder. + + The routine re-orders the Boot Option in BootOption array according to + the order specified by DevOrder. + + @param DevOrder Pointer to buffer containing the BBS Index, + high 8-bit value 0xFF indicating a disabled bo= ot option + @param DevOrderCount Count of the BBS Index + @param EnBootOption Callee allocated buffer containing the enabled= Boot Option Numbers + @param EnBootOptionCount Count of the enabled Boot Option Numbers + @param DisBootOption Callee allocated buffer containing the disable= d Boot Option Numbers + @param DisBootOptionCount Count of the disabled Boot Option Numbers + + @return EFI_SUCCESS The function completed successfully. + @retval other Contain some error, details see the status re= turn by gRT->SetVariable. +**/ +EFI_STATUS +OrderLegacyBootOption4SameType ( + UINT16 *DevOrder, + UINTN DevOrderCount, + UINT16 **EnBootOption, + UINTN *EnBootOptionCount, + UINT16 **DisBootOption, + UINTN *DisBootOptionCount + ) +{ + EFI_STATUS Status; + UINT16 *NewBootOption; + UINT16 *BootOrder; + UINTN BootOrderSize; + UINTN Index; + UINTN StartPosition; + + EFI_BOOT_MANAGER_LOAD_OPTION BootOption; + + CHAR16 OptionName[sizeof ("Boot####")]; + UINT16 *BbsIndexArray; + UINT16 *DeviceTypeArray; + + GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrder, &BootOrderSiz= e); + ASSERT (BootOrder !=3D NULL); + + BbsIndexArray =3D AllocatePool (BootOrderSize); + DeviceTypeArray =3D AllocatePool (BootOrderSize); + *EnBootOption =3D AllocatePool (BootOrderSize); + *DisBootOption =3D AllocatePool (BootOrderSize); + *DisBootOptionCount =3D 0; + *EnBootOptionCount =3D 0; + Index =3D 0; + Status =3D EFI_SUCCESS; + + ASSERT (BbsIndexArray !=3D NULL); + ASSERT (DeviceTypeArray !=3D NULL); + ASSERT (*EnBootOption !=3D NULL); + ASSERT (*DisBootOption !=3D NULL); + + for (Index =3D 0; Index < BootOrderSize / sizeof (UINT16); Index++) { + + UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", BootOrder= [Index]); + Status =3D EfiBootManagerVariableToLoadOption (OptionName, &BootOption= ); + ASSERT_EFI_ERROR (Status); + + if ((DevicePathType (BootOption.FilePath) =3D=3D BBS_DEVICE_PATH) && + (DevicePathSubType (BootOption.FilePath) =3D=3D BBS_BBS_DP)) { + // + // Legacy Boot Option + // + ASSERT (BootOption.OptionalDataSize =3D=3D sizeof (LEGACY_BOOT_OPTIO= N_BBS_DATA)); + + DeviceTypeArray[Index] =3D ((BBS_BBS_DEVICE_PATH *) BootOption.FileP= ath)->DeviceType; + BbsIndexArray [Index] =3D ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOpti= on.OptionalData)->BbsIndex; + } else { + DeviceTypeArray[Index] =3D BBS_TYPE_UNKNOWN; + BbsIndexArray [Index] =3D 0xFFFF; + } + EfiBootManagerFreeLoadOption (&BootOption); + } + + // + // Record the corresponding Boot Option Numbers according to the DevOrder + // Record the EnBootOption and DisBootOption according to the DevOrder + // + StartPosition =3D BootOrderSize / sizeof (UINT16); + NewBootOption =3D AllocatePool (DevOrderCount * sizeof (UINT16)); + ASSERT (NewBootOption !=3D NULL); + while (DevOrderCount-- !=3D 0) { + for (Index =3D 0; Index < BootOrderSize / sizeof (UINT16); Index++) { + if (BbsIndexArray[Index] =3D=3D (DevOrder[DevOrderCount] & 0xFF)) { + StartPosition =3D MIN (StartPosition, Index); + NewBootOption[DevOrderCount] =3D BootOrder[Index]; + + if ((DevOrder[DevOrderCount] & 0xFF00) =3D=3D 0xFF00) { + (*DisBootOption)[*DisBootOptionCount] =3D BootOrder[Index]; + (*DisBootOptionCount)++; + } else { + (*EnBootOption)[*EnBootOptionCount] =3D BootOrder[Index]; + (*EnBootOptionCount)++; + } + break; + } + } + } + + // + // Overwrite the old BootOption + // + CopyMem (&BootOrder[StartPosition], NewBootOption, (*DisBootOptionCount = + *EnBootOptionCount) * sizeof (UINT16)); + Status =3D gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + BootOrderSize, + BootOrder + ); + + FreePool (NewBootOption); + FreePool (DeviceTypeArray); + FreePool (BbsIndexArray); + + return Status; +} + +/** + Update the legacy BBS boot option. L"LegacyDevOrder" and gEfiLegacyDevOr= derVariableGuid EFI Variable + is udpated with the new Legacy Boot order. The EFI Variable of "Boot####= " and gEfiGlobalVariableGuid + is also updated. + + @param NVMapData The data for egacy BBS boot. + + @return EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND If L"LegacyDevOrder" and gEfiLegacyDevOrde= rVariableGuid EFI Variable can not be found. + @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource + @retval other Contain some error, details see the statu= s return by gRT->SetVariable. +**/ +EFI_STATUS +UpdateBBSOption ( + IN LEGACY_BOOT_NV_DATA *NVMapData + ) +{ + UINTN Index; + UINTN Index2; + UINTN CurrentType; + VOID *BootOptionVar; + CHAR16 VarName[100]; + UINTN OptionSize; + EFI_STATUS Status; + UINT32 *Attribute; + LEGACY_MENU_OPTION *OptionMenu; + UINT16 *LegacyDev; + UINT16 *InitialLegacyDev; + UINT8 *VarData; + UINTN VarSize; + LEGACY_DEV_ORDER_ENTRY *DevOrder; + UINT8 *OriginalPtr; + UINT8 *DisMap; + UINTN Pos; + UINTN Bit; + UINT16 *NewOrder; + UINT16 Tmp; + UINT16 *EnBootOption; + UINTN EnBootOptionCount; + UINT16 *DisBootOption; + UINTN DisBootOptionCount; + UINTN BufferSize; + + + DisMap =3D NULL; + NewOrder =3D NULL; + CurrentType =3D 0; + EnBootOption =3D NULL; + DisBootOption =3D NULL; + + + DisMap =3D mLegacyBootOptionPrivate->MaintainMapData->DisableMap; + Status =3D EFI_SUCCESS; + + // + // Update the Variable "LegacyDevOrder" + // + GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VO= ID **) &VarData, &VarSize); + if (VarData =3D=3D NULL) { + return EFI_NOT_FOUND; + } + OriginalPtr =3D VarData; + + while (mBbsType[CurrentType] !=3D BBS_UNKNOWN) { + switch (mBbsType[CurrentType]) { + case BBS_FLOPPY: + OptionMenu =3D (LEGACY_MENU_OPTION *) &LegacyFDMenu; + LegacyDev =3D NVMapData->LegacyFD; + InitialLegacyDev =3D mLegacyBootOptionPrivate->MaintainMapData->= InitialNvData.LegacyFD; + BufferSize =3D sizeof (NVMapData->LegacyFD); + break; + + case BBS_HARDDISK: + OptionMenu =3D (LEGACY_MENU_OPTION *) &LegacyHDMenu; + LegacyDev =3D NVMapData->LegacyHD; + InitialLegacyDev =3D mLegacyBootOptionPrivate->MaintainMapData->= InitialNvData.LegacyHD; + + BufferSize =3D sizeof (NVMapData->LegacyHD); + break; + + case BBS_CDROM: + OptionMenu =3D (LEGACY_MENU_OPTION *) &LegacyCDMenu; + LegacyDev =3D NVMapData->LegacyCD; + InitialLegacyDev =3D mLegacyBootOptionPrivate->MaintainMapData->= InitialNvData.LegacyCD; + BufferSize =3D sizeof (NVMapData->LegacyCD); + break; + + case BBS_EMBED_NETWORK: + OptionMenu =3D (LEGACY_MENU_OPTION *) &LegacyNETMenu; + LegacyDev =3D NVMapData->LegacyNET; + InitialLegacyDev =3D mLegacyBootOptionPrivate->MaintainMapData->= InitialNvData.LegacyNET; + BufferSize =3D sizeof (NVMapData->LegacyNET); + break; + + default: + ASSERT (mBbsType[CurrentType] =3D=3D BBS_BEV_DEVICE); + OptionMenu =3D (LEGACY_MENU_OPTION *) &LegacyBEVMenu; + LegacyDev =3D NVMapData->LegacyBEV; + InitialLegacyDev =3D mLegacyBootOptionPrivate->MaintainMapData->= InitialNvData.LegacyBEV; + BufferSize =3D sizeof (NVMapData->LegacyBEV); + break; + } + + // + // Check whether has value changed. + // + if (CompareMem (LegacyDev, InitialLegacyDev, BufferSize) =3D=3D 0) { + CurrentType++; + continue; + } + + DevOrder =3D (LEGACY_DEV_ORDER_ENTRY *) OriginalPtr; + while (VarData < OriginalPtr + VarSize) { + if (DevOrder->BbsType =3D=3D mBbsType[CurrentType]) { + break; + } + + VarData +=3D sizeof (BBS_TYPE) + DevOrder->Length; + DevOrder =3D (LEGACY_DEV_ORDER_ENTRY *) VarData; + } + + if (VarData >=3D OriginalPtr + VarSize) { + FreePool (OriginalPtr); + return EFI_NOT_FOUND; + } + + NewOrder =3D AllocateZeroPool (DevOrder->Length - sizeof (DevOrder->Le= ngth)); + if (NewOrder =3D=3D NULL) { + FreePool (OriginalPtr); + return EFI_OUT_OF_RESOURCES; + } + + for (Index =3D 0; Index < OptionMenu->MenuNumber; Index++) { + if (0xFF =3D=3D LegacyDev[Index]) { + break; + } + + NewOrder[Index] =3D LegacyDev[Index]; + } + + // + // Only the enable/disable state of each boot device with same device = type can be changed, + // so we can count on the index information in DevOrder. + // DisMap bit array is the only reliable source to check a device's en= /dis state, + // so we use DisMap to set en/dis state of each item in NewOrder array + // + for (Index2 =3D 0; Index2 < OptionMenu->MenuNumber; Index2++) { + Tmp =3D (UINT16) (DevOrder->Data[Index2] & 0xFF); + Pos =3D Tmp / 8; + Bit =3D 7 - (Tmp % 8); + if ((DisMap[Pos] & (1 << Bit)) !=3D 0) { + NewOrder[Index] =3D (UINT16) (0xFF00 | Tmp); + Index++; + } + } + + CopyMem ( + DevOrder->Data, + NewOrder, + DevOrder->Length - sizeof (DevOrder->Length) + ); + FreePool (NewOrder); + + // + // Update BootOrder and Boot####.Attribute + // + // 1. Re-order the Option Number in BootOrder according to Legacy Dev = Order + // + ASSERT (OptionMenu->MenuNumber =3D=3D DevOrder->Length / sizeof (UINT1= 6) - 1); + + Status =3D OrderLegacyBootOption4SameType ( + DevOrder->Data, + DevOrder->Length / sizeof (UINT16) - 1, + &EnBootOption, + &EnBootOptionCount, + &DisBootOption, + &DisBootOptionCount + ); + if (EFI_ERROR(Status)) { + goto Fail; + } + + // + // 2. Deactivate the DisBootOption and activate the EnBootOption + // + for (Index =3D 0; Index < DisBootOptionCount; Index++) { + UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", DisBootOption= [Index]); + GetEfiGlobalVariable2 (VarName, (VOID **) &BootOptionVar, &OptionSiz= e); + if (BootOptionVar !=3D NULL) { + Attribute =3D (UINT32 *) BootOptionVar; + *Attribute &=3D ~LOAD_OPTION_ACTIVE; + + Status =3D gRT->SetVariable ( + VarName, + &gEfiGlobalVariableGuid, + VAR_FLAG, + OptionSize, + BootOptionVar + ); + + FreePool (BootOptionVar); + } + } + + for (Index =3D 0; Index < EnBootOptionCount; Index++) { + UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", EnBootOption[= Index]); + GetEfiGlobalVariable2 (VarName, (VOID **) &BootOptionVar, &OptionSiz= e); + if (BootOptionVar !=3D NULL) { + Attribute =3D (UINT32 *) BootOptionVar; + *Attribute |=3D LOAD_OPTION_ACTIVE; + + Status =3D gRT->SetVariable ( + VarName, + &gEfiGlobalVariableGuid, + VAR_FLAG, + OptionSize, + BootOptionVar + ); + + FreePool (BootOptionVar); + } + } + + + FreePool (EnBootOption); + FreePool (DisBootOption); + + CurrentType++; + } + + Status =3D gRT->SetVariable ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLAT= ILE, + VarSize, + OriginalPtr + ); + +Fail: + if (EnBootOption !=3D NULL) { + FreePool (EnBootOption); + } + + if (DisBootOption !=3D NULL) { + FreePool (DisBootOption); + } + + FreePool (OriginalPtr); + return Status; +} + +/** + This function allows a caller to extract the current configuration for o= ne + or more named elements from the target driver. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in format. + @param Progress On return, points to a character in the Request s= tring. + Points to the string's null terminator if request= was successful. + Points to the most recent '&' before the first fa= iling name/value + pair (or the beginning of the string if the failu= re is in the + first name/value pair) if the request was not suc= cessful. + @param Results A null-terminated Unicode string in format which + has all values filled in for the names in the Req= uest string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested= values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown na= me. + @retval EFI_NOT_FOUND Routing data doesn't match any storage i= n this driver. + +**/ +EFI_STATUS +EFIAPI +LegacyBootOptionExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + if (Progress =3D=3D NULL || Results =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + *Progress =3D Request; + return EFI_NOT_FOUND; +} + +/** + This function processes the results of changes in configuration. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in = format. + @param Progress A pointer to a string filled in with the offset o= f the most + recent '&' before the first failing name/value pa= ir (or the + beginning of the string if the failure is in the = first + name/value pair) or the terminating NULL if all w= as successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage i= n this driver. + +**/ +EFI_STATUS +EFIAPI +LegacyBootOptionRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + EFI_STATUS Status; + EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; + LEGACY_BOOT_NV_DATA *CurrentNVMapData; + UINTN BufferSize; + + + if (Configuration =3D=3D NULL || Progress =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + *Progress =3D Configuration; + + // + // Check routing data in . + // Note: there is no name for Name/Value storage, only GUID will be chec= ked + // + if (!HiiIsConfigHdrMatch (Configuration, &mLegacyBootOptionGuid, mLegacy= BootStorageName)) { + return EFI_NOT_FOUND; + } + + Status =3D gBS->LocateProtocol ( + &gEfiHiiConfigRoutingProtocolGuid, + NULL, + (VOID **) &ConfigRouting + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Convert to buffer data by helper function ConfigToBlock() + // + CurrentNVMapData =3D &mLegacyBootOptionPrivate->MaintainMapData->Current= NvData; + Status =3D ConfigRouting->ConfigToBlock ( + ConfigRouting, + Configuration, + (UINT8 *) CurrentNVMapData, + &BufferSize, + Progress + ); + ASSERT_EFI_ERROR (Status); + + Status =3D UpdateBBSOption (CurrentNVMapData); + + return Status; +} + +/** + Refresh the global UpdateData structure. + +**/ +VOID +RefreshLegacyUpdateData ( + VOID + ) +{ + // + // Free current updated date + // + if (mLegacyStartOpCodeHandle !=3D NULL) { + HiiFreeOpCodeHandle (mLegacyStartOpCodeHandle); + } + if (mLegacyEndOpCodeHandle !=3D NULL) { + HiiFreeOpCodeHandle (mLegacyEndOpCodeHandle); + } + + // + // Create new OpCode Handle + // + mLegacyStartOpCodeHandle =3D HiiAllocateOpCodeHandle (); + mLegacyEndOpCodeHandle =3D HiiAllocateOpCodeHandle (); + + // + // Create Hii Extend Label OpCode as the start opcode + // + mLegacyStartLabel =3D (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + mLegacyStartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + mLegacyStartLabel->ExtendOpCode =3D EFI_IFR_EXTEND_OP_LABEL; + + mLegacyStartLabel->Number =3D FORM_BOOT_LEGACY_DEVICE_ID; + + // + // Create Hii Extend Label OpCode as the start opcode + // + mLegacyEndLabel =3D (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + mLegacyEndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + mLegacyEndLabel->ExtendOpCode =3D EFI_IFR_EXTEND_OP_LABEL; + + mLegacyEndLabel->Number =3D FORM_BOOT_LEGACY_LABEL_END; + +} + +/** + Get the Menu Entry from the list in Menu Entry List. + + If MenuNumber is great or equal to the number of Menu + Entry in the list, then ASSERT. + + @param MenuOption The Menu Entry List to read the menu entry. + @param MenuNumber The index of Menu Entry. + + @return The Menu Entry. + +**/ +LEGACY_MENU_ENTRY * +GetMenuEntry ( + LEGACY_MENU_OPTION *MenuOption, + UINTN MenuNumber + ) +{ + LEGACY_MENU_ENTRY *NewMenuEntry; + UINTN Index; + LIST_ENTRY *List; + + ASSERT (MenuNumber < MenuOption->MenuNumber); + + List =3D MenuOption->Head.ForwardLink; + for (Index =3D 0; Index < MenuNumber; Index++) { + List =3D List->ForwardLink; + } + + NewMenuEntry =3D CR (List, LEGACY_MENU_ENTRY, Link, LEGACY_MENU_ENTRY_SI= GNATURE); + + return NewMenuEntry; +} + +/** + Create string tokens for a menu from its help strings and display strings + + @param HiiHandle Hii Handle of the package to be updated. + @param MenuOption The Menu whose string tokens need to be created + +**/ +VOID +CreateLegacyMenuStringToken ( + IN EFI_HII_HANDLE HiiHandle, + IN LEGACY_MENU_OPTION *MenuOption + ) +{ + LEGACY_MENU_ENTRY *NewMenuEntry; + UINTN Index; + + for (Index =3D 0; Index < MenuOption->MenuNumber; Index++) { + NewMenuEntry =3D GetMenuEntry (MenuOption, Index); + + NewMenuEntry->DisplayStringToken =3D HiiSetString ( + HiiHandle, + 0, + NewMenuEntry->DisplayString, + NULL + ); + + if (NULL =3D=3D NewMenuEntry->HelpString) { + NewMenuEntry->HelpStringToken =3D NewMenuEntry->DisplayStringToken; + } else { + NewMenuEntry->HelpStringToken =3D HiiSetString ( + HiiHandle, + 0, + NewMenuEntry->HelpString, + NULL + ); + } + } +} + +/** + Create a dynamic page so that Legacy Device boot order + can be set for specified device type. + + @param UpdatePageId The form ID. It also spefies the legacy device ty= pe. + + +**/ +VOID +UpdateLegacyDeviceOrderPage ( + IN UINT16 UpdatePageId + ) +{ + LEGACY_MENU_OPTION *OptionMenu; + LEGACY_MENU_ENTRY *NewMenuEntry; + EFI_STRING_ID StrRef; + EFI_STRING_ID StrRefHelp; + UINT16 *Default; + UINT16 Index; + UINT16 Key; + CHAR16 String[100]; + CHAR16 *TypeStr; + CHAR16 *TypeStrHelp; + CHAR16 *FormTitle; + VOID *OptionsOpCodeHandle; + VOID *DefaultOpCodeHandle; + + Key =3D 0; + StrRef =3D 0; + StrRefHelp =3D 0; + OptionMenu =3D NULL; + TypeStr =3D NULL; + TypeStrHelp =3D NULL; + Default =3D NULL; + + RefreshLegacyUpdateData(); + + // + // Create oneof option list + // + switch (UpdatePageId) { + case FORM_FLOPPY_BOOT_ID: + OptionMenu =3D (LEGACY_MENU_OPTION *) &LegacyFDMenu; + Key =3D (UINT16) LEGACY_FD_QUESTION_ID; + TypeStr =3D STR_FLOPPY; + TypeStrHelp =3D STR_FLOPPY_HELP; + FormTitle =3D STR_FLOPPY_TITLE; + Default =3D mLegacyBootOptionPrivate->MaintainMapData->CurrentNvDa= ta.LegacyFD; + break; + + case FORM_HARDDISK_BOOT_ID: + OptionMenu =3D (LEGACY_MENU_OPTION *) &LegacyHDMenu; + Key =3D (UINT16) LEGACY_HD_QUESTION_ID; + TypeStr =3D STR_HARDDISK; + TypeStrHelp =3D STR_HARDDISK_HELP; + FormTitle =3D STR_HARDDISK_TITLE; + Default =3D mLegacyBootOptionPrivate->MaintainMapData->CurrentNvDa= ta.LegacyHD; + break; + + case FORM_CDROM_BOOT_ID: + OptionMenu =3D (LEGACY_MENU_OPTION *) &LegacyCDMenu; + Key =3D (UINT16) LEGACY_CD_QUESTION_ID; + TypeStr =3D STR_CDROM; + TypeStrHelp =3D STR_CDROM_HELP; + FormTitle =3D STR_CDROM_TITLE; + Default =3D mLegacyBootOptionPrivate->MaintainMapData->CurrentNvDa= ta.LegacyCD; + break; + + case FORM_NET_BOOT_ID: + OptionMenu =3D (LEGACY_MENU_OPTION *) &LegacyNETMenu; + Key =3D (UINT16) LEGACY_NET_QUESTION_ID; + TypeStr =3D STR_NET; + TypeStrHelp =3D STR_NET_HELP; + FormTitle =3D STR_NET_TITLE; + Default =3D mLegacyBootOptionPrivate->MaintainMapData->CurrentNvDa= ta.LegacyNET; + break; + + case FORM_BEV_BOOT_ID: + OptionMenu =3D (LEGACY_MENU_OPTION *) &LegacyBEVMenu; + Key =3D (UINT16) LEGACY_BEV_QUESTION_ID; + TypeStr =3D STR_BEV; + TypeStrHelp =3D STR_BEV_HELP; + FormTitle =3D STR_BEV_TITLE; + Default =3D mLegacyBootOptionPrivate->MaintainMapData->CurrentNvDa= ta.LegacyBEV; + break; + + default: + DEBUG ((EFI_D_ERROR, "Invalid command ID for updating page!\n")); + return; + } + + HiiSetString (mLegacyBootOptionPrivate->HiiHandle, STRING_TOKEN(STR_ORDE= R_CHANGE_PROMPT), FormTitle, NULL); + + CreateLegacyMenuStringToken (mLegacyBootOptionPrivate->HiiHandle, Option= Menu); + + OptionsOpCodeHandle =3D HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle !=3D NULL); + + + for (Index =3D 0; Index < OptionMenu->MenuNumber; Index++) { + NewMenuEntry =3D GetMenuEntry (OptionMenu, Index); + // + // Create OneOf for each legacy device + // + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + NewMenuEntry->DisplayStringToken, + 0, + EFI_IFR_TYPE_NUM_SIZE_16, + ((LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->BbsIndex + ); + } + + // + // Create OneOf for item "Disabled" + // + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE), + 0, + EFI_IFR_TYPE_NUM_SIZE_16, + 0xFF + ); + + // + // Create oneof tag here for FD/HD/CD #1 #2 + // + for (Index =3D 0; Index < OptionMenu->MenuNumber; Index++) { + DefaultOpCodeHandle =3D HiiAllocateOpCodeHandle (); + ASSERT (DefaultOpCodeHandle !=3D NULL); + + HiiCreateDefaultOpCode ( + DefaultOpCodeHandle, + EFI_HII_DEFAULT_CLASS_STANDARD, + EFI_IFR_TYPE_NUM_SIZE_16, + *Default++ + ); + + // + // Create the string for oneof tag + // + UnicodeSPrint (String, sizeof (String), TypeStr, Index); + StrRef =3D HiiSetString (mLegacyBootOptionPrivate->HiiHandle, 0, Strin= g, NULL); + + UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index); + StrRefHelp =3D HiiSetString (mLegacyBootOptionPrivate->HiiHandle, 0, S= tring, NULL); + + HiiCreateOneOfOpCode ( + mLegacyStartOpCodeHandle, + (EFI_QUESTION_ID) (Key + Index), + VARSTORE_ID_LEGACY_BOOT, + (UINT16) (Key + Index * 2 - CONFIG_OPTION_OFFSET), + StrRef, + StrRefHelp, + EFI_IFR_FLAG_CALLBACK, + EFI_IFR_NUMERIC_SIZE_2, + OptionsOpCodeHandle, + DefaultOpCodeHandle //NULL // + ); + + HiiFreeOpCodeHandle (DefaultOpCodeHandle); + } + + HiiUpdateForm ( + mLegacyBootOptionPrivate->HiiHandle, + &mLegacyBootOptionGuid, + LEGACY_ORDER_CHANGE_FORM_ID, + mLegacyStartOpCodeHandle, + mLegacyEndOpCodeHandle + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); +} + + +/** + Adjust question value when one question value has been changed. + + @param QuestionId The question id for the value changed question. + @param Value The value for the changed question. + +**/ +VOID +AdjustOptionValue ( + IN UINT16 QuestionId, + IN EFI_IFR_TYPE_VALUE *Value + ) +{ + UINTN Number; + UINT16 *Default; + LEGACY_BOOT_NV_DATA *CurrentNVMap; + UINT16 *CurrentVal; + UINTN Index; + UINTN Index2; + UINTN Index3; + UINTN NewValuePos; + UINTN OldValue; + UINTN NewValue; + UINT8 *DisMap; + UINTN Pos; + UINTN Bit; + + Number =3D 0; + CurrentVal =3D 0; + Default =3D NULL; + NewValue =3D 0; + NewValuePos =3D 0; + OldValue =3D 0; + + // + // Update Select FD/HD/CD/NET/BEV Order Form + // + ASSERT ((QuestionId >=3D LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_= BEV_QUESTION_ID + MAX_MENU_NUMBER)); + + CurrentNVMap =3D &mLegacyBootOptionPrivate->MaintainMapData->CurrentNvDa= ta; + HiiGetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeo= f (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap); + DisMap =3D mLegacyBootOptionPrivate->MaintainMapData->DisableMap; + + if (QuestionId >=3D LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUES= TION_ID + MAX_MENU_NUMBER) { + Number =3D (UINT16) LegacyFDMenu.MenuNumber; + CurrentVal =3D CurrentNVMap->LegacyFD; + Default =3D mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvD= ata.LegacyFD; + } else if (QuestionId >=3D LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_= HD_QUESTION_ID + MAX_MENU_NUMBER) { + Number =3D (UINT16) LegacyHDMenu.MenuNumber; + CurrentVal =3D CurrentNVMap->LegacyHD; + Default =3D mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvD= ata.LegacyHD; + } else if (QuestionId >=3D LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_= CD_QUESTION_ID + MAX_MENU_NUMBER) { + Number =3D (UINT16) LegacyCDMenu.MenuNumber; + CurrentVal =3D CurrentNVMap->LegacyCD; + Default =3D mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvD= ata.LegacyCD; + } else if (QuestionId >=3D LEGACY_NET_QUESTION_ID && QuestionId < LEGACY= _NET_QUESTION_ID + MAX_MENU_NUMBER) { + Number =3D (UINT16) LegacyNETMenu.MenuNumber; + CurrentVal =3D CurrentNVMap->LegacyNET; + Default =3D mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvD= ata.LegacyNET; + } else if (QuestionId >=3D LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY= _BEV_QUESTION_ID + MAX_MENU_NUMBER) { + Number =3D (UINT16) LegacyBEVMenu.MenuNumber; + CurrentVal =3D CurrentNVMap->LegacyBEV; + Default =3D mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvD= ata.LegacyBEV; + } + + // + // First, find the different position + // if there is change, it should be only one + // + for (Index =3D 0; Index < Number; Index++) { + if (CurrentVal[Index] !=3D Default[Index]) { + OldValue =3D Default[Index]; + NewValue =3D CurrentVal[Index]; + break; + } + } + + if (Index !=3D Number) { + // + // there is change, now process + // + if (0xFF =3D=3D NewValue) { + // + // This item will be disable + // Just move the items behind this forward to overlap it + // + Pos =3D OldValue / 8; + Bit =3D 7 - (OldValue % 8); + DisMap[Pos] =3D (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); + for (Index2 =3D Index; Index2 < Number - 1; Index2++) { + CurrentVal[Index2] =3D CurrentVal[Index2 + 1]; + } + + CurrentVal[Index2] =3D 0xFF; + } else { + for (Index2 =3D 0; Index2 < Number; Index2++) { + if (Index2 =3D=3D Index) { + continue; + } + + if (Default[Index2] =3D=3D NewValue) { + // + // If NewValue is in OldLegacyDev array + // remember its old position + // + NewValuePos =3D Index2; + break; + } + } + + if (Index2 !=3D Number) { + // + // We will change current item to an existing item + // (It's hard to describe here, please read code, it's like a cycl= e-moving) + // + for (Index2 =3D NewValuePos; Index2 !=3D Index;) { + if (NewValuePos < Index) { + CurrentVal[Index2] =3D Default[Index2 + 1]; + Index2++; + } else { + CurrentVal[Index2] =3D Default[Index2 - 1]; + Index2--; + } + } + } else { + // + // If NewValue is not in OldlegacyDev array, we are changing to a = disabled item + // so we should modify DisMap to reflect the change + // + Pos =3D NewValue / 8; + Bit =3D 7 - (NewValue % 8); + DisMap[Pos] =3D (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit))); + if (0xFF !=3D OldValue) { + // + // Because NewValue is a item that was disabled before + // so after changing the OldValue should be disabled + // actually we are doing a swap of enable-disable states of two = items + // + Pos =3D OldValue / 8; + Bit =3D 7 - (OldValue % 8); + DisMap[Pos] =3D (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); + } + } + } + // + // To prevent DISABLE appears in the middle of the list + // we should perform a re-ordering + // + Index3 =3D Index; + Index =3D 0; + while (Index < Number) { + if (0xFF !=3D CurrentVal[Index]) { + Index++; + continue; + } + + Index2 =3D Index; + Index2++; + while (Index2 < Number) { + if (0xFF !=3D CurrentVal[Index2]) { + break; + } + + Index2++; + } + + if (Index2 < Number) { + CurrentVal[Index] =3D CurrentVal[Index2]; + CurrentVal[Index2] =3D 0xFF; + } + + Index++; + } + + // + // Return correct question value. + // + Value->u16 =3D CurrentVal[Index3]; + CopyMem (Default, CurrentVal, sizeof (UINT16) * Number); + } + + // + // Pass changed uncommitted data back to Form Browser + // + HiiSetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeo= f (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap, NULL); +} + +/** + This call back function is registered with Boot Manager formset. + When user selects a boot option, this call back function will + be triggered. The boot option is saved for later processing. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original expo= rting driver + so that it can identify the type of data to expec= t. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original = exporting driver. + @param ActionRequest On return, points to the action requested by the = callback function. + + @retval EFI_SUCCESS The callback successfully handled the act= ion. + @retval EFI_INVALID_PARAMETER The setup browser call this function with= invalid parameters. + +**/ +EFI_STATUS +EFIAPI +LegacyBootOptionCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + if (Action !=3D EFI_BROWSER_ACTION_CHANGED && Action !=3D EFI_BROWSER_AC= TION_CHANGING && Action !=3D EFI_BROWSER_ACTION_FORM_OPEN) { + // + // Do nothing for other UEFI Action. Only do call back when data is ch= anged or the form is open. + // + return EFI_UNSUPPORTED; + } + + if ((Value =3D=3D NULL) || (ActionRequest =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (Action =3D=3D EFI_BROWSER_ACTION_FORM_OPEN) { + if (QuestionId =3D=3D FORM_FLOPPY_BOOT_ID) { + if (!mFirstEnterLegacyForm) { + // + // The leagcyBootMaintUiLib depends on the LegacyBootManagerLib to= realize its functionality. + // We need to do the leagcy boot options related actions after the= LegacyBootManagerLib has been initialized. + // Opening the legacy menus is the appropriate time that the Legac= yBootManagerLib has already been initialized. + // + mFirstEnterLegacyForm =3D TRUE; + GetLegacyOptions (); + GetLegacyOptionsOrder (); + } + } + } + + if (Action =3D=3D EFI_BROWSER_ACTION_CHANGING) { + switch (QuestionId) { + case FORM_FLOPPY_BOOT_ID: + case FORM_HARDDISK_BOOT_ID: + case FORM_CDROM_BOOT_ID: + case FORM_NET_BOOT_ID: + case FORM_BEV_BOOT_ID: + UpdateLegacyDeviceOrderPage (QuestionId); + break; + + default: + break; + } + } else if (Action =3D=3D EFI_BROWSER_ACTION_CHANGED) { + if ((Value =3D=3D NULL) || (ActionRequest =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((QuestionId >=3D LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BE= V_QUESTION_ID + MAX_MENU_NUMBER)) { + AdjustOptionValue(QuestionId, Value); + } + } + return EFI_SUCCESS; +} + + +/** + Create a menu entry by given menu type. + + @param MenuType The Menu type to be created. + + @retval NULL If failed to create the menu. + @return the new menu entry. + +**/ +LEGACY_MENU_ENTRY * +CreateMenuEntry ( + VOID + ) +{ + LEGACY_MENU_ENTRY *MenuEntry; + + // + // Create new menu entry + // + MenuEntry =3D AllocateZeroPool (sizeof (LEGACY_MENU_ENTRY)); + if (MenuEntry =3D=3D NULL) { + return NULL; + } + + MenuEntry->VariableContext =3D AllocateZeroPool (sizeof (LEGACY_DEVICE_C= ONTEXT)); + if (MenuEntry->VariableContext =3D=3D NULL) { + FreePool (MenuEntry); + return NULL; + } + + MenuEntry->Signature =3D LEGACY_MENU_ENTRY_SIGNATURE; + return MenuEntry; +} + +/** + + Base on the L"LegacyDevOrder" variable to build the current order data. + +**/ +VOID +GetLegacyOptionsOrder ( + VOID + ) +{ + UINTN VarSize; + UINT8 *VarData; + UINT8 *VarTmp; + LEGACY_DEV_ORDER_ENTRY *DevOrder; + UINT16 *LegacyDev; + UINTN Index; + LEGACY_MENU_OPTION *OptionMenu; + UINT16 VarDevOrder; + UINTN Pos; + UINTN Bit; + UINT8 *DisMap; + UINTN TotalLength; + + LegacyDev =3D NULL; + OptionMenu =3D NULL; + + DisMap =3D ZeroMem (mLegacyBootOptionPrivate->MaintainMapData->DisableMa= p, sizeof (mLegacyBootOptionPrivate->MaintainMapData->DisableMap)); + + // + // Get Device Order from variable + // + GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VO= ID **) &VarData, &VarSize); + VarTmp =3D VarData; + if (NULL !=3D VarData) { + DevOrder =3D (LEGACY_DEV_ORDER_ENTRY *) VarData; + while (VarData < VarTmp + VarSize) { + switch (DevOrder->BbsType) { + case BBS_FLOPPY: + LegacyDev =3D mLegacyBootOptionPrivate->MaintainMapData->InitialNv= Data.LegacyFD; + OptionMenu =3D &LegacyFDMenu; + break; + + case BBS_HARDDISK: + LegacyDev =3D mLegacyBootOptionPrivate->MaintainMapData->InitialNv= Data.LegacyHD; + OptionMenu =3D &LegacyHDMenu; + break; + + case BBS_CDROM: + LegacyDev =3D mLegacyBootOptionPrivate->MaintainMapData->InitialNv= Data.LegacyCD; + OptionMenu =3D &LegacyCDMenu; + break; + + case BBS_EMBED_NETWORK: + LegacyDev =3D mLegacyBootOptionPrivate->MaintainMapData->InitialNv= Data.LegacyNET; + OptionMenu =3D &LegacyNETMenu; + break; + + case BBS_BEV_DEVICE: + LegacyDev =3D mLegacyBootOptionPrivate->MaintainMapData->InitialNv= Data.LegacyBEV; + OptionMenu =3D &LegacyBEVMenu; + break; + + case BBS_UNKNOWN: + default: + ASSERT (FALSE); + DEBUG ((DEBUG_ERROR, "Unsupported device type found!\n")); + break; + } + + // + // Create oneof tag here for FD/HD/CD #1 #2 + // + for (Index =3D 0; Index < OptionMenu->MenuNumber; Index++) { + TotalLength =3D sizeof (BBS_TYPE) + sizeof (UINT16) + Index * size= of (UINT16); + VarDevOrder =3D *(UINT16 *) ((UINT8 *) DevOrder + TotalLength); + + if (0xFF00 =3D=3D (VarDevOrder & 0xFF00)) { + LegacyDev[Index] =3D 0xFF; + Pos =3D (VarDevOrder & 0xFF) / 8; + Bit =3D 7 - ((VarDevOrder & 0xFF) % 8); + DisMap[Pos] =3D (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); + } else { + LegacyDev[Index] =3D VarDevOrder & 0xFF; + } + } + + VarData ++; + VarData +=3D *(UINT16 *) VarData; + DevOrder =3D (LEGACY_DEV_ORDER_ENTRY *) VarData; + } + } + + CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData, &mL= egacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT= _NV_DATA)); + CopyMem (&mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData, &mLe= gacyBootOptionPrivate->MaintainMapData->InitialNvData, sizeof (LEGACY_BOOT_= NV_DATA)); +} + +/** + + Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios= .GetBbsInfo(). + +**/ +VOID +GetLegacyOptions ( + VOID + ) +{ + LEGACY_MENU_ENTRY *NewMenuEntry; + LEGACY_DEVICE_CONTEXT *NewLegacyDevContext; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; + UINTN BootOptionCount; + UINT16 Index; + UINTN FDNum; + UINTN HDNum; + UINTN CDNum; + UINTN NETNum; + UINTN BEVNum; + + // + // Initialize Bbs Table Context from BBS info data + // + InitializeListHead (&LegacyFDMenu.Head); + InitializeListHead (&LegacyHDMenu.Head); + InitializeListHead (&LegacyCDMenu.Head); + InitializeListHead (&LegacyNETMenu.Head); + InitializeListHead (&LegacyBEVMenu.Head); + + FDNum =3D 0; + HDNum =3D 0; + CDNum =3D 0; + NETNum =3D 0; + BEVNum =3D 0; + + EfiBootManagerConnectAll (); + + // + // for better user experience + // 1. User changes HD configuration (e.g.: unplug HDD), here we have a c= hance to remove the HDD boot option + // 2. User enables/disables UEFI PXE, here we have a chance to add/remov= e EFI Network boot option + // + EfiBootManagerRefreshAllBootOption (); + + BootOption =3D EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptio= nTypeBoot); + for (Index =3D 0; Index < BootOptionCount; Index++) { + if ((DevicePathType (BootOption[Index].FilePath) !=3D BBS_DEVICE_PATH)= || + (DevicePathSubType (BootOption[Index].FilePath) !=3D BBS_BBS_DP) + ) { + continue; + } + ASSERT (BootOption[Index].OptionalDataSize =3D=3D sizeof (LEGACY_BOOT_= OPTION_BBS_DATA)); + NewMenuEntry =3D CreateMenuEntry (); + ASSERT (NewMenuEntry !=3D NULL); + + NewLegacyDevContext =3D (LEGACY_DEVICE_CONTEXT *) NewMenu= Entry->VariableContext; + NewLegacyDevContext->BbsIndex =3D ((LEGACY_BOOT_OPTION_BBS_DATA *) = BootOption[Index].OptionalData)->BbsIndex; + NewLegacyDevContext->Description =3D AllocateCopyPool (StrSize (BootOp= tion[Index].Description), BootOption[Index].Description); + ASSERT (NewLegacyDevContext->Description !=3D NULL); + + NewMenuEntry->DisplayString =3D NewLegacyDevContext->Description; + NewMenuEntry->HelpString =3D NULL; + + switch (((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceTy= pe) { + case BBS_TYPE_FLOPPY: + InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link); + FDNum++; + break; + + case BBS_TYPE_HARDDRIVE: + InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link); + HDNum++; + break; + + case BBS_TYPE_CDROM: + InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link); + CDNum++; + break; + + case BBS_TYPE_EMBEDDED_NETWORK: + InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link); + NETNum++; + break; + + case BBS_TYPE_BEV: + InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link); + BEVNum++; + break; + } + } + + EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); + + LegacyFDMenu.MenuNumber =3D FDNum; + LegacyHDMenu.MenuNumber =3D HDNum; + LegacyCDMenu.MenuNumber =3D CDNum; + LegacyNETMenu.MenuNumber =3D NETNum; + LegacyBEVMenu.MenuNumber =3D BEVNum; +} + + +/** + + Install Boot Manager Menu driver. + + @param ImageHandle The image handle. + @param SystemTable The system table. + + @retval EFI_SUCEESS Install Boot manager menu success. + @retval Other Return error status. + +**/ +EFI_STATUS +EFIAPI +LegacyBootMaintUiLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + LEGACY_BOOT_OPTION_CALLBACK_DATA *LegacyBootOptionData; + + Status =3D gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID= **) &LegacyBios); + if (!EFI_ERROR (Status)) { + // + // Create LegacyBootOptionData structures for Driver Callback + // + LegacyBootOptionData =3D AllocateZeroPool (sizeof (LEGACY_BOOT_OPTION_= CALLBACK_DATA)); + ASSERT (LegacyBootOptionData !=3D NULL); + + LegacyBootOptionData->MaintainMapData =3D AllocateZeroPool (sizeof (LE= GACY_BOOT_MAINTAIN_DATA)); + ASSERT (LegacyBootOptionData->MaintainMapData !=3D NULL); + + LegacyBootOptionData->ConfigAccess.ExtractConfig =3D LegacyBootOptionE= xtractConfig; + LegacyBootOptionData->ConfigAccess.RouteConfig =3D LegacyBootOptionR= outeConfig; + LegacyBootOptionData->ConfigAccess.Callback =3D LegacyBootOptionC= allback; + + // + // Install Device Path Protocol and Config Access protocol to driver h= andle + // + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &LegacyBootOptionData->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mLegacyBootOptionHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &LegacyBootOptionData->ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Publish our HII data + // + LegacyBootOptionData->HiiHandle =3D HiiAddPackages ( + &mLegacyBootOptionGuid, + LegacyBootOptionData->DriverHandle, + LegacyBootMaintUiVfrBin, + LegacyBootMaintUiLibStrings, + NULL + ); + ASSERT (LegacyBootOptionData->HiiHandle !=3D NULL); + + mLegacyBootOptionPrivate =3D LegacyBootOptionData; + } + + return EFI_SUCCESS; +} + +/** + Destructor of Customized Display Library Instance. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The destructor completed successfully. + @retval Other value The destructor did not complete successfully. + +**/ +EFI_STATUS +EFIAPI +LegacyBootMaintUiLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + if (mLegacyBootOptionPrivate !=3D NULL && mLegacyBootOptionPrivate->Driv= erHandle !=3D NULL) { + Status =3D gBS->UninstallMultipleProtocolInterfaces ( + mLegacyBootOptionPrivate->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mLegacyBootOptionHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mLegacyBootOptionPrivate->ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + HiiRemovePackages (mLegacyBootOptionPrivate->HiiHandle); + + FreePool (mLegacyBootOptionPrivate->MaintainMapData); + FreePool (mLegacyBootOptionPrivate); + } + + return EFI_SUCCESS; +} + diff --git a/OvmfPkg/Csm/LegacyBootManagerLib/LegacyBm.c b/OvmfPkg/Csm/Lega= cyBootManagerLib/LegacyBm.c new file mode 100644 index 0000000000..6138a32ad7 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBootManagerLib/LegacyBm.c @@ -0,0 +1,1530 @@ +/** @file + This function deal with the legacy boot option, it create, delete + and manage the legacy boot option, all legacy boot option is getting from + the legacy BBS table. + +Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalLegacyBm.h" + +#define LEGACY_BM_BOOT_DESCRIPTION_LENGTH 32 + +/** + Initialize legacy boot manager library by call EfiBootManagerRegisterLeg= acyBootSupport + function to export two function pointer. + + @param ImageHandle The image handle. + @param SystemTable The system table. + + @retval EFI_SUCCESS The legacy boot manager library is initialized co= rrectly. + @return Other value if failed to initialize the legacy boot manager libr= ary. +**/ +EFI_STATUS +EFIAPI +LegacyBootManagerLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable +) +{ + EfiBootManagerRegisterLegacyBootSupport ( + LegacyBmRefreshAllBootOption, + LegacyBmBoot + ); + return EFI_SUCCESS; +} + +/** + Get the device type from the input legacy device path. + + @param DevicePath The legacy device path. + + @retval The legacy device type. +**/ +UINT16 +LegacyBmDeviceType ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + ASSERT ((DevicePathType (DevicePath) =3D=3D BBS_DEVICE_PATH) && + (DevicePathSubType (DevicePath) =3D=3D BBS_BBS_DP)); + return ((BBS_BBS_DEVICE_PATH *) DevicePath)->DeviceType; +} + +/** + Validate the BbsEntry base on the Boot Priority info in the BbsEntry. + + @param BbsEntry The input bbs entry info. + + @retval TRUE The BbsEntry is valid. + @retval FALSE The BbsEntry is invalid. +**/ +BOOLEAN +LegacyBmValidBbsEntry ( + IN BBS_TABLE *BbsEntry + ) +{ + switch (BbsEntry->BootPriority) { + case BBS_IGNORE_ENTRY: + case BBS_DO_NOT_BOOT_FROM: + case BBS_LOWEST_PRIORITY: + return FALSE; + default: + return TRUE; + } +} + +/** + Build Legacy Device Name String according. + + @param CurBBSEntry BBS Table. + @param Index Index. + @param BufSize The buffer size. + @param BootString The output string. + +**/ +VOID +LegacyBmBuildLegacyDevNameString ( + IN BBS_TABLE *CurBBSEntry, + IN UINTN Index, + IN UINTN BufSize, + OUT CHAR16 *BootString + ) +{ + CHAR16 *Fmt; + CHAR16 *Type; + CHAR8 *StringDesc; + CHAR8 StringBufferA[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1]; + CHAR16 StringBufferU[LEGACY_BM_BOOT_DESCRIPTION_LENGTH + 1]; + + switch (Index) { + // + // Primary Master + // + case 1: + Fmt =3D L"Primary Master %s"; + break; + + // + // Primary Slave + // + case 2: + Fmt =3D L"Primary Slave %s"; + break; + + // + // Secondary Master + // + case 3: + Fmt =3D L"Secondary Master %s"; + break; + + // + // Secondary Slave + // + case 4: + Fmt =3D L"Secondary Slave %s"; + break; + + default: + Fmt =3D L"%s"; + break; + } + + switch (CurBBSEntry->DeviceType) { + case BBS_FLOPPY: + Type =3D L"Floppy"; + break; + + case BBS_HARDDISK: + Type =3D L"Harddisk"; + break; + + case BBS_CDROM: + Type =3D L"CDROM"; + break; + + case BBS_PCMCIA: + Type =3D L"PCMCIAe"; + break; + + case BBS_USB: + Type =3D L"USB"; + break; + + case BBS_EMBED_NETWORK: + Type =3D L"Network"; + break; + + case BBS_BEV_DEVICE: + Type =3D L"BEVe"; + break; + + case BBS_UNKNOWN: + default: + Type =3D L"Unknown"; + break; + } + // + // If current BBS entry has its description then use it. + // + StringDesc =3D (CHAR8 *) (((UINTN) CurBBSEntry->DescStringSegment << 4) = + CurBBSEntry->DescStringOffset); + if (NULL !=3D StringDesc) { + // + // Only get fisrt 32 characters, this is suggested by BBS spec + // + CopyMem (StringBufferA, StringDesc, LEGACY_BM_BOOT_DESCRIPTION_LENGTH); + StringBufferA[LEGACY_BM_BOOT_DESCRIPTION_LENGTH] =3D 0; + AsciiStrToUnicodeStrS (StringBufferA, StringBufferU, ARRAY_SIZE (Strin= gBufferU)); + Fmt =3D L"%s"; + Type =3D StringBufferU; + } + + // + // BbsTable 16 entries are for onboard IDE. + // Set description string for SATA harddisks, Harddisk 0 ~ Harddisk 11 + // + if (Index >=3D 5 && Index <=3D 16 && (CurBBSEntry->DeviceType =3D=3D BBS= _HARDDISK || CurBBSEntry->DeviceType =3D=3D BBS_CDROM)) { + Fmt =3D L"%s %d"; + UnicodeSPrint (BootString, BufSize, Fmt, Type, Index - 5); + } else { + UnicodeSPrint (BootString, BufSize, Fmt, Type); + } +} + +/** + Get the Bbs index for the input boot option. + + @param BootOption The input boot option info. + @param BbsTable The input Bbs table. + @param BbsCount The input total bbs entry number. + @param BbsIndexUsed The array shows how many BBS table indexs have bee= n used. + + @retval The index for the input boot option. +**/ +UINT16 +LegacyBmFuzzyMatch ( + EFI_BOOT_MANAGER_LOAD_OPTION *BootOption, + BBS_TABLE *BbsTable, + UINT16 BbsCount, + BOOLEAN *BbsIndexUsed + ) +{ + UINT16 Index; + LEGACY_BM_BOOT_OPTION_BBS_DATA *BbsData; + CHAR16 Description[LEGACY_BM_BOOT_DESCRIPTION_LE= NGTH + 1]; + + BbsData =3D (LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption->OptionalData; + + // + // Directly check the BBS index stored in BootOption + // + if ((BbsData->BbsIndex < BbsCount) && + (LegacyBmDeviceType (BootOption->FilePath) =3D=3D BbsTable[BbsData->= BbsIndex].DeviceType)) { + LegacyBmBuildLegacyDevNameString ( + &BbsTable[BbsData->BbsIndex], + BbsData->BbsIndex, + sizeof (Description), + Description + ); + if ((StrCmp (Description, BootOption->Description) =3D=3D 0) && !BbsIn= dexUsed[BbsData->BbsIndex]) { + // + // If devices with the same description string are connected, + // the BbsIndex of the first device is returned for the other device= also. + // So, check if the BbsIndex is already being used, before assigning= the BbsIndex. + // + BbsIndexUsed[BbsData->BbsIndex] =3D TRUE; + return BbsData->BbsIndex; + } + } + + // + // BBS table could be changed (entry removed/moved) + // find the correct BBS index + // + for (Index =3D 0; Index < BbsCount; Index++) { + if (!LegacyBmValidBbsEntry (&BbsTable[Index]) || + (BbsTable[Index].DeviceType !=3D LegacyBmDeviceType (BootOption->F= ilePath))) { + continue; + } + + LegacyBmBuildLegacyDevNameString ( + &BbsTable[Index], + Index, + sizeof (Description), + Description + ); + if ((StrCmp (Description, BootOption->Description) =3D=3D 0) && !BbsIn= dexUsed[Index]) { + // + // If devices with the same description string are connected, + // the BbsIndex of the first device is assigned for the other device= also. + // So, check if the BbsIndex is already being used, before assigning= the corrected BbsIndex. + // + break; + } + } + + // + // Add the corrected BbsIndex in the UsedBbsIndex Buffer + // + if (Index !=3D BbsCount) { + BbsIndexUsed[Index] =3D TRUE; + } + + return Index; +} + +/** + + Update legacy device order base on the input info. + + @param LegacyDevOrder Legacy device order data buffer. + @param LegacyDevOrderSize Legacy device order data buffer size. + @param DeviceType Device type which need to check. + @param OldBbsIndex Old Bds Index. + @param NewBbsIndex New Bds Index, if it is -1,means remove this= option. + +**/ +VOID +LegacyBmUpdateBbsIndex ( + LEGACY_DEV_ORDER_ENTRY *LegacyDevOrder, + UINTN *LegacyDevOrderSize, + UINT16 DeviceType, + UINT16 OldBbsIndex, + UINT16 NewBbsIndex // Delete entry if -1 + ) +{ + LEGACY_DEV_ORDER_ENTRY *Entry; + UINTN Index; + + ASSERT (((LegacyDevOrder =3D=3D NULL) && (*LegacyDevOrderSize =3D=3D 0))= || + ((LegacyDevOrder !=3D NULL) && (*LegacyDevOrderSize !=3D 0)) + ); + + for (Entry =3D LegacyDevOrder; + Entry < (LEGACY_DEV_ORDER_ENTRY *) ((UINT8 *) LegacyDevOrder + *Leg= acyDevOrderSize); + Entry =3D (LEGACY_DEV_ORDER_ENTRY *) ((UINTN) Entry + sizeof (BBS_T= YPE) + Entry->Length) + ) { + if (Entry->BbsType =3D=3D DeviceType) { + for (Index =3D 0; Index < Entry->Length / sizeof (UINT16) - 1; Index= ++) { + if (Entry->Data[Index] =3D=3D OldBbsIndex) { + if (NewBbsIndex =3D=3D (UINT16) -1) { + // + // Delete the old entry + // + CopyMem ( + &Entry->Data[Index], + &Entry->Data[Index + 1], + (UINT8 *) LegacyDevOrder + *LegacyDevOrderSize - (UINT8 *) &= Entry->Data[Index + 1] + ); + Entry->Length -=3D sizeof (UINT16); + *LegacyDevOrderSize -=3D sizeof(UINT16); + } else { + Entry->Data[Index] =3D NewBbsIndex; + } + break; + } + } + break; + } + } +} + +/** + Delete all the legacy boot options. + + @retval EFI_SUCCESS All legacy boot options are deleted. +**/ +EFI_STATUS +LegacyBmDeleteAllBootOptions ( + VOID + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; + UINTN BootOptionCount; + + BootOption =3D EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptio= nTypeBoot); + for (Index =3D 0; Index < BootOptionCount; Index++) { + if ((DevicePathType (BootOption[Index].FilePath) =3D=3D BBS_DEVICE_PAT= H) && + (DevicePathSubType (BootOption[Index].FilePath) =3D=3D BBS_BBS_DP)= ) { + Status =3D EfiBootManagerDeleteLoadOptionVariable (BootOption[Index]= .OptionNumber, BootOption[Index].OptionType); + // + // Deleting variable with current variable implementation shouldn't = fail. + // + ASSERT_EFI_ERROR (Status); + } + } + + Status =3D gRT->SetVariable ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + 0, + 0, + NULL + ); + // + // Deleting variable with current variable implementation shouldn't fail. + // + ASSERT (Status =3D=3D EFI_SUCCESS || Status =3D=3D EFI_NOT_FOUND); + + return EFI_SUCCESS; +} + + +/** + Delete all the invalid legacy boot options. + + @retval EFI_SUCCESS All invalide legacy boot options are del= eted. + @retval EFI_OUT_OF_RESOURCES Fail to allocate necessary memory. + @retval EFI_NOT_FOUND Fail to retrive variable of boot order. +**/ +EFI_STATUS +LegacyBmDeleteAllInvalidBootOptions ( + VOID + ) +{ + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *HddInfo; + BBS_TABLE *BbsTable; + UINT16 BbsIndex; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN Index; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; + UINTN BootOptionCount; + LEGACY_DEV_ORDER_ENTRY *LegacyDevOrder; + UINTN LegacyDevOrderSize; + BOOLEAN *BbsIndexUsed; + + HddCount =3D 0; + BbsCount =3D 0; + HddInfo =3D NULL; + BbsTable =3D NULL; + + Status =3D gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL= , (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &HddInfo, + &BbsCount, + &BbsTable + ); + if (EFI_ERROR (Status)) { + return Status; + } + + GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VO= ID **) &LegacyDevOrder, &LegacyDevOrderSize); + + BootOption =3D EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptio= nTypeBoot); + + BbsIndexUsed =3D AllocateZeroPool (BbsCount * sizeof (BOOLEAN)); + ASSERT (BbsIndexUsed !=3D NULL); + + for (Index =3D 0; Index < BootOptionCount; Index++) { + // + // Skip non legacy boot option + // + if ((DevicePathType (BootOption[Index].FilePath) !=3D BBS_DEVICE_PATH)= || + (DevicePathSubType (BootOption[Index].FilePath) !=3D BBS_BBS_DP)) { + continue; + } + + BbsIndex =3D LegacyBmFuzzyMatch (&BootOption[Index], BbsTable, BbsCoun= t, BbsIndexUsed); + if (BbsIndex =3D=3D BbsCount) { + DEBUG ((EFI_D_INFO, "[LegacyBds] Delete Boot Option Boot%04x: %s\n",= (UINTN) BootOption[Index].OptionNumber, BootOption[Index].Description)); + // + // Delete entry from LegacyDevOrder + // + LegacyBmUpdateBbsIndex ( + LegacyDevOrder, + &LegacyDevOrderSize, + LegacyBmDeviceType (BootOption[Index].FilePath), + ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData= )->BbsIndex, + (UINT16) -1 + ); + EfiBootManagerDeleteLoadOptionVariable (BootOption[Index].OptionNumb= er, BootOption[Index].OptionType); + } else { + if (((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalDa= ta)->BbsIndex !=3D BbsIndex) { + DEBUG ((EFI_D_INFO, "[LegacyBds] Update Boot Option Boot%04x: %s B= bs0x%04x->Bbs0x%04x\n", (UINTN) BootOption[Index].OptionNumber, BootOption[= Index].Description, + (UINTN) ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Ind= ex].OptionalData)->BbsIndex, (UINTN) BbsIndex)); + // + // Update the BBS index in LegacyDevOrder + // + LegacyBmUpdateBbsIndex ( + LegacyDevOrder, + &LegacyDevOrderSize, + LegacyBmDeviceType (BootOption[Index].FilePath), + ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalDa= ta)->BbsIndex, + BbsIndex + ); + + // + // Update the OptionalData in the Boot#### variable + // + ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData= )->BbsIndex =3D BbsIndex; + EfiBootManagerLoadOptionToVariable (&BootOption[Index]); + } + } + } + EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); + + if (LegacyDevOrder !=3D NULL) { + Status =3D gRT->SetVariable ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOL= ATILE, + LegacyDevOrderSize, + LegacyDevOrder + ); + // + // Shrink variable with current variable implementation shouldn't fail. + // + ASSERT_EFI_ERROR (Status); + + FreePool (LegacyDevOrder); + } + FreePool(BbsIndexUsed); + return Status; +} + +/** + Create legacy boot option. + + @param BootOption Ponter to the boot option which will be crated. + @param BbsEntry The input bbs entry info. + @param BbsIndex The BBS index. + + @retval EFI_SUCCESS Create legacy boot option successfully. + @retval EFI_INVALID_PARAMETER Invalid input parameter. + +**/ +EFI_STATUS +LegacyBmCreateLegacyBootOption ( + IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *BootOption, + IN BBS_TABLE *BbsEntry, + IN UINT16 BbsIndex + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + CHAR16 Description[LEGACY_BM_BOOT_DESCRIPTION_LENG= TH + 1]; + CHAR8 HelpString[LEGACY_BM_BOOT_DESCRIPTION_LENGT= H + 1]; + UINTN StringLen; + LEGACY_BM_BOOT_OPTION_BBS_DATA *OptionalData; + BBS_BBS_DEVICE_PATH *BbsNode; + + if ((BootOption =3D=3D NULL) || (BbsEntry =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + LegacyBmBuildLegacyDevNameString (BbsEntry, BbsIndex, sizeof (Descriptio= n), Description); + + // + // Create the BBS device path with description string + // + UnicodeStrToAsciiStrS (Description, HelpString, sizeof (HelpString)); + StringLen =3D AsciiStrLen (HelpString); + DevicePath =3D AllocatePool (sizeof (BBS_BBS_DEVICE_PATH) + StringLen + = END_DEVICE_PATH_LENGTH); + ASSERT (DevicePath !=3D NULL); + + BbsNode =3D (BBS_BBS_DEVICE_PATH *) DevicePath; + SetDevicePathNodeLength (BbsNode, sizeof (BBS_BBS_DEVICE_PATH) + StringL= en); + BbsNode->Header.Type =3D BBS_DEVICE_PATH; + BbsNode->Header.SubType =3D BBS_BBS_DP; + BbsNode->DeviceType =3D BbsEntry->DeviceType; + CopyMem (&BbsNode->StatusFlag, &BbsEntry->StatusFlags, sizeof (BBS_STATU= S_FLAGS)); + CopyMem (BbsNode->String, HelpString, StringLen + 1); + + SetDevicePathEndNode (NextDevicePathNode (BbsNode)); + + // + // Create the OptionalData + // + OptionalData =3D AllocatePool (sizeof (LEGACY_BM_BOOT_OPTION_BBS_DATA)); + ASSERT (OptionalData !=3D NULL); + OptionalData->BbsIndex =3D BbsIndex; + + // + // Create the BootOption + // + Status =3D EfiBootManagerInitializeLoadOption ( + BootOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + LOAD_OPTION_ACTIVE, + Description, + DevicePath, + (UINT8 *) OptionalData, + sizeof (LEGACY_BM_BOOT_OPTION_BBS_DATA) + ); + FreePool (DevicePath); + FreePool (OptionalData); + + return Status; +} + +/** + Fill the device order buffer. + + @param BbsTable The BBS table. + @param BbsType The BBS Type. + @param BbsCount The BBS Count. + @param Buf device order buffer. + + @return The device order buffer. + +**/ +UINT16 * +LegacyBmFillDevOrderBuf ( + IN BBS_TABLE *BbsTable, + IN BBS_TYPE BbsType, + IN UINTN BbsCount, + OUT UINT16 *Buf + ) +{ + UINTN Index; + + for (Index =3D 0; Index < BbsCount; Index++) { + if (!LegacyBmValidBbsEntry (&BbsTable[Index])) { + continue; + } + + if (BbsTable[Index].DeviceType !=3D BbsType) { + continue; + } + + *Buf =3D (UINT16) (Index & 0xFF); + Buf++; + } + + return Buf; +} + +/** + Create the device order buffer. + + @param BbsTable The BBS table. + @param BbsCount The BBS Count. + + @retval EFI_SUCCES The buffer is created and the EFI variabl= e named + VAR_LEGACY_DEV_ORDER and EfiLegacyDevOrde= rGuid is + set correctly. + @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough. + @retval EFI_DEVICE_ERROR Fail to add the device order into EFI var= iable fail + because of hardware error. +**/ +EFI_STATUS +LegacyBmCreateDevOrder ( + IN BBS_TABLE *BbsTable, + IN UINT16 BbsCount + ) +{ + UINTN Index; + UINTN FDCount; + UINTN HDCount; + UINTN CDCount; + UINTN NETCount; + UINTN BEVCount; + UINTN TotalSize; + UINTN HeaderSize; + LEGACY_DEV_ORDER_ENTRY *DevOrder; + LEGACY_DEV_ORDER_ENTRY *DevOrderPtr; + EFI_STATUS Status; + + FDCount =3D 0; + HDCount =3D 0; + CDCount =3D 0; + NETCount =3D 0; + BEVCount =3D 0; + TotalSize =3D 0; + HeaderSize =3D sizeof (BBS_TYPE) + sizeof (UINT16); + DevOrder =3D NULL; + Status =3D EFI_SUCCESS; + + // + // Count all boot devices + // + for (Index =3D 0; Index < BbsCount; Index++) { + if (!LegacyBmValidBbsEntry (&BbsTable[Index])) { + continue; + } + + switch (BbsTable[Index].DeviceType) { + case BBS_FLOPPY: + FDCount++; + break; + + case BBS_HARDDISK: + HDCount++; + break; + + case BBS_CDROM: + CDCount++; + break; + + case BBS_EMBED_NETWORK: + NETCount++; + break; + + case BBS_BEV_DEVICE: + BEVCount++; + break; + + default: + break; + } + } + + TotalSize +=3D (HeaderSize + sizeof (UINT16) * FDCount); + TotalSize +=3D (HeaderSize + sizeof (UINT16) * HDCount); + TotalSize +=3D (HeaderSize + sizeof (UINT16) * CDCount); + TotalSize +=3D (HeaderSize + sizeof (UINT16) * NETCount); + TotalSize +=3D (HeaderSize + sizeof (UINT16) * BEVCount); + + // + // Create buffer to hold all boot device order + // + DevOrder =3D AllocateZeroPool (TotalSize); + if (NULL =3D=3D DevOrder) { + return EFI_OUT_OF_RESOURCES; + } + DevOrderPtr =3D DevOrder; + + DevOrderPtr->BbsType =3D BBS_FLOPPY; + DevOrderPtr->Length =3D (UINT16) (sizeof (DevOrderPtr->Length) + FDCoun= t * sizeof (UINT16)); + DevOrderPtr =3D (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrder= Buf (BbsTable, BBS_FLOPPY, BbsCount, DevOrderPtr->Data); + + DevOrderPtr->BbsType =3D BBS_HARDDISK; + DevOrderPtr->Length =3D (UINT16) (sizeof (UINT16) + HDCount * sizeof (U= INT16)); + DevOrderPtr =3D (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrder= Buf (BbsTable, BBS_HARDDISK, BbsCount, DevOrderPtr->Data); + + DevOrderPtr->BbsType =3D BBS_CDROM; + DevOrderPtr->Length =3D (UINT16) (sizeof (UINT16) + CDCount * sizeof (U= INT16)); + DevOrderPtr =3D (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrder= Buf (BbsTable, BBS_CDROM, BbsCount, DevOrderPtr->Data); + + DevOrderPtr->BbsType =3D BBS_EMBED_NETWORK; + DevOrderPtr->Length =3D (UINT16) (sizeof (UINT16) + NETCount * sizeof (= UINT16)); + DevOrderPtr =3D (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrder= Buf (BbsTable, BBS_EMBED_NETWORK, BbsCount, DevOrderPtr->Data); + + DevOrderPtr->BbsType =3D BBS_BEV_DEVICE; + DevOrderPtr->Length =3D (UINT16) (sizeof (UINT16) + BEVCount * sizeof (= UINT16)); + DevOrderPtr =3D (LEGACY_DEV_ORDER_ENTRY *) LegacyBmFillDevOrder= Buf (BbsTable, BBS_BEV_DEVICE, BbsCount, DevOrderPtr->Data); + + ASSERT (TotalSize =3D=3D ((UINTN) DevOrderPtr - (UINTN) DevOrder)); + + // + // Save device order for legacy boot device to variable. + // + Status =3D gRT->SetVariable ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLAT= ILE, + TotalSize, + DevOrder + ); + FreePool (DevOrder); + + return Status; +} + +/** + Add the legacy boot devices from BBS table into + the legacy device boot order. + + @retval EFI_SUCCESS The boot devices are added successfully. + @retval EFI_NOT_FOUND The legacy boot devices are not found. + @retval EFI_OUT_OF_RESOURCES Memmory or storage is not enough. + @retval EFI_DEVICE_ERROR Fail to add the legacy device boot order i= nto EFI variable + because of hardware error. +**/ +EFI_STATUS +LegacyBmUpdateDevOrder ( + VOID + ) +{ + LEGACY_DEV_ORDER_ENTRY *DevOrder; + LEGACY_DEV_ORDER_ENTRY *NewDevOrder; + LEGACY_DEV_ORDER_ENTRY *Ptr; + LEGACY_DEV_ORDER_ENTRY *NewPtr; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *LocalHddInfo; + BBS_TABLE *LocalBbsTable; + UINTN Index; + UINTN Index2; + UINTN *Idx; + UINTN FDCount; + UINTN HDCount; + UINTN CDCount; + UINTN NETCount; + UINTN BEVCount; + UINTN TotalSize; + UINTN HeaderSize; + UINT16 *NewFDPtr; + UINT16 *NewHDPtr; + UINT16 *NewCDPtr; + UINT16 *NewNETPtr; + UINT16 *NewBEVPtr; + UINT16 *NewDevPtr; + UINTN FDIndex; + UINTN HDIndex; + UINTN CDIndex; + UINTN NETIndex; + UINTN BEVIndex; + + Idx =3D NULL; + FDCount =3D 0; + HDCount =3D 0; + CDCount =3D 0; + NETCount =3D 0; + BEVCount =3D 0; + TotalSize =3D 0; + HeaderSize =3D sizeof (BBS_TYPE) + sizeof (UINT16); + FDIndex =3D 0; + HDIndex =3D 0; + CDIndex =3D 0; + NETIndex =3D 0; + BEVIndex =3D 0; + NewDevPtr =3D NULL; + + Status =3D gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL= , (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + if (EFI_ERROR (Status)) { + return Status; + } + + GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VO= ID **) &DevOrder, NULL); + if (NULL =3D=3D DevOrder) { + return LegacyBmCreateDevOrder (LocalBbsTable, BbsCount); + } + // + // First we figure out how many boot devices with same device type respe= ctively + // + for (Index =3D 0; Index < BbsCount; Index++) { + if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) { + continue; + } + + switch (LocalBbsTable[Index].DeviceType) { + case BBS_FLOPPY: + FDCount++; + break; + + case BBS_HARDDISK: + HDCount++; + break; + + case BBS_CDROM: + CDCount++; + break; + + case BBS_EMBED_NETWORK: + NETCount++; + break; + + case BBS_BEV_DEVICE: + BEVCount++; + break; + + default: + break; + } + } + + TotalSize +=3D (HeaderSize + FDCount * sizeof (UINT16)); + TotalSize +=3D (HeaderSize + HDCount * sizeof (UINT16)); + TotalSize +=3D (HeaderSize + CDCount * sizeof (UINT16)); + TotalSize +=3D (HeaderSize + NETCount * sizeof (UINT16)); + TotalSize +=3D (HeaderSize + BEVCount * sizeof (UINT16)); + + NewDevOrder =3D AllocateZeroPool (TotalSize); + if (NULL =3D=3D NewDevOrder) { + return EFI_OUT_OF_RESOURCES; + } + + // + // copy FD + // + Ptr =3D DevOrder; + NewPtr =3D NewDevOrder; + NewPtr->BbsType =3D Ptr->BbsType; + NewPtr->Length =3D (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16= )); + for (Index =3D 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) { + if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || + LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType !=3D BBS_FLOPPY + ) { + continue; + } + + NewPtr->Data[FDIndex] =3D Ptr->Data[Index]; + FDIndex++; + } + NewFDPtr =3D NewPtr->Data; + + // + // copy HD + // + Ptr =3D (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length /= sizeof (UINT16) - 1]); + NewPtr =3D (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Le= ngth / sizeof (UINT16) -1]); + NewPtr->BbsType =3D Ptr->BbsType; + NewPtr->Length =3D (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16= )); + for (Index =3D 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) { + if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || + LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType !=3D BBS_HARDDISK + ) { + continue; + } + + NewPtr->Data[HDIndex] =3D Ptr->Data[Index]; + HDIndex++; + } + NewHDPtr =3D NewPtr->Data; + + // + // copy CD + // + Ptr =3D (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (= UINT16) - 1]); + NewPtr =3D (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / si= zeof (UINT16) -1]); + NewPtr->BbsType =3D Ptr->BbsType; + NewPtr->Length =3D (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16= )); + for (Index =3D 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) { + if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || + LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType !=3D BBS_CDROM + ) { + continue; + } + + NewPtr->Data[CDIndex] =3D Ptr->Data[Index]; + CDIndex++; + } + NewCDPtr =3D NewPtr->Data; + + // + // copy NET + // + Ptr =3D (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (= UINT16) - 1]); + NewPtr =3D (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / si= zeof (UINT16) -1]); + NewPtr->BbsType =3D Ptr->BbsType; + NewPtr->Length =3D (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT1= 6)); + for (Index =3D 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) { + if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || + LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType !=3D BBS_EMBED_N= ETWORK + ) { + continue; + } + + NewPtr->Data[NETIndex] =3D Ptr->Data[Index]; + NETIndex++; + } + NewNETPtr =3D NewPtr->Data; + + // + // copy BEV + // + Ptr =3D (LEGACY_DEV_ORDER_ENTRY *) (&Ptr->Data[Ptr->Length / sizeof (= UINT16) - 1]); + NewPtr =3D (LEGACY_DEV_ORDER_ENTRY *) (&NewPtr->Data[NewPtr->Length / si= zeof (UINT16) -1]); + NewPtr->BbsType =3D Ptr->BbsType; + NewPtr->Length =3D (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT1= 6)); + for (Index =3D 0; Index < Ptr->Length / sizeof (UINT16) - 1; Index++) { + if (!LegacyBmValidBbsEntry (&LocalBbsTable[Ptr->Data[Index] & 0xFF]) || + LocalBbsTable[Ptr->Data[Index] & 0xFF].DeviceType !=3D BBS_BEV_DEV= ICE + ) { + continue; + } + + NewPtr->Data[BEVIndex] =3D Ptr->Data[Index]; + BEVIndex++; + } + NewBEVPtr =3D NewPtr->Data; + + for (Index =3D 0; Index < BbsCount; Index++) { + if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) { + continue; + } + + switch (LocalBbsTable[Index].DeviceType) { + case BBS_FLOPPY: + Idx =3D &FDIndex; + NewDevPtr =3D NewFDPtr; + break; + + case BBS_HARDDISK: + Idx =3D &HDIndex; + NewDevPtr =3D NewHDPtr; + break; + + case BBS_CDROM: + Idx =3D &CDIndex; + NewDevPtr =3D NewCDPtr; + break; + + case BBS_EMBED_NETWORK: + Idx =3D &NETIndex; + NewDevPtr =3D NewNETPtr; + break; + + case BBS_BEV_DEVICE: + Idx =3D &BEVIndex; + NewDevPtr =3D NewBEVPtr; + break; + + default: + Idx =3D NULL; + break; + } + // + // at this point we have copied those valid indexes to new buffer + // and we should check if there is any new appeared boot device + // + if (Idx !=3D NULL) { + for (Index2 =3D 0; Index2 < *Idx; Index2++) { + if ((NewDevPtr[Index2] & 0xFF) =3D=3D (UINT16) Index) { + break; + } + } + + if (Index2 =3D=3D *Idx) { + // + // Index2 =3D=3D *Idx means we didn't find Index + // so Index is a new appeared device's index in BBS table + // insert it before disabled indexes. + // + for (Index2 =3D 0; Index2 < *Idx; Index2++) { + if ((NewDevPtr[Index2] & 0xFF00) =3D=3D 0xFF00) { + break; + } + } + CopyMem (&NewDevPtr[Index2 + 1], &NewDevPtr[Index2], (*Idx - Index= 2) * sizeof (UINT16)); + NewDevPtr[Index2] =3D (UINT16) (Index & 0xFF); + (*Idx)++; + } + } + } + + FreePool (DevOrder); + + Status =3D gRT->SetVariable ( + VAR_LEGACY_DEV_ORDER, + &gEfiLegacyDevOrderVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLAT= ILE, + TotalSize, + NewDevOrder + ); + FreePool (NewDevOrder); + + return Status; +} + +/** + Set Boot Priority for specified device type. + + @param DeviceType The device type. + @param BbsIndex The BBS index to set the highest priority. Ignore= when -1. + @param LocalBbsTable The BBS table. + @param Priority The prority table. + + @retval EFI_SUCCESS The function completes successfully. + @retval EFI_NOT_FOUND Failed to find device. + @retval EFI_OUT_OF_RESOURCES Failed to get the efi variable of device o= rder. + +**/ +EFI_STATUS +LegacyBmSetPriorityForSameTypeDev ( + IN UINT16 DeviceType, + IN UINTN BbsIndex, + IN OUT BBS_TABLE *LocalBbsTable, + IN OUT UINT16 *Priority + ) +{ + LEGACY_DEV_ORDER_ENTRY *DevOrder; + LEGACY_DEV_ORDER_ENTRY *DevOrderPtr; + UINTN DevOrderSize; + UINTN Index; + + GetVariable2 (VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, (VO= ID **) &DevOrder, &DevOrderSize); + if (NULL =3D=3D DevOrder) { + return EFI_OUT_OF_RESOURCES; + } + + DevOrderPtr =3D DevOrder; + while ((UINT8 *) DevOrderPtr < (UINT8 *) DevOrder + DevOrderSize) { + if (DevOrderPtr->BbsType =3D=3D DeviceType) { + break; + } + + DevOrderPtr =3D (LEGACY_DEV_ORDER_ENTRY *) ((UINTN) DevOrderPtr + size= of (BBS_TYPE) + DevOrderPtr->Length); + } + + if ((UINT8 *) DevOrderPtr >=3D (UINT8 *) DevOrder + DevOrderSize) { + FreePool (DevOrder); + return EFI_NOT_FOUND; + } + + if (BbsIndex !=3D (UINTN) -1) { + // + // In case the BBS entry isn't valid because devices were plugged or r= emoved. + // + if (!LegacyBmValidBbsEntry (&LocalBbsTable[BbsIndex]) || (LocalBbsTabl= e[BbsIndex].DeviceType !=3D DeviceType)) { + FreePool (DevOrder); + return EFI_NOT_FOUND; + } + LocalBbsTable[BbsIndex].BootPriority =3D *Priority; + (*Priority)++; + } + // + // If the high byte of the DevIndex is 0xFF, it indicates that this devi= ce has been disabled. + // + for (Index =3D 0; Index < DevOrderPtr->Length / sizeof (UINT16) - 1; Ind= ex++) { + if ((DevOrderPtr->Data[Index] & 0xFF00) =3D=3D 0xFF00) { + // + // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority =3D BBS_DISABL= ED_ENTRY; + // + } else if (DevOrderPtr->Data[Index] !=3D BbsIndex) { + LocalBbsTable[DevOrderPtr->Data[Index]].BootPriority =3D *Priority; + (*Priority)++; + } + } + + FreePool (DevOrder); + return EFI_SUCCESS; +} + +/** + Print the BBS Table. + + @param LocalBbsTable The BBS table. + @param BbsCount The count of entry in BBS table. +**/ +VOID +LegacyBmPrintBbsTable ( + IN BBS_TABLE *LocalBbsTable, + IN UINT16 BbsCount + ) +{ + UINT16 Index; + + DEBUG ((DEBUG_INFO, "\n")); + DEBUG ((DEBUG_INFO, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n")); + DEBUG ((DEBUG_INFO, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D\n")); + for (Index =3D 0; Index < BbsCount; Index++) { + if (!LegacyBmValidBbsEntry (&LocalBbsTable[Index])) { + continue; + } + + DEBUG ( + (DEBUG_INFO, + " %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n", + (UINTN) Index, + (UINTN) LocalBbsTable[Index].BootPriority, + (UINTN) LocalBbsTable[Index].Bus, + (UINTN) LocalBbsTable[Index].Device, + (UINTN) LocalBbsTable[Index].Function, + (UINTN) LocalBbsTable[Index].Class, + (UINTN) LocalBbsTable[Index].SubClass, + (UINTN) LocalBbsTable[Index].DeviceType, + (UINTN) * (UINT16 *) &LocalBbsTable[Index].StatusFlags, + (UINTN) LocalBbsTable[Index].BootHandlerSegment, + (UINTN) LocalBbsTable[Index].BootHandlerOffset, + (UINTN) ((LocalBbsTable[Index].MfgStringSegment << 4) + LocalBbsTabl= e[Index].MfgStringOffset), + (UINTN) ((LocalBbsTable[Index].DescStringSegment << 4) + LocalBbsTab= le[Index].DescStringOffset)) + ); + } + + DEBUG ((DEBUG_INFO, "\n")); +} + +/** + Set the boot priority for BBS entries based on boot option entry and boo= t order. + + @param BootOption The boot option is to be checked for refre= sh BBS table. + + @retval EFI_SUCCESS The boot priority for BBS entries is refre= shed successfully. + @retval EFI_NOT_FOUND BBS entries can't be found. + @retval EFI_OUT_OF_RESOURCES Failed to get the legacy device boot order. +**/ +EFI_STATUS +LegacyBmRefreshBbsTableForBoot ( + IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption + ) +{ + EFI_STATUS Status; + UINT16 BbsIndex; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *LocalHddInfo; + BBS_TABLE *LocalBbsTable; + UINT16 DevType; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN Index; + UINT16 Priority; + UINT16 *DeviceType; + UINTN DeviceTypeCount; + UINTN DeviceTypeIndex; + EFI_BOOT_MANAGER_LOAD_OPTION *Option; + UINTN OptionCount; + + HddCount =3D 0; + BbsCount =3D 0; + LocalHddInfo =3D NULL; + LocalBbsTable =3D NULL; + DevType =3D BBS_UNKNOWN; + + Status =3D gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL= , (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // First, set all the present devices' boot priority to BBS_UNPRIORITIZE= D_ENTRY + // We will set them according to the settings setup by user + // + for (Index =3D 0; Index < BbsCount; Index++) { + if (LegacyBmValidBbsEntry (&LocalBbsTable[Index])) { + LocalBbsTable[Index].BootPriority =3D BBS_UNPRIORITIZED_ENTRY; + } + } + // + // boot priority always starts at 0 + // + Priority =3D 0; + if ((DevicePathType (BootOption->FilePath) =3D=3D BBS_DEVICE_PATH) && + (DevicePathSubType (BootOption->FilePath) =3D=3D BBS_BBS_DP)) { + // + // If BootOption stands for a legacy boot option, we prioritize the de= vices with the same type first. + // + DevType =3D LegacyBmDeviceType (BootOption->FilePath); + BbsIndex =3D ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOption->OptionalD= ata)->BbsIndex; + Status =3D LegacyBmSetPriorityForSameTypeDev ( + DevType, + BbsIndex, + LocalBbsTable, + &Priority + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // we have to set the boot priority for other BBS entries with different= device types + // + Option =3D EfiBootManagerGetLoadOptions (&OptionCount, LoadOpti= onTypeBoot); + DeviceType =3D AllocatePool (sizeof (UINT16) * OptionCount); + ASSERT (DeviceType !=3D NULL); + DeviceType[0] =3D DevType; + DeviceTypeCount =3D 1; + for (Index =3D 0; Index < OptionCount; Index++) { + if ((DevicePathType (Option[Index].FilePath) !=3D BBS_DEVICE_PATH) || + (DevicePathSubType (Option[Index].FilePath) !=3D BBS_BBS_DP)) { + continue; + } + + DevType =3D LegacyBmDeviceType (Option[Index].FilePath); + for (DeviceTypeIndex =3D 0; DeviceTypeIndex < DeviceTypeCount; DeviceT= ypeIndex++) { + if (DeviceType[DeviceTypeIndex] =3D=3D DevType) { + break; + } + } + if (DeviceTypeIndex < DeviceTypeCount) { + // + // We don't want to process twice for a device type + // + continue; + } + + DeviceType[DeviceTypeCount] =3D DevType; + DeviceTypeCount++; + + Status =3D LegacyBmSetPriorityForSameTypeDev ( + DevType, + (UINTN) -1, + LocalBbsTable, + &Priority + ); + } + EfiBootManagerFreeLoadOptions (Option, OptionCount); + + DEBUG_CODE_BEGIN(); + LegacyBmPrintBbsTable (LocalBbsTable, BbsCount); + DEBUG_CODE_END(); + + return Status; +} + + +/** + Boot the legacy system with the boot option. + + @param BootOption The legacy boot option which have BBS device path + On return, BootOption->Status contains the boot statu= s. + EFI_UNSUPPORTED There is no legacybios protocol, d= o not support + legacy boot. + EFI_STATUS The status of LegacyBios->LegacyBo= ot (). +**/ +VOID +EFIAPI +LegacyBmBoot ( + IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + + Status =3D gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID= **) &LegacyBios); + if (EFI_ERROR (Status)) { + // + // If no LegacyBios protocol we do not support legacy boot + // + BootOption->Status =3D EFI_UNSUPPORTED; + return; + } + // + // Notes: if we separate the int 19, then we don't need to refresh BBS + // + Status =3D LegacyBmRefreshBbsTableForBoot (BootOption); + if (EFI_ERROR (Status)) { + BootOption->Status =3D Status; + return; + } + + BootOption->Status =3D LegacyBios->LegacyBoot ( + LegacyBios, + (BBS_BBS_DEVICE_PATH *) BootOption->F= ilePath, + BootOption->OptionalDataSize, + BootOption->OptionalData + ); +} + +/** + This function enumerates all the legacy boot options. + + @param BootOptionCount Return the legacy boot option count. + + @retval Pointer to the legacy boot option buffer. +**/ +EFI_BOOT_MANAGER_LOAD_OPTION * +LegacyBmEnumerateAllBootOptions ( + UINTN *BootOptionCount + ) +{ + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *HddInfo; + BBS_TABLE *BbsTable; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINT16 Index; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + + ASSERT (BootOptionCount !=3D NULL); + + BootOptions =3D NULL; + *BootOptionCount =3D 0; + BbsCount =3D 0; + + Status =3D gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL= , (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return NULL; + } + + Status =3D LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &HddInfo, + &BbsCount, + &BbsTable + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + for (Index =3D 0; Index < BbsCount; Index++) { + if (!LegacyBmValidBbsEntry (&BbsTable[Index])) { + continue; + } + + BootOptions =3D ReallocatePool ( + sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCo= unt), + sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * (*BootOptionCo= unt + 1), + BootOptions + ); + ASSERT (BootOptions !=3D NULL); + + Status =3D LegacyBmCreateLegacyBootOption (&BootOptions[(*BootOptionCo= unt)++], &BbsTable[Index], Index); + ASSERT_EFI_ERROR (Status); + } + + return BootOptions; +} + +/** + Return the index of the boot option in the boot option array. + + The function compares the Description, FilePath, OptionalData. + + @param Key The input boot option which is compared with. + @param Array The input boot option array. + @param Count The count of the input boot options. + + @retval The index of the input boot option in the array. + +**/ +INTN +LegacyBmFindBootOption ( + IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key, + IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array, + IN UINTN Count + ) +{ + UINTN Index; + + for (Index =3D 0; Index < Count; Index++) { + if ((StrCmp (Key->Description, Array[Index].Description) =3D=3D 0) && + (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSi= ze (Key->FilePath)) =3D=3D 0) && + (Key->OptionalDataSize =3D=3D Array[Index].OptionalDataSize) && + (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->Op= tionalDataSize) =3D=3D 0)) { + return (INTN) Index; + } + } + + return -1; +} + +/** + Refresh all legacy boot options. + +**/ +VOID +EFIAPI +LegacyBmRefreshAllBootOption ( + VOID + ) +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN RootBridgeHandleCount; + EFI_HANDLE *RootBridgeHandleBuffer; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN RootBridgeIndex; + UINTN Index; + UINTN Flags; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + EFI_BOOT_MANAGER_LOAD_OPTION *ExistingBootOptions; + UINTN ExistingBootOptionCount; + + Status =3D gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID= **) &LegacyBios); + if (EFI_ERROR (Status)) { + LegacyBmDeleteAllBootOptions (); + return; + } + PERF_START (NULL, "LegacyBootOptionEnum", "BDS", 0); + + // + // Before enumerating the legacy boot option, we need to dispatch all th= e legacy option roms + // to ensure the GetBbsInfo() counts all the legacy devices. + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &RootBridgeHandleCount, + &RootBridgeHandleBuffer + ); + for (RootBridgeIndex =3D 0; RootBridgeIndex < RootBridgeHandleCount; Roo= tBridgeIndex++) { + gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL,= NULL, FALSE); + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + for (Index =3D 0; Index < HandleCount; Index++) { + // + // Start the thunk driver so that the legacy option rom gets dispatc= hed. + // Note: We don't directly call InstallPciRom because some thunk dri= vers + // (e.g. BlockIo thunk driver) depend on the immediate result after = dispatching + // + Status =3D LegacyBios->CheckPciRom ( + LegacyBios, + HandleBuffer[Index], + NULL, + NULL, + &Flags + ); + if (!EFI_ERROR (Status)) { + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE); + } + } + } + + // + // Same algorithm pattern as the EfiBootManagerRefreshAllBootOption + // Firstly delete the invalid legacy boot options, + // then enumreate and save the newly appeared legacy boot options + // the last step is legacy boot option special action to refresh the Leg= acyDevOrder variable + // + LegacyBmDeleteAllInvalidBootOptions (); + + ExistingBootOptions =3D EfiBootManagerGetLoadOptions (&ExistingBootOptio= nCount, LoadOptionTypeBoot); + BootOptions =3D LegacyBmEnumerateAllBootOptions (&BootOptionCo= unt); + + for (Index =3D 0; Index < BootOptionCount; Index++) { + if (LegacyBmFindBootOption (&BootOptions[Index], ExistingBootOptions, = ExistingBootOptionCount) =3D=3D -1) { + Status =3D EfiBootManagerAddLoadOptionVariable (&BootOptions[Index],= (UINTN) -1); + DEBUG (( + EFI_D_INFO, "[LegacyBds] New Boot Option: Boot%04x Bbs0x%04x %s %r= \n", + (UINTN) BootOptions[Index].OptionNumber, + (UINTN) ((LEGACY_BM_BOOT_OPTION_BBS_DATA *) BootOptions[Index].Opt= ionalData)->BbsIndex, + BootOptions[Index].Description, + Status + )); + // + // Continue upon failure to add boot option. + // + } + } + + EfiBootManagerFreeLoadOptions (ExistingBootOptions, ExistingBootOptionCo= unt); + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); + + // + // Failure to create LegacyDevOrder variable only impacts the boot order. + // + LegacyBmUpdateDevOrder (); + + PERF_END (NULL, "LegacyBootOptionEnum", "BDS", 0); +} diff --git a/OvmfPkg/Csm/BiosThunk/VideoDxe/BiosVideoDxe.uni b/OvmfPkg/Csm/= BiosThunk/VideoDxe/BiosVideoDxe.uni new file mode 100644 index 0000000000..326d9de822 --- /dev/null +++ b/OvmfPkg/Csm/BiosThunk/VideoDxe/BiosVideoDxe.uni @@ -0,0 +1,17 @@ +// /** @file +// Video driver based on legacy bios. +// +// This driver by using Legacy Bios protocol service to support csm Video +// and produce Graphics Output Protocol. +// +// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Video driver base= d on legacy bios" + +#string STR_MODULE_DESCRIPTION #language en-US "This driver uses = the Legacy Bios protocol service to utilize the CSM Video Support and produ= ce the Graphics Output Protocol." + diff --git a/OvmfPkg/Csm/BiosThunk/VideoDxe/BiosVideoDxeExtra.uni b/OvmfPkg= /Csm/BiosThunk/VideoDxe/BiosVideoDxeExtra.uni new file mode 100644 index 0000000000..23fb8fe0b0 --- /dev/null +++ b/OvmfPkg/Csm/BiosThunk/VideoDxe/BiosVideoDxeExtra.uni @@ -0,0 +1,14 @@ +// /** @file +// BiosVideoDxe Localized Strings and Content +// +// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"Legacy Video DXE Driver" + + diff --git a/OvmfPkg/Csm/LegacyBiosDxe/IA32/InterruptTable.nasm b/OvmfPkg/C= sm/LegacyBiosDxe/IA32/InterruptTable.nasm new file mode 100644 index 0000000000..90bfdffb0b --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/IA32/InterruptTable.nasm @@ -0,0 +1,63 @@ +;; @file +; Interrupt Redirection Template +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;; + +SECTION .text + +;-------------------------------------------------------------------------= --- +; Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x= 6F +; +; Input: None +; +; Output: None +; +; Prototype: VOID +; InterruptRedirectionTemplate ( +; VOID +; ); +; +; Saves: None +; +; Modified: None +; +; Description: Contains the code that is copied into low memory (below 64= 0K). +; This code reflects interrupts 0x68-0x6f to interrupts 0x08= -0x0f. +; This template must be copied into low memory, and the IDT = entries +; 0x68-0x6F must be point to the low memory copy of this cod= e. Each +; entry is 4 bytes long, so IDT entries 0x68-0x6F can be eas= ily +; computed. +; +;-------------------------------------------------------------------------= --- + +global ASM_PFX(InterruptRedirectionTemplate) +ASM_PFX(InterruptRedirectionTemplate): + int 0x8 + DB 0xcf ; IRET + nop + int 0x9 + DB 0xcf ; IRET + nop + int 0xa + DB 0xcf ; IRET + nop + int 0xb + DB 0xcf ; IRET + nop + int 0xc + DB 0xcf ; IRET + nop + int 0xd + DB 0xcf ; IRET + nop + int 0xe + DB 0xcf ; IRET + nop + int 0xf + DB 0xcf ; IRET + nop + diff --git a/OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.uni b/OvmfPkg/Csm/Lega= cyBiosDxe/LegacyBiosDxe.uni new file mode 100644 index 0000000000..1a41d6d856 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.uni @@ -0,0 +1,16 @@ +// /** @file +// Legacy Bios Module to support CSM. +// +// This driver installs Legacy Bios Protocol to support CSM module work in= EFI system. +// +// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Legacy Bios Modul= e to support CSM" + +#string STR_MODULE_DESCRIPTION #language en-US "This driver insta= lls Legacy Bios Protocol to support CSM module work in a EFI system." + diff --git a/OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxeExtra.uni b/OvmfPkg/Csm= /LegacyBiosDxe/LegacyBiosDxeExtra.uni new file mode 100644 index 0000000000..a02e783d94 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxeExtra.uni @@ -0,0 +1,14 @@ +// /** @file +// LegacyBiosDxe Localized Strings and Content +// +// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"Legacy BIOS Support DXE Driver" + + diff --git a/OvmfPkg/Csm/LegacyBiosDxe/X64/InterruptTable.nasm b/OvmfPkg/Cs= m/LegacyBiosDxe/X64/InterruptTable.nasm new file mode 100644 index 0000000000..afc2f0e639 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBiosDxe/X64/InterruptTable.nasm @@ -0,0 +1,64 @@ +;; @file +; Interrupt Redirection Template +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;; + + DEFAULT REL + SECTION .text + +;-------------------------------------------------------------------------= --- +; Procedure: InterruptRedirectionTemplate: Redirects interrupts 0x68-0x= 6F +; +; Input: None +; +; Output: None +; +; Prototype: VOID +; InterruptRedirectionTemplate ( +; VOID +; ); +; +; Saves: None +; +; Modified: None +; +; Description: Contains the code that is copied into low memory (below 64= 0K). +; This code reflects interrupts 0x68-0x6f to interrupts 0x08= -0x0f. +; This template must be copied into low memory, and the IDT = entries +; 0x68-0x6F must be point to the low memory copy of this cod= e. Each +; entry is 4 bytes long, so IDT entries 0x68-0x6F can be eas= ily +; computed. +; +;-------------------------------------------------------------------------= --- + +global ASM_PFX(InterruptRedirectionTemplate) +ASM_PFX(InterruptRedirectionTemplate): + int 0x8 + DB 0xcf ; IRET + nop + int 0x9 + DB 0xcf ; IRET + nop + int 0xa + DB 0xcf ; IRET + nop + int 0xb + DB 0xcf ; IRET + nop + int 0xc + DB 0xcf ; IRET + nop + int 0xd + DB 0xcf ; IRET + nop + int 0xe + DB 0xcf ; IRET + nop + int 0xf + DB 0xcf ; IRET + nop + diff --git a/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.uni b/Ov= mfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.uni new file mode 100644 index 0000000000..c2c100d378 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.uni @@ -0,0 +1,20 @@ +// /** @file +// Legacy Boot Maintainence UI module is library for BDS phase. +// +// Legacy Boot Maintainence UI module is library for BDS phase. +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_MODULE_ABSTRACT +#language en-US +"Legacy Boot Maintainence UI module is library for BDS phase." + +#string STR_MODULE_DESCRIPTION +#language en-US +"Legacy Boot Maintainence UI module is library for BDS phase." + + diff --git a/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiStrings.uni = b/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiStrings.uni new file mode 100644 index 0000000000..8d40ca1af1 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiStrings.uni @@ -0,0 +1,43 @@ +///** @file +// +// String definitions for Legacy Boot Maintainece Ui. +// +// Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+// SPDX-License-Identifier: BSD-2-Clause-Patent +// +//**/ + +/=3D# + +#langdef en-US "English" +#langdef fr-FR "Fran=C3=A7ais" + +#string STR_LEGACY_BOOT_PROMPT #language en-US "Legacy Boot Optio= ns Menu" + #language fr-FR "Legacy Boot Optio= ns Menu" +#string STR_LEGACY_BOOT_HELP #language en-US "Manager legacy bo= ot options in this driver." + #language fr-FR "Manager legacy bo= ot options in this driver." +#string STR_FORM_FLOPPY_BOOT_TITLE #language en-US "Set Legacy Floppy= Driver Order" + #language fr-FR "Set Legacy Floppy= Driver Order" +#string STR_FORM_FLOPPY_BOOT_HELP #language en-US "Set Legacy Floppy= Driver Order." + #language fr-FR "Set Legacy Floppy= Driver Order." +#string STR_FORM_HARDDISK_BOOT_TITLE #language en-US "Set Legacy HARDDI= SK Driver Order" + #language fr-FR "Set Legacy HARDDI= SK Driver Order" +#string STR_FORM_HARDDISK_BOOT_HELP #language en-US "Set Legacy HARDDI= SK Driver Order." + #language fr-FR "Set Legacy HARDDI= SK Driver Order." +#string STR_FORM_CDROM_BOOT_TITLE #language en-US "Set Legacy CDROM = Driver Order" + #language fr-FR "Set Legacy CDROM = Driver Order" +#string STR_FORM_CDROM_BOOT_HELP #language en-US "Set Legacy CDROM = Driver Order." + #language fr-FR "Set Legacy CDROM = Driver Order." +#string STR_FORM_NET_BOOT_TITLE #language en-US "Set Legacy NET Dr= iver Order" + #language fr-FR "Set Legacy NET Dr= iver Order" +#string STR_FORM_NET_BOOT_HELP #language en-US "Set Legacy NET Dr= iver Order." + #language fr-FR "Set Legacy NET Dr= iver Order." +#string STR_FORM_BEV_BOOT_TITLE #language en-US "Set Legacy BEV Dr= iver Order" + #language fr-FR "Set Legacy BEV Dr= iver Order" +#string STR_FORM_BEV_BOOT_HELP #language en-US "Set Legacy BEV Dr= iver Order." + #language fr-FR "Set Legacy BEV Dr= iver Order." +#string STR_ORDER_CHANGE_PROMPT #language en-US "Change Driver Boo= t Order." + #language fr-FR "Change Driver Boo= t Order." +#string STR_DISABLE_LEGACY_DEVICE #language en-US "Disabled" + #language fr-FR "Disabled" + diff --git a/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.Vfr b/Ov= mfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.Vfr new file mode 100644 index 0000000000..c879ca551f --- /dev/null +++ b/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiVfr.Vfr @@ -0,0 +1,67 @@ +///** @file +// =20 +// Browser formset. +// =20 +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// SPDX-License-Identifier: BSD-2-Clause-Patent +// =20 +//**/ + +#include "LegacyBootMaintUiVfr.h" + + +formset + guid =3D LEGACY_BOOT_OPTION_FORMSET_GUID, + title =3D STRING_TOKEN(STR_LEGACY_BOOT_PROMPT), + help =3D STRING_TOKEN(STR_LEGACY_BOOT_HELP), + classguid =3D EFI_IFR_BOOT_MAINTENANCE_GUID, + =20 + varstore LEGACY_BOOT_NV_DATA, + varid =3D VARSTORE_ID_LEGACY_BOOT, + name =3D LegacyBootData, + guid =3D LEGACY_BOOT_OPTION_FORMSET_GUID; + =20 + form formid =3D LEGACY_BOOT_FORM_ID, + title =3D STRING_TOKEN(STR_LEGACY_BOOT_PROMPT); + =20 + goto LEGACY_ORDER_CHANGE_FORM_ID, + prompt =3D STRING_TOKEN(STR_FORM_FLOPPY_BOOT_TITLE), + help =3D STRING_TOKEN(STR_FORM_FLOPPY_BOOT_HELP), + flags =3D INTERACTIVE, + key =3D FORM_FLOPPY_BOOT_ID; + + goto LEGACY_ORDER_CHANGE_FORM_ID, + prompt =3D STRING_TOKEN(STR_FORM_HARDDISK_BOOT_TITLE), + help =3D STRING_TOKEN(STR_FORM_HARDDISK_BOOT_HELP), + flags =3D INTERACTIVE, + key =3D FORM_HARDDISK_BOOT_ID; + + goto LEGACY_ORDER_CHANGE_FORM_ID, + prompt =3D STRING_TOKEN(STR_FORM_CDROM_BOOT_TITLE), + help =3D STRING_TOKEN(STR_FORM_CDROM_BOOT_HELP), + flags =3D INTERACTIVE, + key =3D FORM_CDROM_BOOT_ID; + + goto LEGACY_ORDER_CHANGE_FORM_ID, + prompt =3D STRING_TOKEN(STR_FORM_NET_BOOT_TITLE), + help =3D STRING_TOKEN(STR_FORM_NET_BOOT_HELP), + flags =3D INTERACTIVE, + key =3D FORM_NET_BOOT_ID; + + goto LEGACY_ORDER_CHANGE_FORM_ID, + prompt =3D STRING_TOKEN(STR_FORM_BEV_BOOT_TITLE), + help =3D STRING_TOKEN(STR_FORM_BEV_BOOT_HELP), + flags =3D INTERACTIVE, + key =3D FORM_BEV_BOOT_ID; + =20 + endform; + + form formid =3D LEGACY_ORDER_CHANGE_FORM_ID, + title =3D STRING_TOKEN(STR_ORDER_CHANGE_PROMPT); + =20 + label FORM_BOOT_LEGACY_DEVICE_ID; + label FORM_BOOT_LEGACY_LABEL_END; + =20 + endform; + +endformset; diff --git a/OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.uni b/Ov= mfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.uni new file mode 100644 index 0000000000..da2915a9a3 --- /dev/null +++ b/OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.uni @@ -0,0 +1,20 @@ +// /** @file +// Legacy Boot Manager module is library for BDS phase. +// +// Legacy Boot Manager module is library for BDS phase. +// +// Copyright (c) 2015, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_MODULE_ABSTRACT +#language en-US +"Legacy Boot Manager module is library for BDS phase." + +#string STR_MODULE_DESCRIPTION +#language en-US +"Legacy Boot Manager module is library for BDS phase." + + --=20 2.12.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#40649): https://edk2.groups.io/g/devel/message/40649 Mute This Topic: https://groups.io/mt/31627721/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 20:18:32 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+40651+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40651+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1557908872; cv=none; d=zoho.com; s=zohoarc; b=Jf9MhS3hCGrb4Idvd5c4mR5EBWv+IpiogMR/GYVV4L5aZbjRrMyAYf5dJyvn0ag39FlPFujg57l+ANUMQ37fXK3nQadvdGDCmiXhplGpL8JQrtKJ8Dy+S5ZhvyoK6ExirWVvimhmzpMm/IaWB7QCo6Pv0BIQWR5hts/fUaBOPh4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1557908872; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=MfVewLawlR2hfnvc2uvA+tq8bSQQNGv4uRIXZDVW3ek=; b=UlxfsOoSC9X+G4FgMSLskUQa2ocFyiyNEvzpBrAkTDWFqz7LMEAyXFSqYGpxF3nUpiKnnHgotHhuMNidW/6ldK+1YDBZRaO+VlXxb7kXSR4OBJdQ/1qJIu4lETwQP/wiCdzvfj0XuS2PAT5Gc2/2sC2QzjdtqGq9WzM5WXP2/QA= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40651+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1557908872753235.3471668149897; Wed, 15 May 2019 01:27:52 -0700 (PDT) Return-Path: X-Received: from mga12.intel.com (mga12.intel.com []) by groups.io with SMTP; Wed, 15 May 2019 01:27:51 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 May 2019 01:27:48 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by orsmga005.jf.intel.com with ESMTP; 15 May 2019 01:27:46 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , Ray Ni , David Woodhouse , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v1 2/9] OvmfPkg/OvmfPkg.dec: Add definitions for CSM-related Guid & Protocol Date: Wed, 15 May 2019 16:27:13 +0800 Message-Id: <20190515082720.12560-3-hao.a.wu@intel.com> In-Reply-To: <20190515082720.12560-1-hao.a.wu@intel.com> References: <20190515082720.12560-1-hao.a.wu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,hao.a.wu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1557908872; bh=BgD4khp2ky5Z/VM50PGT4ekcoMXDAMQWRt6tAP0n1Vk=; h=Cc:Date:From:Reply-To:Subject:To; b=jSRDH55iurqjgFM55NIZLnbQYu5RCWqg8Swj5JYVDjGjf8caVk0+cMg5WWRxoZUVxC5 crJ1hv90mN7CMSBRlzd9UMFXp/6jy37abo7LrBCCTVRgvH5fJlc3ww7gk6LBqq8wnIYmQ G0jbboPl59wpgJMgjbWk1Ak6t5smGWJHdHk= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1811 This commit will add the Guid definitions of the duplicated CSM-related Guids and Protocols from IntelFramework[Module]Pkg. Cc: Ray Ni Cc: David Woodhouse Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu --- OvmfPkg/OvmfPkg.dec | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 0e555c5c78..59eda563a2 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -79,6 +79,8 @@ gXenBusRootDeviceGuid =3D {0xa732241f, 0x383d, 0x4d9c, {0x= 8a, 0xe1, 0x8e, 0x09, 0x83, 0x75, 0x89, 0xd7}} gRootBridgesConnectedEventGroupGuid =3D {0x24a2d66f, 0xeedd, 0x4086, {0x= 90, 0x42, 0xf2, 0x6e, 0x47, 0x97, 0xee, 0x69}} gMicrosoftVendorGuid =3D {0x77fa9abd, 0x0359, 0x4d32, {0x= bd, 0x60, 0x28, 0xf4, 0xe7, 0x8f, 0x78, 0x4b}} + gEfiLegacyBiosGuid =3D {0x2E3044AC, 0x879F, 0x490F, {0x= 97, 0x60, 0xBB, 0xDF, 0xAF, 0x69, 0x5F, 0x50}} + gEfiLegacyDevOrderVariableGuid =3D {0xa56074db, 0x65fe, 0x45f7, {0x= bd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52}} =20 [Protocols] gVirtioDeviceProtocolGuid =3D {0xfa920010, 0x6785, 0x4941, {0x= b6, 0xec, 0x49, 0x8c, 0x57, 0x9f, 0x16, 0x0a}} @@ -86,6 +88,13 @@ gXenIoProtocolGuid =3D {0x6efac84f, 0x0ab0, 0x4747, {0x= 81, 0xbe, 0x85, 0x55, 0x62, 0x59, 0x04, 0x49}} gIoMmuAbsentProtocolGuid =3D {0xf8775d50, 0x8abd, 0x4adf, {0x= 92, 0xac, 0x85, 0x3e, 0x51, 0xf6, 0xc8, 0xdc}} gEfiLegacy8259ProtocolGuid =3D {0x38321dba, 0x4fe0, 0x4e17, {0x= 8a, 0xec, 0x41, 0x30, 0x55, 0xea, 0xed, 0xc1}} + gEfiFirmwareVolumeProtocolGuid =3D {0x389F751F, 0x1838, 0x4388, {0x= 83, 0x90, 0xcd, 0x81, 0x54, 0xbd, 0x27, 0xf8}} + gEfiIsaAcpiProtocolGuid =3D {0x64a892dc, 0x5561, 0x4536, {0x= 92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33, 0x55}} + gEfiIsaIoProtocolGuid =3D {0x7ee2bd44, 0x3da0, 0x11d4, {0x= 9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d}} + gEfiLegacyBiosProtocolGuid =3D {0xdb9a1e3d, 0x45cb, 0x4abb, {0x= 85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d}} + gEfiLegacyBiosPlatformProtocolGuid =3D {0x783658a3, 0x4172, 0x4421, {0x= a2, 0x99, 0xe0, 0x09, 0x07, 0x9c, 0x0c, 0xb4}} + gEfiLegacyInterruptProtocolGuid =3D {0x31ce593d, 0x108a, 0x485d, {0x= ad, 0xb2, 0x78, 0xf2, 0x1f, 0x29, 0x66, 0xbe}} + gEfiVgaMiniPortProtocolGuid =3D {0xc7735a2f, 0x88f5, 0x4882, {0x= ae, 0x63, 0xfa, 0xac, 0x8c, 0x8b, 0x86, 0xb3}} =20 [PcdsFixedAtBuild] gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0 --=20 2.12.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#40651): https://edk2.groups.io/g/devel/message/40651 Mute This Topic: https://groups.io/mt/31627723/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 20:18:32 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+40650+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40650+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1557908872; cv=none; d=zoho.com; s=zohoarc; b=DJNfC+ABQkeiouKGokwZgUC/LJRhBrLtacfZC/iL3Th1aXno4VOEpYyRHbfIaJkV+7NbP2Or86n8ijiDiPtvf7Y7qpHCfDJiJUrwg0s1GAto6q0cq13jO6dpo6U/+7vS01zD7edjBQHH6ehWZsLlkeY0nfiDM1bn8Ui9lkkKcKg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1557908872; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=giJjgnut69Vch2hlPzCsGVPXOzka8P5EwZcK50UtiTQ=; b=fYnsACmu3PKQUV3KXyYX43BEBFSihBfCorrb5QYRIm65shuo+/qSzq/rEi6mz4OM6zdezCvtetsKEL7p7JUqLOprjOOB7pVOMZH2BZEAH4FV2lvzBZdpGxqDkh0PMbgUQQeaRZRq+PAgmt/y0ESW9SJhRtKYQ9u3BIk9BqfXrg4= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40650+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1557908872443585.5462704087383; Wed, 15 May 2019 01:27:52 -0700 (PDT) Return-Path: X-Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by groups.io with SMTP; Wed, 15 May 2019 01:27:50 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 May 2019 01:27:50 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by orsmga005.jf.intel.com with ESMTP; 15 May 2019 01:27:48 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , Ray Ni , David Woodhouse , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v1 3/9] OvmfPkg/OvmfPkg.dec: Add the new include folder for CSM header files Date: Wed, 15 May 2019 16:27:14 +0800 Message-Id: <20190515082720.12560-4-hao.a.wu@intel.com> In-Reply-To: <20190515082720.12560-1-hao.a.wu@intel.com> References: <20190515082720.12560-1-hao.a.wu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,hao.a.wu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1557908871; bh=N7+5xi/snQ6gN9wohbPyZaOqB/8gh8kr3eUIqN4lGgc=; h=Cc:Date:From:Reply-To:Subject:To; b=w4MAPXpJJEv36wSceTTYVowhnF1zVa3Pq2XfGFT4V0OQ+ezqA9P1bi9wU2T3LFHWUFO hcvXctmHMGRKUUHx8kNf1ppF9tHuHghZ7TQEsWqLxicErpYjQ/5vbAvBmuZKMckI/BTMC qpHuaqQiF1HvSl4pYXSSzRO3QmfdyOLo8ss= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1811 The previous file-duplication commit has put all the CSM related header files within folder: OvmfPkg/Csm/Inclue. This commit will update the DEC file to add that folder under the '[Include]' section. Cc: Ray Ni Cc: David Woodhouse Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu --- OvmfPkg/OvmfPkg.dec | 1 + 1 file changed, 1 insertion(+) diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 59eda563a2..2251f4ca99 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -15,6 +15,7 @@ =20 [Includes] Include + Csm/Include =20 [LibraryClasses] ## @libraryclass Loads and boots a Linux kernel image --=20 2.12.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#40650): https://edk2.groups.io/g/devel/message/40650 Mute This Topic: https://groups.io/mt/31627722/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 20:18:32 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+40652+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40652+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1557908873; cv=none; d=zoho.com; s=zohoarc; b=SpLu5v26KDEweNaZbmfW0cfBrc+hSIa2czLTQSJisEln6iSjVqnqvYxur9tuOjLfINxbNSHmclPgygoTpg965CR/6T5b4+ERVrrXHguBNL5np2vfm2LklZ/waF82BZ6/YqbVKI8Vyx+sRTlrfTuc/ROWIvRdO7xhCR7BemMVSMs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1557908873; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=ysU7FhQekcEys4yHwIzf9k0NKS86fOJQrUXxJRYTOgs=; b=fxTIEZWsYdM+UxDPFS+lAP/1hcD6jDfGzdPXZDPf72FvnWkxqfYG5RHboe69rjOMhSjJuckckDZ2OAT4/kxtO/gLzDV+PKYDcucTm3i/vahrbY7RU5IrbufdwqbCycMyXM4l8PvcW/DIB0onUic6YNbecCbp6wou6+YjTpfebVo= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40652+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1557908873236217.96043876400392; Wed, 15 May 2019 01:27:53 -0700 (PDT) Return-Path: X-Received: from mga17.intel.com (mga17.intel.com []) by groups.io with SMTP; Wed, 15 May 2019 01:27:52 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 May 2019 01:27:52 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by orsmga005.jf.intel.com with ESMTP; 15 May 2019 01:27:50 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , Ray Ni , David Woodhouse , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v1 4/9] OvmfPkg/OvmfPkg.dec: Add PCD definitions used by copied CSM modules Date: Wed, 15 May 2019 16:27:15 +0800 Message-Id: <20190515082720.12560-5-hao.a.wu@intel.com> In-Reply-To: <20190515082720.12560-1-hao.a.wu@intel.com> References: <20190515082720.12560-1-hao.a.wu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,hao.a.wu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1557908872; bh=K3a9anQIE5xEoVNbqjN2yQmut0/kTdiHQEBdxr/nKfc=; h=Cc:Date:From:Reply-To:Subject:To; b=mA5DGJykUThGOsb8CRGHcMkdMEbBJOmSLZ+oKAtHLiUrf+d5PteKrBxIiu6JcwBUXt5 eNkn2TgNiPFqk720Z1ljGuJxtWmpun6d++1CAvVntoyBBcly4fnJbLXR7TVn8SY8rXZNC ECpoFM9bvTtRZ7n66z/Rr/DLJ4mm6nh5yZI= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1811 This commit will add the PCD definitions consumed by the duplicated drivers: * VideoDxe * LegacyBiosDxe into the OvmfPkg DEC file. Please note that, instead of adding these PCDs under section: [PcdsFixedAtBuild, PcdsDynamic, PcdsDynamicEx, PcdsPatchableInModule] as in IntelFrameworkModulePkg.dec file, they are added in section: [PcdsFixedAtBuild] in OvmfPkg.dec instead. Cc: Ray Ni Cc: David Woodhouse Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu --- OvmfPkg/OvmfPkg.dec | 58 ++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 2251f4ca99..9640360f62 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -160,6 +160,64 @@ # For the corresponding bits, 0 =3D Edge triggered and 1 =3D Level trig= gered. gUefiOvmfPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0000|UINT16|0x5 =20 + ## Indicates if BiosVideo driver will switch to 80x25 Text VGA Mode when + # exiting boot service. + # TRUE - Switch to Text VGA Mode. + # FALSE - Does not switch to Text VGA Mode. + gUefiOvmfPkgTokenSpaceGuid.PcdBiosVideoSetTextVgaModeEnable|FALSE|BOOLEA= N|0x28 + + ## Indicates if BiosVideo driver will check for VESA BIOS Extension serv= ice + # support. + # TRUE - Check for VESA BIOS Extension service. + # FALSE - Does not check for VESA BIOS Extension service. + gUefiOvmfPkgTokenSpaceGuid.PcdBiosVideoCheckVbeEnable|TRUE|BOOLEAN|0x29 + + ## Indicates if BiosVideo driver will check for VGA service support. + # NOTE: If both PcdBiosVideoCheckVbeEnable and PcdBiosVideoCheckVgaEnab= le + # are set to FALSE, that means Graphics Output protocol will not be + # installed, the VGA miniport protocol will be installed instead. + # TRUE - Check for VGA service.
+ # FALSE - Does not check for VGA service.
+ gUefiOvmfPkgTokenSpaceGuid.PcdBiosVideoCheckVgaEnable|TRUE|BOOLEAN|0x2a + + ## Indicates if memory space for legacy region will be set as cacheable. + # TRUE - Set cachebility for legacy region. + # FALSE - Does not set cachebility for legacy region. + gUefiOvmfPkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion|TRUE|BOOLEAN|0= x2b + + ## Specify memory size with bytes to reserve EBDA below 640K for OPROM. + # The value should be a multiple of 4KB. + gUefiOvmfPkgTokenSpaceGuid.PcdEbdaReservedMemorySize|0x8000|UINT32|0x2c + + ## Specify memory base address for OPROM to find free memory. + # Some OPROMs do not use EBDA or PMM to allocate memory for its usage, + # instead they find the memory filled with zero from 0x20000. + # The value should be a multiple of 4KB. + # The range should be below the EBDA reserved range from + # (CONVENTIONAL_MEMORY_TOP - Reserved EBDA Memory Size) to + # CONVENTIONAL_MEMORY_TOP. + gUefiOvmfPkgTokenSpaceGuid.PcdOpromReservedMemoryBase|0x60000|UINT32|0x2d + + ## Specify memory size with bytes for OPROM to find free memory. + # The value should be a multiple of 4KB. And the range should be below = the + # EBDA reserved range from + # (CONVENTIONAL_MEMORY_TOP - Reserved EBDA Memory Size) to + # CONVENTIONAL_MEMORY_TOP. + gUefiOvmfPkgTokenSpaceGuid.PcdOpromReservedMemorySize|0x28000|UINT32|0x2e + + ## Specify the end of address below 1MB for the OPROM. + # The last shadowed OpROM should not exceed this address. + gUefiOvmfPkgTokenSpaceGuid.PcdEndOpromShadowAddress|0xdffff|UINT32|0x2f + + ## Specify the low PMM (Post Memory Manager) size with bytes below 1MB. + # The value should be a multiple of 4KB. + # @Prompt Low PMM (Post Memory Manager) Size + gUefiOvmfPkgTokenSpaceGuid.PcdLowPmmMemorySize|0x10000|UINT32|0x30 + + ## Specify the high PMM (Post Memory Manager) size with bytes above 1MB. + # The value should be a multiple of 4KB. + gUefiOvmfPkgTokenSpaceGuid.PcdHighPmmMemorySize|0x400000|UINT32|0x31 + [PcdsDynamic, PcdsDynamicEx] gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 --=20 2.12.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#40652): https://edk2.groups.io/g/devel/message/40652 Mute This Topic: https://groups.io/mt/31627724/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 20:18:32 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+40653+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40653+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1557908875; cv=none; d=zoho.com; s=zohoarc; b=ewYRS8KSLctM9W6ID6tpdfs9mMiSe4c1dVubgdFaxzgF5YAbzyIUHMFHu9uyfI8T5QsZxKGftE5Hs4ozjHBb/arDAqv91jR8oFmRnPj2n6162gGe3AzGXPUCm/05BPUjsiMMd+6up+uHAQ9NhQ7lJ28hXe9kXAqAMfgR4kc1Zs0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1557908875; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=Ixc1aYnjhZigXteP3S3blr8Zad7UigLGEOGy5zVcmz4=; b=H9rDaH8t5yF7nGRlQrYvgNyjxxJPbV7pYuS6GWS3Z56Uy3DS3fngwmF3WTWyy40GC29GROkk+ltvt8XgiJL4lYR+9DrXKLR2xD9LrLeu1OQ7+8jrHQfj8rkFUa6jqntreYc0Uq6S6jt5XiwAG8RAF5k1td78RoZD7ze6vyTLKq8= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40653+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1557908875515308.83927839120156; Wed, 15 May 2019 01:27:55 -0700 (PDT) Return-Path: X-Received: from mga17.intel.com (mga17.intel.com []) by groups.io with SMTP; Wed, 15 May 2019 01:27:54 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 May 2019 01:27:54 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by orsmga005.jf.intel.com with ESMTP; 15 May 2019 01:27:52 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , Ray Ni , David Woodhouse , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v1 5/9] OvmfPkg/Csm/VideoDxe: Update to make it build for OVMF Date: Wed, 15 May 2019 16:27:16 +0800 Message-Id: <20190515082720.12560-6-hao.a.wu@intel.com> In-Reply-To: <20190515082720.12560-1-hao.a.wu@intel.com> References: <20190515082720.12560-1-hao.a.wu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,hao.a.wu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1557908874; bh=4sBVqb/1uiJQpk+tMo9xYvxVcVjaalKVYeaed7fHBpU=; h=Cc:Date:From:Reply-To:Subject:To; b=ZjeGQg8HrUCQBf6SPyHFi14XXzPNlYgSzDRqRS/T68ZR6gpygEJ7zLnl4VJIVPT55DW JpFikM8F81PsoiUdbMb70KpG0u5aDKOIz+OcQgFuvDTAUXfY9Af4+c1n9+nO6lg6bN8KF ly1KX5EhsOPbmxdsTA9AysYAJPrRzKYswM8= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1811 This commit will update the driver's INF file to: A) Assign a new file GUID; B) Consume the PCDs duplicated in OvmfPkg DEC file; C) Remove the IntelFramework[Module]Pkg DEC file dependency. Please note that a subsequent commit (final patch of the series) will: Replace the use of VideoDxe in IntelFrameworkModulePkg with the one copied in OvmfPkg within DSC/FDF files. Cc: Ray Ni Cc: David Woodhouse Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu --- OvmfPkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/OvmfPkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf b/OvmfPkg/Csm/Bios= Thunk/VideoDxe/VideoDxe.inf index 1526bc4cc2..1ed4020661 100644 --- a/OvmfPkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf +++ b/OvmfPkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf @@ -4,7 +4,7 @@ # This driver by using Legacy Bios protocol service to support csm Video # and produce Graphics Output Protocol. # -# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -14,7 +14,7 @@ INF_VERSION =3D 0x00010005 BASE_NAME =3D BiosVideoDxe MODULE_UNI_FILE =3D BiosVideoDxe.uni - FILE_GUID =3D 0B04B2ED-861C-42cd-A22F-C3AAFACCB896 + FILE_GUID =3D 8669E6C9-842B-4B49-BCC3-32C96D244750 MODULE_TYPE =3D UEFI_DRIVER VERSION_STRING =3D 1.0 =20 @@ -38,9 +38,7 @@ [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - + OvmfPkg/OvmfPkg.dec =20 [LibraryClasses] MemoryAllocationLib @@ -70,9 +68,9 @@ gEfiEdidOverrideProtocolGuid ## SOMETIMES_CONSUMES =20 [Pcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoSetTextVgaModeEnab= le ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVbeEnable = ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBiosVideoCheckVgaEnable = ## SOMETIMES_CONSUMES + gUefiOvmfPkgTokenSpaceGuid.PcdBiosVideoSetTextVgaModeEnable = ## CONSUMES + gUefiOvmfPkgTokenSpaceGuid.PcdBiosVideoCheckVbeEnable = ## CONSUMES + gUefiOvmfPkgTokenSpaceGuid.PcdBiosVideoCheckVgaEnable = ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution = ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution = ## SOMETIMES_CONSUMES =20 --=20 2.12.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#40653): https://edk2.groups.io/g/devel/message/40653 Mute This Topic: https://groups.io/mt/31627725/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 20:18:32 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+40654+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40654+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1557908877; cv=none; d=zoho.com; s=zohoarc; b=APxuAZD7/w26Go/rQ8hmPUd3lgIs8pFc3qez98HqZIHHGUn21NICbGhT1pCbuUeoTzmZDPWKFuKPhaG4FfOC+Rey1KYqWRs/+7jtPbbPhg65Sr8Hi3jduSbZVMZEYm79F7jPoUtljTxE3lkh+GXqH2+GKxSbjBx/45L6Suw4jb0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1557908877; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=eVVRXvHG2dab6wWlBJWCji8WBXgro9xSUdaeya4Ol0A=; b=Ex4Afq+EzyJ7pIUpT3sJCL4ArSocpE2hAtuogfpIDIH8SXwNYzZTT0Ypw+y8VZelvae/V1tRNjAQZd+pZlxW0KOueVIj9RtPc8zHsxFMj02GsHbcPvmvfaop4Mz6IRz5FfAvsVxDgWKJLF1mQjY+4FXIV3Vex76ACvEZw9wkAHo= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40654+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1557908877404341.8410992110887; Wed, 15 May 2019 01:27:57 -0700 (PDT) Return-Path: X-Received: from mga17.intel.com (mga17.intel.com []) by groups.io with SMTP; Wed, 15 May 2019 01:27:55 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 May 2019 01:27:55 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by orsmga005.jf.intel.com with ESMTP; 15 May 2019 01:27:54 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , Ray Ni , David Woodhouse , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v1 6/9] OvmfPkg/Csm/LegacyBiosDxe: Update to make it build for OVMF Date: Wed, 15 May 2019 16:27:17 +0800 Message-Id: <20190515082720.12560-7-hao.a.wu@intel.com> In-Reply-To: <20190515082720.12560-1-hao.a.wu@intel.com> References: <20190515082720.12560-1-hao.a.wu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,hao.a.wu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1557908876; bh=fS2ECLfdEWPMX4w0LehHocYWOZ0m1QpbTJisoBkF7jU=; h=Cc:Date:From:Reply-To:Subject:To; b=OOYeNlsh9YLFGXYcBKEeZ+6pKg0DBYLD7eWM/ZWi+okVbfVNm2wPVEa9Jja6hDQSDCN +HEBcLB2AHASF6qXrVzXskZ3qG91KwoQgrvnZvVXy7KIweKzQIG1ai7OOs0jfkpCc1MXz HO+2Fhn4J/YwMMvAHwv1eARVZT+DFctfzB8= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1811 This commit will update the driver's INF file to: A) Assign a new file GUID; B) Consume the PCDs duplicated in OvmfPkg DEC file; C) Remove the IntelFramework[Module]Pkg DEC file dependency. Please note that a subsequent commit (final patch of the series) will: Replace the use of LegacyBiosDxe in IntelFrameworkModulePkg with the one copied in OvmfPkg within DSC/FDF files. Cc: Ray Ni Cc: David Woodhouse Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu --- OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf | 22 +++++++++----------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf b/OvmfPkg/Csm/Lega= cyBiosDxe/LegacyBiosDxe.inf index 471d37365c..f6379dcc46 100644 --- a/OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf +++ b/OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf @@ -3,7 +3,7 @@ # # This driver installs Legacy Bios Protocol to support CSM module work in = EFI system. # -# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -13,7 +13,7 @@ INF_VERSION =3D 0x00010005 BASE_NAME =3D LegacyBiosDxe MODULE_UNI_FILE =3D LegacyBiosDxe.uni - FILE_GUID =3D F122A15C-C10B-4d54-8F48-60F4F06DD1AD + FILE_GUID =3D 46482D14-7CA1-4977-9DDB-64D747E13DE6 MODULE_TYPE =3D DXE_DRIVER VERSION_STRING =3D 1.0 =20 @@ -50,9 +50,7 @@ [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - + OvmfPkg/OvmfPkg.dec =20 [LibraryClasses] DevicePathLib @@ -116,13 +114,13 @@ gEdkiiIoMmuProtocolGuid ## CONSUMES =20 [Pcd] - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion= ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize = ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEndOpromShadowAddress = ## SOMETIMES_CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLowPmmMemorySize = ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdHighPmmMemorySize = ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemoryBase = ## CONSUMES - gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdOpromReservedMemorySize = ## CONSUMES + gUefiOvmfPkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion ## CONSUMES + gUefiOvmfPkgTokenSpaceGuid.PcdEbdaReservedMemorySize ## CONSUMES + gUefiOvmfPkgTokenSpaceGuid.PcdEndOpromShadowAddress ## SOMETIMES_= CONSUMES + gUefiOvmfPkgTokenSpaceGuid.PcdLowPmmMemorySize ## CONSUMES + gUefiOvmfPkgTokenSpaceGuid.PcdHighPmmMemorySize ## CONSUMES + gUefiOvmfPkgTokenSpaceGuid.PcdOpromReservedMemoryBase ## CONSUMES + gUefiOvmfPkgTokenSpaceGuid.PcdOpromReservedMemorySize ## CONSUMES =20 [Depex] gEfiLegacyRegion2ProtocolGuid AND gEfiLegacyInterruptProtocolGuid AND gE= fiLegacyBiosPlatformProtocolGuid AND gEfiLegacy8259ProtocolGuid AND gEfiGen= ericMemTestProtocolGuid AND gEfiCpuArchProtocolGuid AND gEfiTimerArchProtoc= olGuid AND gEfiVariableWriteArchProtocolGuid --=20 2.12.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#40654): https://edk2.groups.io/g/devel/message/40654 Mute This Topic: https://groups.io/mt/31627726/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 20:18:32 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+40655+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40655+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1557908878; cv=none; d=zoho.com; s=zohoarc; b=arSdUdGSAMn/gBqtyqpTGKDyERWg1tyjdWd8s1eMAIsIVDFbtp9eOGu1GRbgowIiWbkFL/4avfR2d4GpYj5CECuWEesRWKt6fEN8RMxVAK3Jj3wmUh//bUyXced3Cy277sSDJ1dDdQBeERA8NjcYR/MUbO7kVMrJbBcDpG8harU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1557908878; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=wsHqtiDKMzg6xXkxZtAGTO5jJiOXlJ5u5/E6O6FM/oA=; b=FZ+fc+KoNHoSR/Ucfb08p2C4hd6k3ajsd2zNZvLn59EWT9puivFjYc/wT4ZdnvVBAkG3uDlWHIPKFbj7bX+tIyRqylspwRosLF3hYFhkvwMZkuvseJdcQYBoJDNMxmGxOnsD0i0vr/bH5GIRevyYje6n5NsdgAGALYgxLn6rNzM= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40655+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1557908878948866.2329661783532; Wed, 15 May 2019 01:27:58 -0700 (PDT) Return-Path: X-Received: from mga17.intel.com (mga17.intel.com []) by groups.io with SMTP; Wed, 15 May 2019 01:27:58 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 May 2019 01:27:57 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by orsmga005.jf.intel.com with ESMTP; 15 May 2019 01:27:55 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , Ray Ni , David Woodhouse , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v1 7/9] OvmfPkg/Csm/LegacyBootMaintUiLib: Update to make it build for OVMF Date: Wed, 15 May 2019 16:27:18 +0800 Message-Id: <20190515082720.12560-8-hao.a.wu@intel.com> In-Reply-To: <20190515082720.12560-1-hao.a.wu@intel.com> References: <20190515082720.12560-1-hao.a.wu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,hao.a.wu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1557908878; bh=92Hpdl7cF7Z16wlkbBDVLxO49BKkD/2RvgSvRlR8BY8=; h=Cc:Date:From:Reply-To:Subject:To; b=DMpiWsNlRBmRh9nbr2dMmfVBwr7tMFKAGf0HXu3ONGZQPdvy4bocfBRLs+wVmgJQpA6 lJNMYvPrBve0gBc/jgB2RXe4kzQWqDs9qMNR9jf/ZI0H4oFKtVJ06Kqu4+pdnnvcP/uxo dwNct/mceqkM8fIS1MxjieFG1a8WqVPgyME= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1811 This commit will update the library's INF file to: A) Assign a new file GUID; B) Remove the IntelFramework[Module]Pkg DEC file dependency. Please note that a subsequent commit (final patch of the series) will: Replace the use of LegacyBootMaintUiLib in IntelFrameworkModulePkg with the one copied in OvmfPkg within DSC files. Cc: Ray Ni Cc: David Woodhouse Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu --- OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf b/Ov= mfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf index 557b8d8169..5cc64a1b2d 100644 --- a/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf +++ b/OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf @@ -1,7 +1,7 @@ ## @file # Legacy Boot Maintainence UI module is library for BDS phase. # -# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## @@ -10,7 +10,7 @@ INF_VERSION =3D 0x00010005 BASE_NAME =3D LegacyBootMaintUiLib MODULE_UNI_FILE =3D LegacyBootMaintUiLib.uni - FILE_GUID =3D e6f7f038-3ed9-401a-af1f-5ea7bf644d34 + FILE_GUID =3D 259A90B1-C151-43E5-8A71-82B4E3201F4E MODULE_TYPE =3D DXE_DRIVER VERSION_STRING =3D 1.0 LIBRARY_CLASS =3D NULL|DXE_DRIVER UEFI_APPLICATION @@ -32,8 +32,7 @@ [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec + OvmfPkg/OvmfPkg.dec =20 [LibraryClasses] DevicePathLib --=20 2.12.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#40655): https://edk2.groups.io/g/devel/message/40655 Mute This Topic: https://groups.io/mt/31627727/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 20:18:32 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+40656+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40656+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1557908880; cv=none; d=zoho.com; s=zohoarc; b=MdawVCtrLBbGVbGmveXrl7iP2JwASjoTkPZ+/8Sf8T4RDSdw5xroG9up4OrRI5qOWXZEg8J1NTnZ1ia9cSHkmf/vC81Pr3TcLOejgivpjyHWrB9DLjUue3zvoEpA2nQVaZJrfO21z3Xs8DFzDVYnBvXKgOty+a2NuptDKVF4bkA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1557908880; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=LNVdxyKR7bk6HeKFSlPBDEDuFHvNCKJItUg4TCHVy2A=; b=NEUqAef7qTGFTgThhY+XBiLIAaI0vckCD3bzJBuU85nTq9DUyPiy/2ecHBj7tV7a0mj2YB7BKNNXf2LgUwPAAVisYCHVwHXfCg0N6V8/t4ohrEjgUi0Xlu1PxQGHkYIpLnmaEx70DVked5Bir1ARuuzZddP9KWpnAxfW95/AJFE= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40656+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1557908880708608.2145365118571; Wed, 15 May 2019 01:28:00 -0700 (PDT) Return-Path: X-Received: from mga17.intel.com (mga17.intel.com []) by groups.io with SMTP; Wed, 15 May 2019 01:27:59 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 May 2019 01:27:59 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by orsmga005.jf.intel.com with ESMTP; 15 May 2019 01:27:58 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , Ray Ni , David Woodhouse , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v1 8/9] OvmfPkg/Csm/LegacyBootManagerLib: Update to make it build for OVMF Date: Wed, 15 May 2019 16:27:19 +0800 Message-Id: <20190515082720.12560-9-hao.a.wu@intel.com> In-Reply-To: <20190515082720.12560-1-hao.a.wu@intel.com> References: <20190515082720.12560-1-hao.a.wu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,hao.a.wu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1557908880; bh=1tMIYHYDlIhKLKxUnAWddywtbNYPm0yDJ+0xMTBgmtM=; h=Cc:Date:From:Reply-To:Subject:To; b=ChqfIDnmBm1HOu0iZcmF/gOQYpfnjDWS+HTjWr1fYeiOwRh8q8mqm8wP6zALlHIayHz TgO5bjGCgwZCGmU3YrfXkVDSBo1D+XXKYnTDvpQNQI6VyWAK+v8krGq4LnjPA5B2kP2wK E/BmYkWTnQfbQC/cUY8wgNJvs29RgTCJF1k= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1811 This commit will update the library's INF file to: A) Assign a new file GUID; B) Remove the IntelFramework[Module]Pkg DEC file dependency. Please note that a subsequent commit (final patch of the series) will: Replace the use of LegacyBootManagerLib in IntelFrameworkModulePkg with the one copied in OvmfPkg within DSC files. Cc: Ray Ni Cc: David Woodhouse Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu --- OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf b/Ov= mfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf index eaf7b7235d..e43351cf95 100644 --- a/OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf +++ b/OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf @@ -1,7 +1,7 @@ ## @file # Legacy Boot Manager module is library for BDS phase. # -# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## @@ -10,7 +10,7 @@ INF_VERSION =3D 0x00010005 BASE_NAME =3D LegacyBootManagerLib MODULE_UNI_FILE =3D LegacyBootManagerLib.uni - FILE_GUID =3D F1B87BE4-0ACC-409A-A52B-7BFFABCC96A0 + FILE_GUID =3D D1BBB810-6A9E-40E0-87CB-65EAD2AA2A09 MODULE_TYPE =3D DXE_DRIVER VERSION_STRING =3D 1.0 LIBRARY_CLASS =3D NULL|DXE_DRIVER UEFI_APPLICATION @@ -29,8 +29,7 @@ [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + OvmfPkg/OvmfPkg.dec =20 [LibraryClasses] BaseLib --=20 2.12.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#40656): https://edk2.groups.io/g/devel/message/40656 Mute This Topic: https://groups.io/mt/31627728/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 20:18:32 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+40657+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40657+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1557908883; cv=none; d=zoho.com; s=zohoarc; b=PNE4X8EruLfluvkBI6CQSh9uvFABK1wN9KtXDbXHhRJHf0w2tsKHaXCkbOUXt8dZT8tfNu++D/1vUgGze/XcQqRA1aYr1zrMGfzp5HQrIdwKQGYgeTtJaUibZMCP75lMNGVGf/ORvMh2PbWTRx14dfbM4mDIk8N4E9qf8ETX+yw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1557908883; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=cuX7SNFHBKolfZOmdYp8QWGJ/H+CIPL/HvFfnVZSNIE=; b=b5VIDWz4YepKcctVylOpY1yeYn0dyHQFyzKmQuNtS9OC6YE8K0XpnHwTN1/6FQWNdDmQH2gK0Bad20cyEfA0frfmx1HRYmS1bGCi+qhuHOCbKzCwM1RQxij+WW0PXwLRvE9FEpxpn7lX2f+HVvF1O3Bb/Xw+h2VXhWaPrmFyjog= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+40657+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 155790888309038.57412584906524; Wed, 15 May 2019 01:28:03 -0700 (PDT) Return-Path: X-Received: from mga17.intel.com (mga17.intel.com []) by groups.io with SMTP; Wed, 15 May 2019 01:28:01 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 May 2019 01:28:01 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by orsmga005.jf.intel.com with ESMTP; 15 May 2019 01:27:59 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , Ray Ni , David Woodhouse , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v1 9/9] OvmfPkg: Update DSC/FDF files to consume CSM components in OvmfPkg Date: Wed, 15 May 2019 16:27:20 +0800 Message-Id: <20190515082720.12560-10-hao.a.wu@intel.com> In-Reply-To: <20190515082720.12560-1-hao.a.wu@intel.com> References: <20190515082720.12560-1-hao.a.wu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,hao.a.wu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1557908882; bh=bwr2Y826IUtcDF8FAc1oibgzar84LbGSbCHHhNXvBFI=; h=Cc:Date:From:Reply-To:Subject:To; b=SaStgz2TrYcBzJYRk7O5+71DonXhaatdV39gTRAPg0rbtmrV0wVVj5tMl24nYCF6UiP GFK3+CuASI+rK+kgx1Ymwai8005U2pFfqATEVOsAF9nacQN6FDAnkJGZ0nKZwOEZ2+sNo /2gd3nglKfDD6EHxXfR+JiTlCzNfzFyZPDc= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1811 This commit updates the OVMF DSC/FDF files to consume the copied CSM components within OvmfPkg. Cc: Ray Ni Cc: David Woodhouse Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu --- OvmfPkg/OvmfPkgIa32.dsc | 10 +++++----- OvmfPkg/OvmfPkgIa32X64.dsc | 10 +++++----- OvmfPkg/OvmfPkgX64.dsc | 10 +++++----- OvmfPkg/OvmfPkgIa32.fdf | 4 ++-- OvmfPkg/OvmfPkgIa32X64.fdf | 4 ++-- OvmfPkg/OvmfPkgX64.fdf | 4 ++-- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index 36a0f87258..86109522e7 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -686,7 +686,7 @@ !ifdef $(CSM_ENABLE) NULL|OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.inf - NULL|IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBoot= ManagerLib.inf + NULL|OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf !endif } MdeModulePkg/Logo/LogoDxe.inf @@ -696,8 +696,8 @@ NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanc= eManagerUiLib.inf !ifdef $(CSM_ENABLE) - NULL|IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBoot= ManagerLib.inf - NULL|IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBoot= MaintUiLib.inf + NULL|OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf + NULL|OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf !endif } OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf @@ -825,11 +825,11 @@ MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf =20 !ifdef $(CSM_ENABLE) - IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf { + OvmfPkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf { PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf } - IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf + OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf OvmfPkg/Csm/Csm16/Csm16.inf !endif =20 diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 9b341e17d7..751425f994 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -695,7 +695,7 @@ !ifdef $(CSM_ENABLE) NULL|OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.inf - NULL|IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBoot= ManagerLib.inf + NULL|OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf !endif } MdeModulePkg/Logo/LogoDxe.inf @@ -705,8 +705,8 @@ NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanc= eManagerUiLib.inf !ifdef $(CSM_ENABLE) - NULL|IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBoot= ManagerLib.inf - NULL|IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBoot= MaintUiLib.inf + NULL|OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf + NULL|OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf !endif } OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf @@ -834,11 +834,11 @@ MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf =20 !ifdef $(CSM_ENABLE) - IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf { + OvmfPkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf { PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf } - IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf + OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf OvmfPkg/Csm/Csm16/Csm16.inf !endif =20 diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index a0f87f74da..9122e2f6c4 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -693,7 +693,7 @@ !ifdef $(CSM_ENABLE) NULL|OvmfPkg/Csm/CsmSupportLib/CsmSupportLib.inf - NULL|IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBoot= ManagerLib.inf + NULL|OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf !endif } MdeModulePkg/Logo/LogoDxe.inf @@ -703,8 +703,8 @@ NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanc= eManagerUiLib.inf !ifdef $(CSM_ENABLE) - NULL|IntelFrameworkModulePkg/Library/LegacyBootManagerLib/LegacyBoot= ManagerLib.inf - NULL|IntelFrameworkModulePkg/Library/LegacyBootMaintUiLib/LegacyBoot= MaintUiLib.inf + NULL|OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf + NULL|OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf !endif } OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf @@ -832,11 +832,11 @@ MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf =20 !ifdef $(CSM_ENABLE) - IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf { + OvmfPkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf { PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf } - IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf + OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf OvmfPkg/Csm/Csm16/Csm16.inf !endif =20 diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf index bc08bf2243..bfa83e7041 100644 --- a/OvmfPkg/OvmfPkgIa32.fdf +++ b/OvmfPkg/OvmfPkgIa32.fdf @@ -338,8 +338,8 @@ INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf =20 !ifdef $(CSM_ENABLE) -INF IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf -INF IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf +INF OvmfPkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf +INF OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf INF RuleOverride=3DCSM OvmfPkg/Csm/Csm16/Csm16.inf !endif =20 diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf index ccf36c5dd9..4d3296036f 100644 --- a/OvmfPkg/OvmfPkgIa32X64.fdf +++ b/OvmfPkg/OvmfPkgIa32X64.fdf @@ -344,8 +344,8 @@ INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf =20 !ifdef $(CSM_ENABLE) -INF IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf -INF IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf +INF OvmfPkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf +INF OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf INF RuleOverride=3DCSM OvmfPkg/Csm/Csm16/Csm16.inf !endif =20 diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index ccf36c5dd9..4d3296036f 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -344,8 +344,8 @@ INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf =20 !ifdef $(CSM_ENABLE) -INF IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf -INF IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf +INF OvmfPkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf +INF OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf INF RuleOverride=3DCSM OvmfPkg/Csm/Csm16/Csm16.inf !endif =20 --=20 2.12.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#40657): https://edk2.groups.io/g/devel/message/40657 Mute This Topic: https://groups.io/mt/31627729/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-