From nobody Sat May 18 23:23:42 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+41386+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+41386+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1558926238; cv=none; d=zoho.com; s=zohoarc; b=OY8CvG+0WMm24VmjwrzDsAsWU8wZXKONqgYv/WcZ/kBjS5lWD+VviwvUyxD2+AeuH/nHktK79ugOjnCboHyYVXH1WGW3/L6592ngrs4vHTJP8w4zIDDUARdnrzAdHQcxNhyZpjt0US4lAS9Nkik6yMhdX4b3Fk/DmBv56M/9H0s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558926238; 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=AuLPSkcJ1EonmPyKAAmGGMwwijdhaLCeN2Bc2IXEIwQ=; b=gNwUPPzyEypWe92ShQnC8g3PLbSw0VwQvaYxYvQoqWpswItpVTnd1w/PBtsY9mIfnZ2eU8IYJs8q63/HzVNIR8pUp/neNYzBpnOZOL3ETPrEqDWMadugjk5LGtnCkc0ydOOcCAS72spWtGixeB025QgdEJAQuwZ252GG1MMFYVY= 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+41386+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 1558926238136941.6888202593647; Sun, 26 May 2019 20:03:58 -0700 (PDT) Return-Path: X-Received: from mga04.intel.com (mga04.intel.com []) by groups.io with SMTP; Sun, 26 May 2019 20:03:57 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 May 2019 20:03:57 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by fmsmga007.fm.intel.com with ESMTP; 26 May 2019 20:03:55 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , David Woodhouse , Ray Ni , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 01/10] Maintainers.txt: Add maintainer for CSM components in OvmfPkg Date: Mon, 27 May 2019 11:03:41 +0800 Message-Id: <20190527030350.11996-2-hao.a.wu@intel.com> In-Reply-To: <20190527030350.11996-1-hao.a.wu@intel.com> References: <20190527030350.11996-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=1558926237; bh=kHgElGV8642SeCiQJ5Wt05AGDHxTx5KbXLeD295ZXa8=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=NuXi6aQkDDonRGdp0XPAXZNXMyUL6ZGHs1zKfIhksX5yUHOYfPJI2ukzVuSWyd3k2ra 6QsHJOvs74A3QBzNb68KI1lsnp7KQDOUTJzxz2p7W8u68efk27hyjFl+48RLHZM+QPD9G 3eQwZTDuTMyS+DI9XIS1FxHsxqXs/g2xsQo= X-ZohoMail-DKIM: pass (identity @groups.io) According to the discussion at: https://edk2.groups.io/g/devel/topic/31627718#40659 (Request by Laszlo to find proper maintainer for to-be-duplicated CSM components in OvmfPkg.) and: https://edk2.groups.io/g/devel/topic/31682287#40996 (Confirmation with David Woodhouse as the maintainer for the to-be-duplicated CSM components in OvmfPkg.) This commit will add David Woodhouse as the maintainer for the CSM modules under OvmfPkg. Please note that the duplication of the required CSM modules from framework packages to OvmfPkg will be done in subsequent commits. Cc: David Woodhouse Cc: Ray Ni Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu Reviewed-by: David Woodhouse Reviewed-by: Laszlo Ersek --- Maintainers.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Maintainers.txt b/Maintainers.txt index aaabe2b52d..3b8449dd66 100644 --- a/Maintainers.txt +++ b/Maintainers.txt @@ -198,6 +198,8 @@ R: Marc-Andr=C3=A9 Lureau (TPM2 modules) R: Stefan Berger (TPM2 modules) +R: David Woodhouse + (CSM modules) S: Maintained =20 PcAtChipsetPkg --=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 (#41386): https://edk2.groups.io/g/devel/message/41386 Mute This Topic: https://groups.io/mt/31805476/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 Sat May 18 23:23:42 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+41387+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+41387+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1558926258; cv=none; d=zoho.com; s=zohoarc; b=ATIehWK0Fw6MhaCVKgXpuXudSExH776iD79RbjtD14oJtrEaMXt3DXvZqUaOnLDw3NkysLe2PiMM6UX8wOxNKqYrVRd3KIt2diZcwy6YBE5EITliniuRfaHQ7OfD+b/lg6pkfG/Onwx83SRd/g44xeVwGHnpo09mbhClXSYfH2Q= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558926258; 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=zg7c8OgQMOrGh1NB2BqBS3f8QgRYx3eoQ8YG4VmABGo=; b=ZUzhDG9RO1ObEd1iLZIzqY6mq4LD0UAJCHugoOOFa61Oe2EsO3MU+AJbbMbmNgWksFbnemWOsaPeJmAFtxlEvo8yS05/5cOYaYD09O50pIajCthjPicLBivEsm2F+1fgGhkAa751HhnSEbhbo3hd6tg0lB8VYVy9A8LB/2B9+7I= 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+41387+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 155892625814670.74584401029881; Sun, 26 May 2019 20:04:18 -0700 (PDT) Return-Path: X-Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by groups.io with SMTP; Sun, 26 May 2019 20:04:15 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 May 2019 20:04:14 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by fmsmga007.fm.intel.com with ESMTP; 26 May 2019 20:03:57 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , David Woodhouse , Ray Ni , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 02/10] OvmfPkg: Copy the required CSM components from framework packages Date: Mon, 27 May 2019 11:03:42 +0800 Message-Id: <20190527030350.11996-3-hao.a.wu@intel.com> In-Reply-To: <20190527030350.11996-1-hao.a.wu@intel.com> References: <20190527030350.11996-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=1558926257; bh=gp8oRvaUAPzn3EE49PBD2SLALTXLr/iyJDO8NBVaAvM=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=RyEtqYTVhd+kmYJblLnzzHG1ZA48W79UKO/DjUNWQt3YLHbrvEeHlLIKL7wcjHWNppT LCpkSKoxWFyu6ymH++xEELCpzOYFd9dgaFgqb7r1llLBQmQ2W5go3M+/kxvX4ZvlmJgNj HikCA+1W+x+3QtW3LO7oCEqC6/0/wyIAySo= 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: David Woodhouse Cc: Ray Ni Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu Reviewed-by: David Woodhouse --- 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 (#41387): https://edk2.groups.io/g/devel/message/41387 Mute This Topic: https://groups.io/mt/31805480/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 Sat May 18 23:23:42 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+41388+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+41388+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1558926258; cv=none; d=zoho.com; s=zohoarc; b=hypn6oQF2qpHWWjPTeeQxnuwINLGGAi2liB7JIe681fSWmvPfTpR/xr5yPn9zRNacUxMaL69WRqL0K0iwQgHrcXD+4SIBR0Xu//RIE7Lc1fK6damoO3j8NVxUSyAbI5iCvFHaNfswg1lfWdfsoTODB2OWHiC3nxO1qqrowJWDFI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558926258; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=TmYDJClEQ8s6106QM8lPsjOlT+VMDmM4VyDzCj9rIMk=; b=Yk5+q+DCP3zQuOQoTdnbQLaR+2kYeWFcLoq/y5pIK0U/dUNAHKW2XL4b6iwQc1xqLOQA8IFPmkY8dE6O2XtzI3DWHTgW3PTt/VJ9Gccv6esUXJfQx58kN0jHMBcAlXif4wKHh6UOU9jQ9zqsWwuPI7zhlJuk3fBUboGCPlnoVUw= 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+41388+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 1558926258492426.6925685645738; Sun, 26 May 2019 20:04:18 -0700 (PDT) Return-Path: X-Received: from mga02.intel.com (mga02.intel.com []) by groups.io with SMTP; Sun, 26 May 2019 20:04:16 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 May 2019 20:04:15 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by fmsmga007.fm.intel.com with ESMTP; 26 May 2019 20:04:13 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , David Woodhouse , Ray Ni , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 03/10] OvmfPkg/OvmfPkg.dec: Add definitions for CSM-related Guid & Protocol Date: Mon, 27 May 2019 11:03:43 +0800 Message-Id: <20190527030350.11996-4-hao.a.wu@intel.com> In-Reply-To: <20190527030350.11996-1-hao.a.wu@intel.com> References: <20190527030350.11996-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=1558926258; bh=4Wa2gU/yoM5dN5Rsg845hrWEAMBzZ+RBzymVvD0FK3I=; h=Cc:Date:From:Reply-To:Subject:To; b=hIo4zNUV8l4xR+Jmm9Mql7fij2LJe2Kt9CFoIXq1vg0EeQvOj/biRn+UEKPZXuA5pel /3pDWQJfcEoC1SD2Tf+7GKKYUxnpXVYNtVvLGze/djnJvS0by1VrUsJ+3WSBhHwgVdzXb hJR5NsK1kzjNZfJODtW16AGFE3NaJAR9OBA= 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: David Woodhouse Cc: Ray Ni Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu Reviewed-by: David Woodhouse --- 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 @@ [Guids] 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 @@ [Protocols] 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 (#41388): https://edk2.groups.io/g/devel/message/41388 Mute This Topic: https://groups.io/mt/31805481/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 Sat May 18 23:23:42 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+41389+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+41389+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1558926258; cv=none; d=zoho.com; s=zohoarc; b=ZgxlDvAl7zKmXOJ1LtVwwAuMEABHSURojgpUxlamQYuBhJ4b0xy4hSzGZQyjLjGnkyDztdRpGaPqpalEJqsqFH81tDoNNsMM33WfqAdHBbx0K4+ldZKljUjEKO7ysiAJtYRanhsaf91rB678tHHF6wXQu8i16pr0aj3DSMeMUc4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558926258; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=D9dAkGhPEnSoBLSUf/ZbWC5b+T0ZA7BpkKsZPQwF8A8=; b=NC3zxqLfge+yiJ4sqdfanbT1V5eBBvV3F4vOzHoTCCBhjkR3AAGNbMZMKzVd+zat8M0KEhElq+SApm1Qm6kAPvmN51rYEDWeaGU9bnzK5+PWDARKrU0oD0OC5o9VwrB80S4E6sRPEBVR9j8zYXc4OOLK0zgrWJAifaN/bf8TO+4= 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+41389+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 1558926258653906.0018627543227; Sun, 26 May 2019 20:04:18 -0700 (PDT) Return-Path: X-Received: from mga02.intel.com (mga02.intel.com []) by groups.io with SMTP; Sun, 26 May 2019 20:04:17 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 May 2019 20:04:17 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by fmsmga007.fm.intel.com with ESMTP; 26 May 2019 20:04:15 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , David Woodhouse , Ray Ni , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 04/10] OvmfPkg/OvmfPkg.dec: Add the new include folder for CSM header files Date: Mon, 27 May 2019 11:03:44 +0800 Message-Id: <20190527030350.11996-5-hao.a.wu@intel.com> In-Reply-To: <20190527030350.11996-1-hao.a.wu@intel.com> References: <20190527030350.11996-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=1558926258; bh=Tnd9gHYcNFnT55QiAvDaAJffKAiKucqYvbGU/+N0zbs=; h=Cc:Date:From:Reply-To:Subject:To; b=vqkHnjKiNTczvE32+C2O/1/aDK+Ncd7KBbXtcBM8HUaSTiUjOrzDVIO6U+oFgbr3Eoe GSCtoHnl0woSLN1nWhwkOJRv1xyH0zPlzC3GYUjmPhU9icoWoyovNaTNvTFQdRsb7TBtH gm6M3AcFkLdZofnb6jd8d2TmGhDpyyNxOIM= 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: David Woodhouse Cc: Ray Ni Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu Reviewed-by: David Woodhouse --- 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 @@ [Defines] =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 (#41389): https://edk2.groups.io/g/devel/message/41389 Mute This Topic: https://groups.io/mt/31805482/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 Sat May 18 23:23:42 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+41390+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+41390+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1558926262; cv=none; d=zoho.com; s=zohoarc; b=Bks18NXMevhzvTrH9+6kk7z3Ow/9qK0eOGQS+kXHsHR82U4b7m57sfifBPpAzu+eh9TDQ0Cj+H5ZGDY4TuNvMSuZfREm4TTGE87mWwNMtLYUvaN1k2t232rMpSYg7QPzMVbMRGH7Nr1Rxui2wCzPm25CuDa03FHmcLwcifI//5g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558926262; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=dzAFeXYpmOGq7HQHCHQC776Hu4gwHQA9oDJwyuE0wls=; b=QVWMEr2ekp9x69x2wxw9zpYw3vMvfDYGb6KHwJH6vIiUTu6C/uRIrYfu3W/8QXrIyOOa6obKI5nKSgH1P259xmGKccjAmfovH71ne38aMZG3Li3SsRxhPfEw3NqUnVbixGSBlvZVUuXAffM45Am1HVC0700RA193E7BcEbUr8Dg= 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+41390+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 1558926262976533.7950683282526; Sun, 26 May 2019 20:04:22 -0700 (PDT) Return-Path: X-Received: from mga02.intel.com (mga02.intel.com []) by groups.io with SMTP; Sun, 26 May 2019 20:04:19 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 May 2019 20:04:18 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by fmsmga007.fm.intel.com with ESMTP; 26 May 2019 20:04:17 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , David Woodhouse , Ray Ni , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 05/10] OvmfPkg/OvmfPkg.dec: Add PCD definitions used by copied CSM modules Date: Mon, 27 May 2019 11:03:45 +0800 Message-Id: <20190527030350.11996-6-hao.a.wu@intel.com> In-Reply-To: <20190527030350.11996-1-hao.a.wu@intel.com> References: <20190527030350.11996-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=1558926262; bh=KWj05aXCq+kmqaYOxwKWSEQLLvXD2oQY4cX3JI3KtGY=; h=Cc:Date:From:Reply-To:Subject:To; b=lFqaotmsIhUVSaaY27lSak9rVUy/3ByuHiUhYgdjwyONGW7Dj7aOGK53UgOwY60KQmr taKLIg1nG7Bs3t/+vTUulPF8ZzyiTxr7eTAdBUljwEdyE1+MpJWfC1tZoApdAfGRivfhL y4FWCaMt47a2u15wEiCP1Oe/MLXc4ktnvGc= 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: David Woodhouse Cc: Ray Ni Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu Reviewed-by: David Woodhouse --- 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 @@ [PcdsFixedAtBuild] # 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 (#41390): https://edk2.groups.io/g/devel/message/41390 Mute This Topic: https://groups.io/mt/31805484/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 Sat May 18 23:23:42 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+41391+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+41391+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1558926263; cv=none; d=zoho.com; s=zohoarc; b=oLM1rCL2cyC+WxbUj9JpB3ATRBtmtcUX21+WM8VsG3uDa53kg35qr0keqLfdye1gM+Ok0pLiGXiWsIEJJeHs20kLdMBxzhiQwWmnE90sHwnyQOljP5CkRddY6Eh5xd2OZ5cP262Qp+QqYjJXlV7IKgG//8bdFhDBmCvkikNsZ+c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558926263; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=U395AWziRxmysz0QCakBTllj5TqjY3ZqSaONlxIkunA=; b=R5uRtLdWDTc8MSrQhr3LGh2AVULXbnOL/0kZ11Af+L2X823P7lti0Om7Ps2DzR0s2x/zS4K6K4XoSS1KpI1Bi44cu/cTmZ0dyaT2xoBFUQCi7Po+omsxNvI2b1gLq/CJnk5cUwv0FtZ+pzrDRKbtRNl4AOuYffxd0WmG+a8xo9o= 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+41391+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 155892626306435.64932328292764; Sun, 26 May 2019 20:04:23 -0700 (PDT) Return-Path: X-Received: from mga02.intel.com (mga02.intel.com []) by groups.io with SMTP; Sun, 26 May 2019 20:04:21 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 May 2019 20:04:20 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by fmsmga007.fm.intel.com with ESMTP; 26 May 2019 20:04:18 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , David Woodhouse , Ray Ni , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 06/10] OvmfPkg/Csm/VideoDxe: Update to make it build for OVMF Date: Mon, 27 May 2019 11:03:46 +0800 Message-Id: <20190527030350.11996-7-hao.a.wu@intel.com> In-Reply-To: <20190527030350.11996-1-hao.a.wu@intel.com> References: <20190527030350.11996-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=1558926262; bh=kLKCqXvPEnTcvf8dDPU7MNrFkoZTcp2aA6tqO0Ea+ZI=; h=Cc:Date:From:Reply-To:Subject:To; b=q/pyf3tSmP1tQSYGDZlRiuWD8n6ex78JuVJyfKpARQi/IpKutJnJ35QI3m86ShGaXow 9krnqyp0Hrp4bl2XDtE3kPQF53+st0REpJ1wDe+auAVC2LND5dCDH5ICthhb4PUaKTSJ7 UWmh8U63pQcIghuQ8KojU0J+cbKD73o83JY= 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: David Woodhouse Cc: Ray Ni Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu Reviewed-by: David Woodhouse --- 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 @@ [Defines] 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 @@ [Sources] [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - + OvmfPkg/OvmfPkg.dec =20 [LibraryClasses] MemoryAllocationLib @@ -70,9 +68,9 @@ [Protocols] 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 (#41391): https://edk2.groups.io/g/devel/message/41391 Mute This Topic: https://groups.io/mt/31805485/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 Sat May 18 23:23:42 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+41392+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+41392+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1558926263; cv=none; d=zoho.com; s=zohoarc; b=KQcKjlBs9k2cBV2aesUiHhNN3wbrzU2eCKYsqAkZOna3UXN8acFLCzUXCnlfN0OCu6MpUFmI/86MgQrMNGqso78K3bSCKrc1gVJS729i0LvbZ3lpyY58jqm55Ix/qjqnOL1AariY00WLSsCZY+liBYQ1GNvWHqar6OztWRtDqDU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558926263; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=FHLismkSX51s5aemPPoH6Ikfv3HNz2CWw+AlXEzLdVI=; b=okqAPwB6K9UW+cT/VD3TDPn+RyTcNWQtXqrbB23rkI9fUNId4lnzq/4nth87u0e9y3VRCGHOWds+ZYpO2W9HcRFhjovK9AbeeFpa4wKgVUdYRIkJOim4B1iHIMLLAbOlqswyf+yWU0h1Y4S8zxXhpAWwXfSga8fzcvoMSgzhtNg= 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+41392+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 1558926263662837.1419712816958; Sun, 26 May 2019 20:04:23 -0700 (PDT) Return-Path: X-Received: from mga02.intel.com (mga02.intel.com []) by groups.io with SMTP; Sun, 26 May 2019 20:04:22 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 May 2019 20:04:22 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by fmsmga007.fm.intel.com with ESMTP; 26 May 2019 20:04:20 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , David Woodhouse , Ray Ni , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 07/10] OvmfPkg/Csm/LegacyBiosDxe: Update to make it build for OVMF Date: Mon, 27 May 2019 11:03:47 +0800 Message-Id: <20190527030350.11996-8-hao.a.wu@intel.com> In-Reply-To: <20190527030350.11996-1-hao.a.wu@intel.com> References: <20190527030350.11996-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=1558926263; bh=Agup6YQ51AowTay4DJcNB2EqwObHc1WoiHvf4xqKiPs=; h=Cc:Date:From:Reply-To:Subject:To; b=RR3Pb3DrO0YTYVrotKe+17PYybHg1HMjtjkl3iqquqAFCeHHHQsdNsxGyL5XiJG8hCK 4p4tUH2h9JZ7ZUY15cr+ZhlAu3/dwR6TxEAJ7ufcP4BcUQdLAQ702D7UzB5H+L2cvRrBb VXRFSPCwIQ4esh68HzhenJ31Vi9V8bWC1bg= 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: David Woodhouse Cc: Ray Ni Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu Reviewed-by: David Woodhouse --- 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 @@ [Defines] 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 @@ [Sources.X64] [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec - IntelFrameworkPkg/IntelFrameworkPkg.dec - IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec - + OvmfPkg/OvmfPkg.dec =20 [LibraryClasses] DevicePathLib @@ -116,13 +114,13 @@ [Protocols] 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 (#41392): https://edk2.groups.io/g/devel/message/41392 Mute This Topic: https://groups.io/mt/31805486/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 Sat May 18 23:23:42 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+41393+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+41393+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1558926265; cv=none; d=zoho.com; s=zohoarc; b=JPRrS/jjcUKWQlAwlC2B6GQOrOJbI5ED6d6EWcQ5y7XYnzBsOSn9pSfgN2YB1OcO83Ks11sGrqvdVthsuBCoqZ/jMq5HS8iAGxHzCJn6XlptzM017DuY5czasRTWlrFV1W7aF7ShTZSDFRb9Rgk/3XnltnLS4IKya/FZNPwZC+4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558926265; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=y8XdNS5eC6hUCFSUPJpfZ90EUMbaklDEddqy8oBNpn8=; b=AwydrpfQr31DLHptsf8md4iX4VvhQUcg/BjqjMqdCDM1Lyn0QYfacRSisJn/0BtajhnCRkKD1E5cw+ZlFL4Tb6G1w3wprhxol2jEjoSGGriz031ZqhWAN5rGQAYfL6YXgrXHVMkrBmgxtlniJOxo7Fmsfyt62ValEqRB4s5ltk8= 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+41393+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 155892626532281.89209359814583; Sun, 26 May 2019 20:04:25 -0700 (PDT) Return-Path: X-Received: from mga02.intel.com (mga02.intel.com []) by groups.io with SMTP; Sun, 26 May 2019 20:04:24 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 May 2019 20:04:24 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by fmsmga007.fm.intel.com with ESMTP; 26 May 2019 20:04:22 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , David Woodhouse , Ray Ni , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 08/10] OvmfPkg/Csm/LegacyBootMaintUiLib: Update to make it build for OVMF Date: Mon, 27 May 2019 11:03:48 +0800 Message-Id: <20190527030350.11996-9-hao.a.wu@intel.com> In-Reply-To: <20190527030350.11996-1-hao.a.wu@intel.com> References: <20190527030350.11996-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=1558926264; bh=uXgBzlm8QPsNfrL1jJtS2Go92QTa9pnC+eA3nKdNcYA=; h=Cc:Date:From:Reply-To:Subject:To; b=TG/d1q4uZUBH7IjlJ6P0UhM/uugKEJhIRoPDXnC0WJl8s+/tJuIfk//LFjrAHh8M1zY i8+8s5IswDquX+AIL2zRS2VfkTMttnPRM9XzqV0lxSUtlUXB2q6+OhVXqPYERUxPXeCmx ysmb39UhqjUyALAqFAIrAUq7eD4xXsK0eJQ= 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: David Woodhouse Cc: Ray Ni Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu Reviewed-by: David Woodhouse --- 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 @@ [Defines] 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 @@ [Sources] [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 (#41393): https://edk2.groups.io/g/devel/message/41393 Mute This Topic: https://groups.io/mt/31805487/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 Sat May 18 23:23:42 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+41394+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+41394+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1558926266; cv=none; d=zoho.com; s=zohoarc; b=hlC0S3xJGNb+149i/JmIy0hW9GZfIQGNm9UbuSRxpYCP1FbGqLJISkQWn9X/hv57Zi520C26FRMOPEp6CW5LgGamDVqqXlBHv+UJriDtAc8Tvu7ZdACEyugi965iBeCC106Ha0+1pBt7Cgpgg7TpDvYh5ehbb5OCI+F1I8FVCKA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558926266; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=1thw2JXvl0Ra5MoHUxMHFEy7Jndquekncuk3rpOfxNA=; b=My6XtRXkR/EjP+5e2Rq+OeWM5WjPZ4P+XuQ4aPj1dsI/ZM71rUw7L4OTRYKv7xp33w1gwdmir9QiPsQcTDZs/1Gq1WulSji/C7BTzRrW+ZB4q7PCzRVbNi9TadYaXWEqQyLgumExC2tbYcNiA18XoxFbCkegR+XR74GjMlVphRA= 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+41394+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 1558926266885434.009031215984; Sun, 26 May 2019 20:04:26 -0700 (PDT) Return-Path: X-Received: from mga02.intel.com (mga02.intel.com []) by groups.io with SMTP; Sun, 26 May 2019 20:04:26 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 May 2019 20:04:25 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by fmsmga007.fm.intel.com with ESMTP; 26 May 2019 20:04:24 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , David Woodhouse , Ray Ni , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 09/10] OvmfPkg/Csm/LegacyBootManagerLib: Update to make it build for OVMF Date: Mon, 27 May 2019 11:03:49 +0800 Message-Id: <20190527030350.11996-10-hao.a.wu@intel.com> In-Reply-To: <20190527030350.11996-1-hao.a.wu@intel.com> References: <20190527030350.11996-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=1558926266; bh=GzyUIIpCAtGOpwHsFrcqvLctdtOSa2OrRBgZDMyJJMw=; h=Cc:Date:From:Reply-To:Subject:To; b=d50hSj/5DzjXQ+CgyoPDCkLFteDtLyMG1O82gWDoab0AG1K3ORJxUjGBQRlzkDgCfjJ srhn0HkqhLQO1rqoSq8IsJ2aqWK+g9Bz0DLXpHEchOojzp9tvhyvlAKAs21To7/dPe2wG HaZlcu4RK5TVndTU3s7KhtVyK/tmhBifGyQ= 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: David Woodhouse Cc: Ray Ni Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu Reviewed-by: David Woodhouse --- 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 @@ [Defines] 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 @@ [Sources] [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 (#41394): https://edk2.groups.io/g/devel/message/41394 Mute This Topic: https://groups.io/mt/31805488/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 Sat May 18 23:23:42 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+41395+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+41395+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1558926268; cv=none; d=zoho.com; s=zohoarc; b=K24JGXooTTqDI0XUvgZWN/M0BqQ0za6zLO6+UUeKfH86q9IR3rtShCGSLG13OBGKYTkmMl/5nEBE4dF6BgslI2l3VrKepn+q8Rc5MfJVR/IreVa3Se8jMKvcvP7ECWDz0vZ735/N89kt9OugGSG5wY0TpR5ts2nDwsjQv5kXIOQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1558926268; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=bK/0Gl7FpB9CryDj7VjQu3YPiFCvWjevM2k5p5bAxOY=; b=NUWz7JCZGUOZ9HvV6dN02E13cGlqNapLi8c3WGIKnKBD7og6z3H8v53Kag2IlsL08bQWUmGOdne9TcfC21DB34ghYfjR/TBvzmsIiI8P70+OjFML35TAAFktQ5ga44rD+AwaCIg+EdK6KHqaByaLnLgkr+40q6lzXN63HG6mUK0= 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+41395+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 1558926268388683.1153201657726; Sun, 26 May 2019 20:04:28 -0700 (PDT) Return-Path: X-Received: from mga02.intel.com (mga02.intel.com []) by groups.io with SMTP; Sun, 26 May 2019 20:04:27 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 May 2019 20:04:27 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.8]) by fmsmga007.fm.intel.com with ESMTP; 26 May 2019 20:04:25 -0700 From: "Wu, Hao A" To: devel@edk2.groups.io Cc: Hao A Wu , David Woodhouse , Ray Ni , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 10/10] OvmfPkg: Update DSC/FDF files to consume CSM components in OvmfPkg Date: Mon, 27 May 2019 11:03:50 +0800 Message-Id: <20190527030350.11996-11-hao.a.wu@intel.com> In-Reply-To: <20190527030350.11996-1-hao.a.wu@intel.com> References: <20190527030350.11996-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=1558926267; bh=1DcDmEuMho2gZ+68j2lY+tdeDTA3ZoY0i9Y0IAbBWuo=; h=Cc:Date:From:Reply-To:Subject:To; b=JFdnVLAtnXR+sD5jFSBrrwlp5AfQ3iSppsiqn+HwRa9cqvkL3UqBkUTmoFsrnUL5oTO VwlHRYAd8wFAs6ZDnWcbdz6XSq1lMAkIMiFQ0ISuwm/zTPT3nfaIK54H+tZJcuVv1bobA hQiy2tGPL14UjFE+QhC8CzDUd+46o0OqSOg= 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: David Woodhouse Cc: Ray Ni Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Signed-off-by: Hao A Wu Reviewed-by: David Woodhouse --- 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 b3446ece31..94d8af6b8a 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -683,7 +683,7 @@ [Components] !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 @@ -693,8 +693,8 @@ [Components] 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 @@ -799,11 +799,11 @@ [Components] 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 679d4eb8dd..5d9c688e8b 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -692,7 +692,7 @@ [Components.X64] !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 @@ -702,8 +702,8 @@ [Components.X64] 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 @@ -808,11 +808,11 @@ [Components.X64] 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 56a9560262..3a9d25ba4a 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -690,7 +690,7 @@ [Components] !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 @@ -700,8 +700,8 @@ [Components] 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 @@ -806,11 +806,11 @@ [Components] 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 e428334702..c334a5bcd1 100644 --- a/OvmfPkg/OvmfPkgIa32.fdf +++ b/OvmfPkg/OvmfPkgIa32.fdf @@ -311,8 +311,8 @@ [FV.DXEFV] 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 6ddffe7547..89c2b44b48 100644 --- a/OvmfPkg/OvmfPkgIa32X64.fdf +++ b/OvmfPkg/OvmfPkgIa32X64.fdf @@ -317,8 +317,8 @@ [FV.DXEFV] 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 6ddffe7547..89c2b44b48 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -317,8 +317,8 @@ [FV.DXEFV] 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 (#41395): https://edk2.groups.io/g/devel/message/41395 Mute This Topic: https://groups.io/mt/31805489/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 Sat May 18 23:23:42 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+42317+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+42317+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1560375785; cv=none; d=zoho.com; s=zohoarc; b=jBOe6r8yAYsYNGweoDOuGhW6DS2Ke9Nix0H7pcLEpIiRiarq5Nat+XnCPPFI+xBY/QmrRyfZS/imwAMQRp8fCKb/BTOLz4ZSILTHFDUijlW1K2Hhml0hkdHGpNe3Qe0cysPNWo58XrJP+1WMi5QuXUZxiR7GV4pT1PKeJRf26yw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1560375785; h=Content-Type:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=JjQWDsCbDodv+aDbjpTRLxQFVruhgR16R+YHwyKFIXQ=; b=bGpQlfeO3AVcMv2t7sKvPzPJkc4ba1trK6LlaplQNuvdK3r2ktIEP5hAkK2wKXkOwn/qrJMojKzO2//YFlOafzojMMp1oMg3rOiCoTtMee8/igNYnHgWkAIRZS19jQIogbFQzFgO7BqhqjqUi0OkiLDmFMe0Lg4IEHwowzcBLWk= 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+42317+1787277+3901457@groups.io Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 156037578544861.68560707720974; Wed, 12 Jun 2019 14:43:05 -0700 (PDT) Return-Path: X-Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) by groups.io with SMTP; Wed, 12 Jun 2019 14:43:03 -0700 X-Received: from [54.239.6.185] (helo=u3832b3a9db3152.ant.amazon.com) by bombadil.infradead.org with esmtpsa (Exim 4.92 #3 (Red Hat Linux)) id 1hbB1K-000602-NJ; Wed, 12 Jun 2019 21:43:03 +0000 Message-ID: <18b24dae9f4e5c022849502fc4b60ac3ba59d6f1.camel@infradead.org> Subject: [edk2-devel] [PATCH 11/10] OvmfPkg/Csm/LegacyBiosDxe: Correct Legacy16GetTableAddress call for E820 data From: "David Woodhouse" To: Hao A Wu Cc: "devel@edk2.groups.io" , Ray Ni , Jordan Justen , Laszlo Ersek , Ard Biesheuvel Date: Wed, 12 Jun 2019 22:43:00 +0100 In-Reply-To: <20190527030350.11996-1-hao.a.wu@intel.com> References: <20190527030350.11996-1-hao.a.wu@intel.com> Mime-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html 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,dwmw2@infradead.org Content-Type: multipart/signed; micalg="sha-256"; protocol="application/x-pkcs7-signature"; boundary="=-EVu/9jE1bhWR3EsmM4yC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1560375785; bh=wFeZ4F9itFCzRism3jCTZTr+mEl+0wAcaD4wa5YYlg0=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=d5j+NhOrG7fUyLhr8zbxnIm3qFeaO7U4xu/PR1YhWyoYpZXVqdLSxZNytfBpsMK9YXe 9W2SEOUOlPmjL0w0MmV6dqkNGKZr+LmeV/F7Ac06Vz3pltpyHosUtddWpKSUmZtj/vM/S wPPloKuIIkFURuzKZfd041+tekKmS98FcGE= X-Zoho-Virus-Status: 1 X-ZohoMail-DKIM: pass (identity @groups.io) --=-EVu/9jE1bhWR3EsmM4yC Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The DX register is supposed to contain the required alignment for the allocation. It was zero, and SeaBIOS doesn't (well, didn't) cope well with that. Set it appropriately, and set BX to indicate the regions it's OK to allocate in too. That was already OK but let's make sure it's initialised properly and not just working by chance. Also actually return an error if the allocation fails. Instead of going all the way through into the CSM and just letting it have a bogus pointer to the E82o data. Signed-off-by: David Woodhouse Reviewed-by: David Woodhouse --- I made SeaBIOS cope with the zero too: https://mail.coreboot.org/hyperkitty/list/seabios@seabios.org/thread/4PHW3O= 3Y3HJFENODFV5INBGDLZMXA5KE/ OvmfPkg/Csm/LegacyBiosDxe/LegacyBootSupport.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OvmfPkg/Csm/LegacyBiosDxe/LegacyBootSupport.c b/OvmfPkg/Csm/LegacyBiosDxe/LegacyBootSupport.c index 211750c012..e7766eb2b1 100644 --- a/OvmfPkg/Csm/LegacyBiosDxe/LegacyBootSupport.c +++ b/OvmfPkg/Csm/LegacyBiosDxe/LegacyBootSupport.c @@ -928,7 +928,9 @@ GenericLegacyBoot ( if (CopySize > Private->Legacy16Table->E820Length) { ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); Regs.X.AX =3D Legacy16GetTableAddress; + Regs.X.BX =3D (UINT16) 0x3; // Region Regs.X.CX =3D (UINT16) CopySize; + Regs.X.DX =3D (UINT16) 0x4; // Alignment Private->LegacyBios.FarCall86 ( &Private->LegacyBios, Private->Legacy16Table->Compatibility16CallSegment, @@ -942,6 +944,7 @@ GenericLegacyBoot ( Private->Legacy16Table->E820Length =3D (UINT32) CopySize; if (Regs.X.AX !=3D 0) { DEBUG ((EFI_D_ERROR, "Legacy16 E820 length insufficient\n")); + return EFI_OUT_OF_RESOURCES; } else { CopyMem ( (VOID *)(UINTN) Private->Legacy16Table->E820Pointer, -=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 (#42317): https://edk2.groups.io/g/devel/message/42317 Mute This Topic: https://groups.io/mt/32045939/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- --=-EVu/9jE1bhWR3EsmM4yC Content-Type: application/x-pkcs7-signature; name="smime.p7s" Content-Disposition: attachment; filename="smime.p7s" Content-Transfer-Encoding: base64 MIAGCSqGSIb3DQEHAqCAMIACAQExDzANBglghkgBZQMEAgEFADCABgkqhkiG9w0BBwEAAKCCECow ggUcMIIEBKADAgECAhEA4rtJSHkq7AnpxKUY8ZlYZjANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UE BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxPTA7BgNVBAMTNENPTU9ETyBSU0EgQ2xpZW50IEF1dGhl bnRpY2F0aW9uIGFuZCBTZWN1cmUgRW1haWwgQ0EwHhcNMTkwMTAyMDAwMDAwWhcNMjIwMTAxMjM1 OTU5WjAkMSIwIAYJKoZIhvcNAQkBFhNkd213MkBpbmZyYWRlYWQub3JnMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEAsv3wObLTCbUA7GJqKj9vHGf+Fa+tpkO+ZRVve9EpNsMsfXhvFpb8 RgL8vD+L133wK6csYoDU7zKiAo92FMUWaY1Hy6HqvVr9oevfTV3xhB5rQO1RHJoAfkvhy+wpjo7Q cXuzkOpibq2YurVStHAiGqAOMGMXhcVGqPuGhcVcVzVUjsvEzAV9Po9K2rpZ52FE4rDkpDK1pBK+ uOAyOkgIg/cD8Kugav5tyapydeWMZRJQH1vMQ6OVT24CyAn2yXm2NgTQMS1mpzStP2ioPtTnszIQ Ih7ASVzhV6csHb8Yrkx8mgllOyrt9Y2kWRRJFm/FPRNEurOeNV6lnYAXOymVJwIDAQABo4IB0zCC Ac8wHwYDVR0jBBgwFoAUgq9sjPjF/pZhfOgfPStxSF7Ei8AwHQYDVR0OBBYEFLfuNf820LvaT4AK xrGK3EKx1DE7MA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUF BwMEBggrBgEFBQcDAjBGBgNVHSAEPzA9MDsGDCsGAQQBsjEBAgEDBTArMCkGCCsGAQUFBwIBFh1o dHRwczovL3NlY3VyZS5jb21vZG8ubmV0L0NQUzBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3Js LmNvbW9kb2NhLmNvbS9DT01PRE9SU0FDbGllbnRBdXRoZW50aWNhdGlvbmFuZFNlY3VyZUVtYWls Q0EuY3JsMIGLBggrBgEFBQcBAQR/MH0wVQYIKwYBBQUHMAKGSWh0dHA6Ly9jcnQuY29tb2RvY2Eu Y29tL0NPTU9ET1JTQUNsaWVudEF1dGhlbnRpY2F0aW9uYW5kU2VjdXJlRW1haWxDQS5jcnQwJAYI KwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTAeBgNVHREEFzAVgRNkd213MkBpbmZy YWRlYWQub3JnMA0GCSqGSIb3DQEBCwUAA4IBAQALbSykFusvvVkSIWttcEeifOGGKs7Wx2f5f45b nv2ghcxK5URjUvCnJhg+soxOMoQLG6+nbhzzb2rLTdRVGbvjZH0fOOzq0LShq0EXsqnJbbuwJhK+ PnBtqX5O23PMHutP1l88AtVN+Rb72oSvnD+dK6708JqqUx2MAFLMevrhJRXLjKb2Mm+/8XBpEw+B 7DisN4TMlLB/d55WnT9UPNHmQ+3KFL7QrTO8hYExkU849g58Dn3Nw3oCbMUgny81ocrLlB2Z5fFG Qu1AdNiBA+kg/UxzyJZpFbKfCITd5yX49bOriL692aMVDyqUvh8fP+T99PqorH4cIJP6OxSTdxKM MIIFHDCCBASgAwIBAgIRAOK7SUh5KuwJ6cSlGPGZWGYwDQYJKoZIhvcNAQELBQAwgZcxCzAJBgNV BAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAY BgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMT0wOwYDVQQDEzRDT01PRE8gUlNBIENsaWVudCBBdXRo ZW50aWNhdGlvbiBhbmQgU2VjdXJlIEVtYWlsIENBMB4XDTE5MDEwMjAwMDAwMFoXDTIyMDEwMTIz NTk1OVowJDEiMCAGCSqGSIb3DQEJARYTZHdtdzJAaW5mcmFkZWFkLm9yZzCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBALL98Dmy0wm1AOxiaio/bxxn/hWvraZDvmUVb3vRKTbDLH14bxaW /EYC/Lw/i9d98CunLGKA1O8yogKPdhTFFmmNR8uh6r1a/aHr301d8YQea0DtURyaAH5L4cvsKY6O 0HF7s5DqYm6tmLq1UrRwIhqgDjBjF4XFRqj7hoXFXFc1VI7LxMwFfT6PStq6WedhROKw5KQytaQS vrjgMjpICIP3A/CroGr+bcmqcnXljGUSUB9bzEOjlU9uAsgJ9sl5tjYE0DEtZqc0rT9oqD7U57My ECIewElc4VenLB2/GK5MfJoJZTsq7fWNpFkUSRZvxT0TRLqznjVepZ2AFzsplScCAwEAAaOCAdMw ggHPMB8GA1UdIwQYMBaAFIKvbIz4xf6WYXzoHz0rcUhexIvAMB0GA1UdDgQWBBS37jX/NtC72k+A CsaxitxCsdQxOzAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEF BQcDBAYIKwYBBQUHAwIwRgYDVR0gBD8wPTA7BgwrBgEEAbIxAQIBAwUwKzApBggrBgEFBQcCARYd aHR0cHM6Ly9zZWN1cmUuY29tb2RvLm5ldC9DUFMwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDovL2Ny bC5jb21vZG9jYS5jb20vQ09NT0RPUlNBQ2xpZW50QXV0aGVudGljYXRpb25hbmRTZWN1cmVFbWFp bENBLmNybDCBiwYIKwYBBQUHAQEEfzB9MFUGCCsGAQUFBzAChklodHRwOi8vY3J0LmNvbW9kb2Nh LmNvbS9DT01PRE9SU0FDbGllbnRBdXRoZW50aWNhdGlvbmFuZFNlY3VyZUVtYWlsQ0EuY3J0MCQG CCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wHgYDVR0RBBcwFYETZHdtdzJAaW5m cmFkZWFkLm9yZzANBgkqhkiG9w0BAQsFAAOCAQEAC20spBbrL71ZEiFrbXBHonzhhirO1sdn+X+O W579oIXMSuVEY1LwpyYYPrKMTjKECxuvp24c829qy03UVRm742R9Hzjs6tC0oatBF7KpyW27sCYS vj5wbal+TttzzB7rT9ZfPALVTfkW+9qEr5w/nSuu9PCaqlMdjABSzHr64SUVy4ym9jJvv/FwaRMP gew4rDeEzJSwf3eeVp0/VDzR5kPtyhS+0K0zvIWBMZFPOPYOfA59zcN6AmzFIJ8vNaHKy5QdmeXx RkLtQHTYgQPpIP1Mc8iWaRWynwiE3ecl+PWzq4i+vdmjFQ8qlL4fHz/k/fT6qKx+HCCT+jsUk3cS jDCCBeYwggPOoAMCAQICEGqb4Tg7/ytrnwHV2binUlYwDQYJKoZIhvcNAQEMBQAwgYUxCzAJBgNV BAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAY BgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYDVQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRp b24gQXV0aG9yaXR5MB4XDTEzMDExMDAwMDAwMFoXDTI4MDEwOTIzNTk1OVowgZcxCzAJBgNVBAYT AkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNV BAoTEUNPTU9ETyBDQSBMaW1pdGVkMT0wOwYDVQQDEzRDT01PRE8gUlNBIENsaWVudCBBdXRoZW50 aWNhdGlvbiBhbmQgU2VjdXJlIEVtYWlsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAvrOeV6wodnVAFsc4A5jTxhh2IVDzJXkLTLWg0X06WD6cpzEup/Y0dtmEatrQPTRI5Or1u6zf +bGBSyD9aH95dDSmeny1nxdlYCeXIoymMv6pQHJGNcIDpFDIMypVpVSRsivlJTRENf+RKwrB6vcf WlP8dSsE3Rfywq09N0ZfxcBa39V0wsGtkGWC+eQKiz4pBZYKjrc5NOpG9qrxpZxyb4o4yNNwTqza aPpGRqXB7IMjtf7tTmU2jqPMLxFNe1VXj9XB1rHvbRikw8lBoNoSWY66nJN/VCJv5ym6Q0mdCbDK CMPybTjoNCQuelc0IAaO4nLUXk0BOSxSxt8kCvsUtQIDAQABo4IBPDCCATgwHwYDVR0jBBgwFoAU u69+Aj36pvE8hI6t7jiY7NkyMtQwHQYDVR0OBBYEFIKvbIz4xf6WYXzoHz0rcUhexIvAMA4GA1Ud DwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMBEGA1UdIAQKMAgwBgYEVR0gADBMBgNVHR8E RTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9u QXV0aG9yaXR5LmNybDBxBggrBgEFBQcBAQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29t b2RvY2EuY29tL0NPTU9ET1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz cC5jb21vZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAHhcsoEoNE887l9Wzp+XVuyPomsX9vP2 SQgG1NgvNc3fQP7TcePo7EIMERoh42awGGsma65u/ITse2hKZHzT0CBxhuhb6txM1n/y78e/4ZOs 0j8CGpfb+SJA3GaBQ+394k+z3ZByWPQedXLL1OdK8aRINTsjk/H5Ns77zwbjOKkDamxlpZ4TKSDM KVmU/PUWNMKSTvtlenlxBhh7ETrN543j/Q6qqgCWgWuMAXijnRglp9fyadqGOncjZjaaSOGTTFB+ E2pvOUtY+hPebuPtTbq7vODqzCM6ryEhNhzf+enm0zlpXK7q332nXttNtjv7VFNYG+I31gnMrwfH M5tdhYF/8v5UY5g2xANPECTQdu9vWPoqNSGDt87b3gXb1AiGGaI06vzgkejL580ul+9hz9D0S0U4 jkhJiA7EuTecP/CFtR72uYRBcunwwH3fciPjviDDAI9SnC/2aPY8ydehzuZutLbZdRJ5PDEJM/1t yZR2niOYihZ+FCbtf3D9mB12D4ln9icgc7CwaxpNSCPt8i/GqK2HsOgkL3VYnwtx7cJUmpvVdZ4o gnzgXtgtdk3ShrtOS1iAN2ZBXFiRmjVzmehoMof06r1xub+85hFQzVxZx5/bRaTKTlL8YXLI8nAb R9HWdFqzcOoB/hxfEyIQpx9/s81rgzdEZOofSlZHynoSMYIDyjCCA8YCAQEwga0wgZcxCzAJBgNV BAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAY BgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMT0wOwYDVQQDEzRDT01PRE8gUlNBIENsaWVudCBBdXRo ZW50aWNhdGlvbiBhbmQgU2VjdXJlIEVtYWlsIENBAhEA4rtJSHkq7AnpxKUY8ZlYZjANBglghkgB ZQMEAgEFAKCCAe0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTkw NjEyMjE0MzAwWjAvBgkqhkiG9w0BCQQxIgQgoEMDJPwuWodmsdx87Ro8nOXiIFARGicrliEzofwn pZgwgb4GCSsGAQQBgjcQBDGBsDCBrTCBlzELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIg TWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQx PTA7BgNVBAMTNENPTU9ETyBSU0EgQ2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBTZWN1cmUgRW1h aWwgQ0ECEQDiu0lIeSrsCenEpRjxmVhmMIHABgsqhkiG9w0BCRACCzGBsKCBrTCBlzELMAkGA1UE BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxPTA7BgNVBAMTNENPTU9ETyBSU0EgQ2xpZW50IEF1dGhl bnRpY2F0aW9uIGFuZCBTZWN1cmUgRW1haWwgQ0ECEQDiu0lIeSrsCenEpRjxmVhmMA0GCSqGSIb3 DQEBAQUABIIBAC3kN9A3Vb0AjKKusAYV9uu8QzGE88r5aTPLIi1Up0INQy1iOrATIHCk1LnynWpx 4IyoG8YREAn327eUDrXxYj8glUdkdAn2STcm7PkZp+qefQPY3v8qUhw73+UqYfLlxY73sccW4Fxr ggKTEElwrEY5wbKvh1hphz6H7swmVlGOHyqcZ3lRkLrhXTAVKmUXIThMIxf8UvVR6er4lLbagExj NxrbXfxoYnWnQZZwkmSLymTA9HgUWVuI+SIP3SYc9KQ6eUvS9NIUiB9T/zN3Q2E9dAH8f/rVUo7j dq+r+nnlj5L8cdyeiIOpPtt7GF/suirLDYSybi8BO95FGmejF54AAAAAAAA= --=-EVu/9jE1bhWR3EsmM4yC--