diff --git a/.gitignore b/.gitignore index b42d5219c51ec1d9f93d84748ecbeadd497c2002..9789e4e115de33a228f0e0b282519ffd71a67f7f 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,7 @@ prelinkedkernel.unpack *.pyc Debug/QemuRun Doxy +Legacy/BinDrivers/X64 +Legacy/BinDrivers/IA32 +Legacy/BootLoader/bin +Legacy/BootSector/bin diff --git a/.travis.yml b/.travis.yml index cbca341a7a697ef4cf8da08c3b6c17fa973afdc5..d61011384261e777ee091960f1695808e7c1d2d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,8 @@ matrix: script: - HOMEBREW_NO_INSTALL_CLEANUP=1 HOMEBREW_NO_AUTO_UPDATE=1 brew install openssl mingw-w64 - - "./macbuild.tool" + - "./build_oc.tool" + - "./build_duet.tool" deploy: provider: releases @@ -59,7 +60,8 @@ matrix: - if [ "$sum" != "$expsum" ]; then echo "Invalid checksum $sum" ; exit 1 ; fi - tar -xf "${file}${suf}" || exit 1 - export PATH="$(pwd)/${file}/bin:$PATH" - - "./macbuild.tool" + - "./build_oc.tool" + - "./build_duet.tool" - os: linux name: "Build Linux CLANG38" @@ -77,7 +79,8 @@ matrix: - sudo apt-get remove -y llvm-3.8 libllvm3.8 # Move LLVM 3.8 out of the way. - export PATH="/usr/lib/llvm-8/bin:$PATH" # Default compiler (7.0 or 3.8) has no LTO plugin. - export TOOLCHAINS=CLANG38 - - "./macbuild.tool" + - "./build_oc.tool" + - "./build_duet.tool" # Currently this is too ugly, but maybe we can use that in the future. - sudo apt-get install -y doxygen texlive texlive-latex-extra - abort() { tail -200 log.txt ; exit 1 ; } @@ -107,6 +110,6 @@ matrix: name: "acidanthera/OpenCorePkg" description: "OpenCorePkg" notification_email: $NOTIFICATION_EMAIL - build_command_prepend: "./macbuild.tool --skip-build --skip-package && cd UDK ; src=$(curl -Lfs https://raw.githubusercontent.com/acidanthera/Lilu/master/Lilu/Scripts/covstrap.sh) && eval \"$src\" || exit 1" - build_command: "../macbuild.tool --skip-tests --skip-package RELEASE" + build_command_prepend: "./build_oc.tool --skip-build --skip-package && cd UDK ; src=$(curl -Lfs https://raw.githubusercontent.com/acidanthera/Lilu/master/Lilu/Scripts/covstrap.sh) && eval \"$src\" || exit 1" + build_command: "../build_oc.tool --skip-tests --skip-package RELEASE" branch_pattern: master diff --git a/Docs/Configuration.tex b/Docs/Configuration.tex index dfa0fdd920f413589dabbe1804692232794a32d4..ae58ff44e92af91d4562d5863dc31558d8aae79f 100755 --- a/Docs/Configuration.tex +++ b/Docs/Configuration.tex @@ -557,9 +557,9 @@ cross-platform and open-source alternative utilised. For BIOS booting a third-party UEFI environment provider will have to -be used. \texttt{DuetPkg} is one of the known UEFI environment providers +be used. \texttt{OpenDuetPkg} is one of the known UEFI environment providers for legacy systems. To run OpenCore on such a legacy system you can install -\texttt{DuetPkg} with a dedicated tool BootInstall (bundled with OpenCore). +\texttt{OpenDuetPkg} with a dedicated tool BootInstall (bundled with OpenCore). For upgrade purposes refer to \texttt{Differences.pdf} document, providing the information about the changes affecting the configuration compared @@ -591,7 +591,6 @@ command sequence may look as follows: \begin{lstlisting}[caption=Compilation Commands, label=compile, style=ocbash] git clone https://github.com/acidanthera/audk UDK cd UDK -git clone https://github.com/acidanthera/DuetPkg git clone https://github.com/acidanthera/OpenCorePkg source edksetup.sh make -C BaseTools @@ -610,11 +609,12 @@ Add \texttt{.clang\_complete} file with similar content to your UDK root: -I/UefiPackages/MdeModulePkg -I/UefiPackages/MdeModulePkg/Include -I/UefiPackages/MdeModulePkg/Include/X64 --I/UefiPackages/DuetPkg/Include -I/UefiPackages/AppleSupportPkg/Include -I/UefiPackages/OpenCorePkg/Include/AMI -I/UefiPackages/OpenCorePkg/Include/Acidanthera -I/UefiPackages/OpenCorePkg/Include/Apple +-I/UefiPackages/OpenCorePkg/Include/Apple/X64 +-I/UefiPackages/OpenCorePkg/Include/Duet -I/UefiPackages/OpenCorePkg/Include/Generic -I/UefiPackages/OpenCorePkg/Include/Intel -I/UefiPackages/OpenCorePkg/Include/Microsoft @@ -2217,7 +2217,7 @@ The boot process is as follows: \end{itemize} \emph{Note 1}: This process is meant to work reliably only when \texttt{RequestBootVarRouting} -option is enabled or the firmware does not control UEFI boot options (\texttt{DuetPkg} or +option is enabled or the firmware does not control UEFI boot options (\texttt{OpenDuetPkg} or custom BDS). Without \texttt{BootProtect} it also is possible that other operating systems overwrite OpenCore, make sure to enable it if you plan to use them. @@ -4163,7 +4163,7 @@ even cause permanent firmware damage. Some of the known drivers are listed below on top of a custom USB keyboard driver implementation. This is an alternative to builtin \texttt{KeySupport}, which may work better or worse depending on the firmware. \\ \href{https://github.com/acidanthera/audk}{\texttt{Ps2KeyboardDxe}}\textbf{*} -& PS/2 keyboard driver from \texttt{MdeModulePkg}. DuetPkg and some firmwares +& PS/2 keyboard driver from \texttt{MdeModulePkg}. \texttt{OpenDuetPkg} and some firmwares may not include this driver, but it is necessary for PS/2 keyboard to work. Note, unlike \texttt{OpenUsbKbDxe} this driver has no \texttt{AppleKeyMapAggregator} support and thus requires \texttt{KeySupport} to be enabled. \\ diff --git a/Include/Duet/EfiFlashMap.h b/Include/Duet/EfiFlashMap.h new file mode 100644 index 0000000000000000000000000000000000000000..4fc74d72cc45b590b1a6faca536992d529eb6aa0 --- /dev/null +++ b/Include/Duet/EfiFlashMap.h @@ -0,0 +1,153 @@ +/** @file + +Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + EfiFlashMap.h + +Abstract: + + Defines for the EFI Flash Map functionality + +**/ + +#ifndef _EFI_FLASHMAP_H_ +#define _EFI_FLASHMAP_H_ + +// +// Definition for flash map GUIDed HOBs +// +typedef UINT32 EFI_FLASH_AREA_ATTRIBUTES; + +#define EFI_FLASH_AREA_FV 0x0001 +#define EFI_FLASH_AREA_SUBFV 0x0002 +#define EFI_FLASH_AREA_MEMMAPPED_FV 0x0004 +#define EFI_FLASH_AREA_REQUIRED 0x0008 +#define EFI_FLASH_AREA_CORRUPT 0x0010 + +typedef UINT8 EFI_FLASH_AREA_TYPE; + +#define EFI_FLASH_AREA_RECOVERY_BIOS 0x0 // Recovery code +#define EFI_FLASH_AREA_MAIN_BIOS 0x1 // Regular BIOS code +#define EFI_FLASH_AREA_PAL_B 0x2 // PAL-B +#define EFI_FLASH_AREA_RESERVED_03 0x3 // Reserved for backwards compatibility +#define EFI_FLASH_AREA_RESERVED_04 0x4 // Reserved for backwards compatibility +#define EFI_FLASH_AREA_DMI_FRU 0x5 // DMI FRU information +#define EFI_FLASH_AREA_OEM_BINARY 0x6 // OEM Binary Code/data +#define EFI_FLASH_AREA_RESERVED_07 0x7 // Reserved for backwards compatibility +#define EFI_FLASH_AREA_RESERVED_08 0x8 // Reserved for backwards compatibility +#define EFI_FLASH_AREA_RESERVED_09 0x9 // Reserved for backwards compatibility +#define EFI_FLASH_AREA_RESERVED_0A 0x0a // Reserved for backwards compatibility +#define EFI_FLASH_AREA_EFI_VARIABLES 0x0b // EFI variables +#define EFI_FLASH_AREA_MCA_LOG 0x0c // MCA error log +#define EFI_FLASH_AREA_SMBIOS_LOG 0x0d // SMBIOS error log +#define EFI_FLASH_AREA_FTW_BACKUP 0x0e // A backup block during FTW operations +#define EFI_FLASH_AREA_FTW_STATE 0x0f // State information during FTW operations +#define EFI_FLASH_AREA_UNUSED 0x0fd // Not used +#define EFI_FLASH_AREA_GUID_DEFINED 0x0fe // Usage defined by a GUID +#pragma pack(1) +// +// An individual sub-area Entry. +// A single flash area may consist of more than one sub-area. +// +/** +typedef struct { + EFI_FLASH_AREA_ATTRIBUTES Attributes; + UINT32 Reserved; + EFI_PHYSICAL_ADDRESS Base; + EFI_PHYSICAL_ADDRESS Length; + EFI_GUID FileSystem; +} EFI_FLASH_SUBAREA_ENTRY; + +typedef struct { + UINT8 Reserved[3]; + EFI_FLASH_AREA_TYPE AreaType; + EFI_GUID AreaTypeGuid; + UINT32 NumEntries; + EFI_FLASH_SUBAREA_ENTRY Entries[1]; +} EFI_FLASH_MAP_ENTRY_DATA; + +typedef struct { + UINT8 Reserved[3]; + EFI_FLASH_AREA_TYPE AreaType; + EFI_GUID AreaTypeGuid; + UINT32 NumberOfEntries; + EFI_FLASH_SUBAREA_ENTRY Entries[1]; + // + // Extended Hob data. + // + // VolumeId and FilePath indicating a unique file. + // + UINT32 VolumeId; + CHAR16 FilePath[256]; + UINT32 ActuralSize; + UINT32 Offset; +} EFI_FLASH_MAP_FS_ENTRY_DATA; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_GUID Name; + UINT8 Reserved[3]; + EFI_FLASH_AREA_TYPE AreaType; + EFI_GUID AreaTypeGuid; + UINT32 NumEntries; + EFI_FLASH_SUBAREA_ENTRY Entries[1]; +} EFI_HOB_FLASH_MAP_ENTRY_TYPE; + +// +// Internal definitions +// +typedef struct { + UINT8 Reserved[3]; + EFI_FLASH_AREA_TYPE AreaType; + EFI_GUID AreaTypeGuid; + UINT32 NumberOfEntries; + EFI_FLASH_SUBAREA_ENTRY SubAreaData; +} EFI_FLASH_AREA_HOB_DATA; + +typedef struct { + UINTN Base; + UINTN Length; + EFI_FLASH_AREA_ATTRIBUTES Attributes; + EFI_FLASH_AREA_TYPE AreaType; + UINT8 Reserved[3]; + EFI_GUID AreaTypeGuid; +} EFI_FLASH_AREA_DATA; +**/ + +typedef struct { + EFI_FLASH_AREA_ATTRIBUTES Attributes; + UINT32 Reserved; + EFI_PHYSICAL_ADDRESS Base; + EFI_PHYSICAL_ADDRESS Length; + EFI_GUID FileSystem; +} EFI_FLASH_SUBAREA_ENTRY; + +typedef struct { + UINT8 Reserved[3]; + EFI_FLASH_AREA_TYPE AreaType; + EFI_GUID AreaTypeGuid; + UINT32 NumberOfEntries; + EFI_FLASH_SUBAREA_ENTRY Entries[1]; + // + // Extended Hob data. + // + // VolumeId and FilePath indicating a unique file. + // + UINT32 VolumeId; + CHAR16 FilePath[258]; + UINT32 ActuralSize; + UINT32 Offset; +} EFI_FLASH_MAP_FS_ENTRY_DATA; + +#pragma pack() + +#endif // #ifndef _EFI_FLASHMAP_H_ diff --git a/Include/Duet/EfiImageFormat.h b/Include/Duet/EfiImageFormat.h new file mode 100644 index 0000000000000000000000000000000000000000..b26eeab4b406b97837fd63ffacfdf18a820c92a5 --- /dev/null +++ b/Include/Duet/EfiImageFormat.h @@ -0,0 +1,296 @@ +/*++ + +Copyright (c) 2004, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + EfiImageFormat.h + +Abstract: + + This file defines the data structures that are architecturally defined for file + images loaded via the FirmwareVolume protocol. The Firmware Volume specification + is the basis for these definitions. + +--*/ + +#ifndef _EFI_IMAGE_FORMAT_H_ +#define _EFI_IMAGE_FORMAT_H_ + +// +// pack all data structures since this is actually a binary format and we cannot +// allow internal padding in the data structures because of some compilerism.. +// +#pragma pack(1) +// +// //////////////////////////////////////////////////////////////////////////// +// +// Architectural file types +// +typedef UINT8 EFI_FV_FILETYPE; + +#define EFI_FV_FILETYPE_ALL 0x00 +#define EFI_FV_FILETYPE_RAW 0x01 +#define EFI_FV_FILETYPE_FREEFORM 0x02 +#define EFI_FV_FILETYPE_SECURITY_CORE 0x03 +#define EFI_FV_FILETYPE_PEI_CORE 0x04 +#define EFI_FV_FILETYPE_DXE_CORE 0x05 +#define EFI_FV_FILETYPE_PEIM 0x06 +#define EFI_FV_FILETYPE_DRIVER 0x07 +#define EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER 0x08 +#define EFI_FV_FILETYPE_APPLICATION 0x09 +// +// File type 0x0A is reserved and should not be used +// +#define EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE 0x0B + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Section types +// +typedef UINT8 EFI_SECTION_TYPE; + +// +// ************************************************************ +// The section type EFI_SECTION_ALL is a psuedo type. It is +// used as a wildcard when retrieving sections. The section +// type EFI_SECTION_ALL matches all section types. +// ************************************************************ +// +#define EFI_SECTION_ALL 0x00 + +// +// ************************************************************ +// Encapsulation section Type values +// ************************************************************ +// +#define EFI_SECTION_COMPRESSION 0x01 +#define EFI_SECTION_GUID_DEFINED 0x02 + +// +// ************************************************************ +// Leaf section Type values +// ************************************************************ +// +#define EFI_SECTION_FIRST_LEAF_SECTION_TYPE 0x10 + +#define EFI_SECTION_PE32 0x10 +#define EFI_SECTION_PIC 0x11 +#define EFI_SECTION_TE 0x12 +#define EFI_SECTION_DXE_DEPEX 0x13 +#define EFI_SECTION_VERSION 0x14 +#define EFI_SECTION_USER_INTERFACE 0x15 +#define EFI_SECTION_COMPATIBILITY16 0x16 +#define EFI_SECTION_FIRMWARE_VOLUME_IMAGE 0x17 +#define EFI_SECTION_FREEFORM_SUBTYPE_GUID 0x18 +#define EFI_SECTION_RAW 0x19 +#define EFI_SECTION_PEI_DEPEX 0x1B + +#define EFI_SECTION_LAST_LEAF_SECTION_TYPE 0x1B +#define EFI_SECTION_LAST_SECTION_TYPE 0x1B + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Common section header +// +typedef struct { + UINT8 Size[3]; + UINT8 Type; +} EFI_COMMON_SECTION_HEADER; + +#define SECTION_SIZE(SectionHeaderPtr) \ + ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) SectionHeaderPtr)->Size) & 0x00ffffff)) + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Compression section +// +// +// CompressionType values +// +#define EFI_NOT_COMPRESSED 0x00 +#define EFI_STANDARD_COMPRESSION 0x01 +#define EFI_CUSTOMIZED_COMPRESSION 0x02 + +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + UINT32 UncompressedLength; + UINT8 CompressionType; +} EFI_COMPRESSION_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// GUID defined section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + EFI_GUID SectionDefinitionGuid; + UINT16 DataOffset; + UINT16 Attributes; +} EFI_GUID_DEFINED_SECTION; + +// +// Bit values for Attributes +// +#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01 +#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02 + +// +// 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 + +// +// //////////////////////////////////////////////////////////////////////////// +// +// PE32+ section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; +} EFI_PE32_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// PIC section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; +} EFI_PIC_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// PEIM header section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; +} EFI_PEIM_HEADER_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// DEPEX section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; +} EFI_DEPEX_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Version section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + UINT16 BuildNumber; + INT16 VersionString[1]; +} EFI_VERSION_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// User interface section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + INT16 FileNameString[1]; +} EFI_USER_INTERFACE_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Code16 section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; +} EFI_CODE16_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Firmware Volume Image section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; +} EFI_FIRMWARE_VOLUME_IMAGE_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Freeform subtype GUID section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + EFI_GUID SubTypeGuid; +} EFI_FREEFORM_SUBTYPE_GUID_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Raw section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; +} EFI_RAW_SECTION; + +// +// undo the pragma from the beginning... +// +#pragma pack() + +typedef union { + EFI_COMMON_SECTION_HEADER *CommonHeader; + EFI_COMPRESSION_SECTION *CompressionSection; + EFI_GUID_DEFINED_SECTION *GuidDefinedSection; + EFI_PE32_SECTION *Pe32Section; + EFI_PIC_SECTION *PicSection; + EFI_PEIM_HEADER_SECTION *PeimHeaderSection; + EFI_DEPEX_SECTION *DependencySection; + EFI_VERSION_SECTION *VersionSection; + EFI_USER_INTERFACE_SECTION *UISection; + EFI_CODE16_SECTION *Code16Section; + EFI_FIRMWARE_VOLUME_IMAGE_SECTION *FVImageSection; + EFI_FREEFORM_SUBTYPE_GUID_SECTION *FreeformSubtypeSection; + EFI_RAW_SECTION *RawSection; +} EFI_FILE_SECTION_POINTER; + +// +// EFI_FV_ATTRIBUTES bit definitions +// +typedef UINT64 EFI_FV_ATTRIBUTES; +typedef UINT32 EFI_FV_FILE_ATTRIBUTES; +typedef UINT32 EFI_FV_WRITE_POLICY; + + +typedef struct { + EFI_GUID *NameGuid; + EFI_FV_FILETYPE Type; + EFI_FV_FILE_ATTRIBUTES FileAttributes; + VOID *Buffer; + UINT32 BufferSize; +} EFI_FV_WRITE_FILE_DATA; + + +#endif diff --git a/Include/Duet/EfiLdrHandoff.h b/Include/Duet/EfiLdrHandoff.h new file mode 100644 index 0000000000000000000000000000000000000000..cba777f01b0d544c80b05914c28bd30fdd3581e5 --- /dev/null +++ b/Include/Duet/EfiLdrHandoff.h @@ -0,0 +1,59 @@ +/** @file + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + EfiLdrHandoff.h + +Abstract: + +Revision History: + +**/ + +#ifndef _EFILDR_HANDOFF_H_ +#define _EFILDR_HANDOFF_H_ + +#include +#include + +#define EFILDR_BASE_SEGMENT 0x2000 +#define EFILDR_LOAD_ADDRESS (EFILDR_BASE_SEGMENT << 4) +#define EFILDR_HEADER_ADDRESS (EFILDR_LOAD_ADDRESS+0x2000) + +#define EFILDR_CB_VA 0x00 + +typedef struct _EFILDRHANDOFF { + UINTN MemDescCount; + EFI_MEMORY_DESCRIPTOR *MemDesc; + VOID *BfvBase; + UINTN BfvSize; + VOID *DxeIplImageBase; + UINTN DxeIplImageSize; + VOID *DxeCoreImageBase; + UINTN DxeCoreImageSize; + VOID *DxeCoreEntryPoint; +} EFILDRHANDOFF; + +typedef struct { + UINT32 CheckSum; + UINT32 Offset; + UINT32 Length; + UINT8 FileName[52]; +} EFILDR_IMAGE; + +typedef struct { + UINT32 Signature; + UINT32 HeaderCheckSum; + UINT32 FileLength; + UINT32 NumberOfImages; +} EFILDR_HEADER; + +#endif diff --git a/Include/Duet/FlashLayout.h b/Include/Duet/FlashLayout.h new file mode 100644 index 0000000000000000000000000000000000000000..4829c68f964e7f777d290f7cff45896b52a90bdf --- /dev/null +++ b/Include/Duet/FlashLayout.h @@ -0,0 +1,54 @@ +/** @file + +Copyright (c) 2007, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + FlashLayout.h + +Abstract: + + Platform specific flash layout + +**/ + +#ifndef _EFI_FLASH_LAYOUT +#define _EFI_FLASH_LAYOUT + +#include + +// +// Firmware Volume Information for DUET +// +#define FV_BLOCK_SIZE 0x10000 +#define FV_BLOCK_MASK 0x0FFFF +#define EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH (sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY)) + +#define NV_STORAGE_SIZE 0x4000 +#define NV_STORAGE_FVB_SIZE ((NV_STORAGE_SIZE + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH + FV_BLOCK_MASK) & ~FV_BLOCK_MASK) +#define NV_STORAGE_FVB_BLOCK_NUM (NV_STORAGE_FVB_SIZE / FV_BLOCK_SIZE) + +#define NV_FTW_WORKING_SIZE 0x2000 +#define NV_FTW_SPARE_SIZE 0x10000 +#define NV_FTW_FVB_SIZE ((NV_FTW_WORKING_SIZE + NV_FTW_SPARE_SIZE + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH + FV_BLOCK_MASK) & ~FV_BLOCK_MASK) +#define NV_FTW_FVB_BLOCK_NUM (NV_FTW_FVB_SIZE / FV_BLOCK_SIZE) + +#define NV_STORAGE_FILE_PATH L".\\Efivar.bin" + +#define BOOT1_BASE ((UINTN) 0xE000U) +#define BOOT1_MAGIC 0xAA55 + +typedef struct { + UINT8 LoaderCode[496]; + UINT8 Signature[14]; + UINT16 Magic; +} BOOT1_LOADER; + +#endif // _EFI_FLASH_LAYOUT diff --git a/Include/Duet/Guid/AcpiDescription.h b/Include/Duet/Guid/AcpiDescription.h new file mode 100644 index 0000000000000000000000000000000000000000..6f8161026c3be8e5420f0e4caaff8b0afd85b337 --- /dev/null +++ b/Include/Duet/Guid/AcpiDescription.h @@ -0,0 +1,109 @@ +/** @file + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + AcpiDescription.h + +Abstract: + + + GUIDs used for ACPI Description + +**/ + +#ifndef _EFI_ACPI_DESCRIPTION_H_ +#define _EFI_ACPI_DESCRIPTION_H_ + +#include + +#define EFI_ACPI_DESCRIPTION_GUID \ + { \ + 0x3c699197, 0x93c, 0x4c69, {0xb0, 0x6b, 0x12, 0x8a, 0xe3, 0x48, 0x1d, 0xc9} \ + } + +// +// Following structure defines ACPI Description information. +// This information is platform specific, may be consumed by DXE generic driver. +// +#pragma pack(1) +typedef struct _EFI_ACPI_DESCRIPTION { + // + // For Timer + // + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE PM_TMR_BLK; + UINT8 PM_TMR_LEN; + UINT8 TMR_VAL_EXT; + + // + // For RTC + // + UINT8 DAY_ALRM; + UINT8 MON_ALRM; + UINT8 CENTURY; + + // + // For Reset + // + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE RESET_REG; + UINT8 RESET_VALUE; + + // + // For Shutdown + // + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE PM1a_EVT_BLK; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE PM1b_EVT_BLK; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE PM1a_CNT_BLK; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE PM1b_CNT_BLK; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE PM2_CNT_BLK; + UINT8 PM1_EVT_LEN; + UINT8 PM1_CNT_LEN; + UINT8 PM2_CNT_LEN; + UINT8 SLP_TYPa; + UINT8 SLP_TYPb; + + // + // For sleep + // + UINT8 SLP1_TYPa; + UINT8 SLP1_TYPb; + UINT8 SLP2_TYPa; + UINT8 SLP2_TYPb; + UINT8 SLP3_TYPa; + UINT8 SLP3_TYPb; + UINT8 SLP4_TYPa; + UINT8 SLP4_TYPb; + + // + // GPE + // + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE GPE0_BLK; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE GPE1_BLK; + UINT8 GPE0_BLK_LEN; + UINT8 GPE1_BLK_LEN; + UINT8 GPE1_BASE; + + // + // IAPC Boot Arch + // + UINT16 IAPC_BOOT_ARCH; + + // + // Flags + // + UINT32 Flags; + +} EFI_ACPI_DESCRIPTION; +#pragma pack() + +extern EFI_GUID gEfiAcpiDescriptionGuid; + +#endif diff --git a/Include/Duet/Guid/DxeCoreFileName.h b/Include/Duet/Guid/DxeCoreFileName.h new file mode 100644 index 0000000000000000000000000000000000000000..c4a8a1905c2c2717795da9df9539932df2780426 --- /dev/null +++ b/Include/Duet/Guid/DxeCoreFileName.h @@ -0,0 +1,23 @@ +/** @file + Guid is EDKII DxeCore moudle GUID. + +Copyright (c) 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DXE_CORE_FILE_NAME__ +#define __DXE_CORE_FILE_NAME__ + +#define DXE_CORE_FILE_NAME_GUID \ + { 0xD6A2CB7F, 0x6A18, 0x4e2f, {0xB4, 0x3B, 0x99, 0x20, 0xA7, 0x33, 0x70, 0x0A }} + +extern EFI_GUID gDxeCoreFileNameGuid; + +#endif diff --git a/Include/Duet/Guid/FlashMapHob.h b/Include/Duet/Guid/FlashMapHob.h new file mode 100644 index 0000000000000000000000000000000000000000..e62f159fb3869883719c86b07d264940b7650f49 --- /dev/null +++ b/Include/Duet/Guid/FlashMapHob.h @@ -0,0 +1,33 @@ +/** @file + +Copyright (c) 2004, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + FlashMapHob.h + +Abstract: + + GUID used for Flash Map HOB entries in the HOB list. + +**/ + +#ifndef _FLASH_MAP_HOB_GUID_H_ +#define _FLASH_MAP_HOB_GUID_H_ + +// +// Definitions for Flash Map +// +#define EFI_FLASH_MAP_HOB_GUID \ + { 0xb091e7d2, 0x5a0, 0x4198, {0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59} } + +extern EFI_GUID gEfiFlashMapHobGuid; + +#endif // _FLASH_MAP_HOB_GUID_H_ diff --git a/Include/Duet/Guid/LdrMemoryDescriptor.h b/Include/Duet/Guid/LdrMemoryDescriptor.h new file mode 100644 index 0000000000000000000000000000000000000000..38a997deea0c8431f45667e67a93b5cb6ff49457 --- /dev/null +++ b/Include/Duet/Guid/LdrMemoryDescriptor.h @@ -0,0 +1,33 @@ +/** @file + Guid is for GUIDED HOB of LDR memory descriptor. + +Copyright (c) 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __LDR_MEMORY_DESCRIPTOR__ +#define __LDR_MEMORY_DESCRIPTOR__ + +#define LDR_MEMORY_DESCRIPTOR_GUID \ + { 0x7701d7e5, 0x7d1d, 0x4432, {0xa4, 0x68, 0x67, 0x3d, 0xab, 0x8a, 0xde, 0x60}} + +#pragma pack(1) + +typedef struct { + EFI_HOB_GUID_TYPE Hob; + UINTN MemDescCount; + EFI_MEMORY_DESCRIPTOR *MemDesc; +} MEMORY_DESC_HOB; + +#pragma pack() + +extern EFI_GUID gLdrMemoryDescriptorGuid; + +#endif diff --git a/Include/Duet/Guid/PciExpressBaseAddress.h b/Include/Duet/Guid/PciExpressBaseAddress.h new file mode 100644 index 0000000000000000000000000000000000000000..ff554383c11b4d43984c4d09a9025a855bb7aa3e --- /dev/null +++ b/Include/Duet/Guid/PciExpressBaseAddress.h @@ -0,0 +1,46 @@ +/** @file + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciExpressBaseAddress.h + +Abstract: + + + GUIDs used for PciExpress Base Address + +**/ + +#ifndef _EFI_PCI_EXPRESS_BASE_ADDRESS_H_ +#define _EFI_PCI_EXPRESS_BASE_ADDRESS_H_ + +#define EFI_PCI_EXPRESS_BASE_ADDRESS_GUID \ + { \ + 0x3677d529, 0x326f, 0x4603, {0xa9, 0x26, 0xea, 0xac, 0xe0, 0x1d, 0xcb, 0xb0} \ + } + +// +// Following structure defines PCI Express Base Address information. +// This information is platform specific, and built into hob in PEI phase. +// It can be consumed by PEI PCI driver and DXE PCI driver. +// +#pragma pack(1) +typedef struct _EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION { + UINT32 HostBridgeNumber; + UINT32 RootBridgeNumber; + UINT64 PciExpressBaseAddress; +} EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION; +#pragma pack() + +extern EFI_GUID gEfiPciExpressBaseAddressGuid; + +#endif diff --git a/Include/Duet/Guid/PciOptionRomTable.h b/Include/Duet/Guid/PciOptionRomTable.h new file mode 100644 index 0000000000000000000000000000000000000000..a2fb99710a690befd89b5978f7b8501f5605419a --- /dev/null +++ b/Include/Duet/Guid/PciOptionRomTable.h @@ -0,0 +1,41 @@ +/** @file + GUID and data structure used to describe the list of PCI Option ROMs present in a system. + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PCI_OPTION_ROM_TABLE_GUID_H_ +#define __PCI_OPTION_ROM_TABLE_GUID_H_ + +#define EFI_PCI_OPTION_ROM_TABLE_GUID \ + { 0x7462660f, 0x1cbd, 0x48da, {0xad, 0x11, 0x91, 0x71, 0x79, 0x13, 0x83, 0x1c } } + +extern EFI_GUID gEfiPciOptionRomTableGuid; + +typedef struct { + EFI_PHYSICAL_ADDRESS RomAddress; + EFI_MEMORY_TYPE MemoryType; + UINT32 RomLength; + UINT32 Seg; + UINT8 Bus; + UINT8 Dev; + UINT8 Func; + BOOLEAN ExecutedLegacyBiosImage; + BOOLEAN DontLoadEfiRom; +} EFI_PCI_OPTION_ROM_DESCRIPTOR; + +typedef struct { + UINT64 PciOptionRomCount; + EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptors; +} EFI_PCI_OPTION_ROM_TABLE; + +#endif // __PCI_OPTION_ROM_TABLE_GUID_H_ + diff --git a/Include/Duet/Library/DuetBdsLib.h b/Include/Duet/Library/DuetBdsLib.h new file mode 100644 index 0000000000000000000000000000000000000000..a53d3da610e1b350ed188c3be524638fbc331157 --- /dev/null +++ b/Include/Duet/Library/DuetBdsLib.h @@ -0,0 +1,294 @@ +/** @file + Duet BDS library. + +Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _DUET_BDS_LIB_H_ +#define _DUET_BDS_LIB_H_ + +/// +/// ConnectType +/// +#define CONSOLE_OUT 0x00000001 +#define STD_ERROR 0x00000002 +#define CONSOLE_IN 0x00000004 +#define CONSOLE_ALL (CONSOLE_OUT | CONSOLE_IN | STD_ERROR) + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN ConnectType; +} BDS_CONSOLE_CONNECT_ENTRY; + +/** + This function reads the EFI variable (VendorGuid/Name) and returns a dynamically allocated + buffer and the size of the buffer. If it fails, return NULL. + + @param Name The string part of the EFI variable name. + @param VendorGuid The GUID part of the EFI variable name. + @param VariableSize Returns the size of the EFI variable that was read. + + @return Dynamically allocated memory that contains a copy + of the EFI variable. The caller is responsible for + freeing the buffer. + @retval NULL The variable was not read. + +**/ +VOID * +EFIAPI +BdsLibGetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VariableSize + ); + + +// +// Bds connect and disconnect driver lib funcions +// +/** + This function connects all system drivers with the corresponding controllers. + +**/ +VOID +EFIAPI +BdsLibConnectAllDriversToAllControllers ( + VOID + ); + +/** + This function connects all system drivers to controllers. + +**/ +VOID +EFIAPI +BdsLibConnectAll ( + VOID + ); + +/** + This function creates all handles associated with the given device + path node. If the handle associated with one device path node cannot + be created, then it tries to execute the dispatch to load the missing drivers. + + @param DevicePathToConnect The device path to be connected. Can be + a multi-instance device path. + + @retval EFI_SUCCESS All handles associates with every device path node + were created. + @retval EFI_OUT_OF_RESOURCES Not enough resources to create new handles. + @retval EFI_NOT_FOUND At least one handle could not be created. + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect + ); + +/** + This function will connect all current system handles recursively. + gBS->ConnectController() service is invoked for each handle exist in system handler buffer. + If the handle is bus type handler, all childrens also will be connected recursively by gBS->ConnectController(). + + @retval EFI_SUCCESS All handles and child handles have been + connected. + @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer(). +**/ +EFI_STATUS +EFIAPI +BdsLibConnectAllEfi ( + VOID + ); + +/** + This function will disconnect all current system handles. + gBS->DisconnectController() is invoked for each handle exists in system handle buffer. + If handle is a bus type handle, all childrens also are disconnected recursively by gBS->DisconnectController(). + + @retval EFI_SUCCESS All handles have been disconnected. + @retval EFI_STATUS Error status returned by of gBS->LocateHandleBuffer(). + +**/ +EFI_STATUS +EFIAPI +BdsLibDisconnectAllEfi ( + VOID + ); + +// +// Bds console related lib functions +// +/** + This function will search every simpletxt device in the current system, + and make every simpletxt device a potential console device. + +**/ +VOID +EFIAPI +BdsLibConnectAllConsoles ( + VOID + ); + + +/** + This function will connect console device based on the console + device variable ConIn, ConOut and ErrOut. + + @retval EFI_SUCCESS At least one of the ConIn and ConOut devices have + been connected. + @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable (). + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectAllDefaultConsoles ( + VOID + ); + +/** + This function updates the console variable based on ConVarName. It can + add or remove one specific console device path from the variable + + @param ConVarName The console-related variable name: ConIn, ConOut, + ErrOut. + @param CustomizedConDevicePath The console device path to be added to + the console variable ConVarName. Cannot be multi-instance. + @param ExclusiveDevicePath The console device path to be removed + from the console variable ConVarName. Cannot be multi-instance. + + @retval EFI_UNSUPPORTED The added device path is the same as a removed one. + @retval EFI_SUCCESS Successfully added or removed the device path from the + console variable. + +**/ +EFI_STATUS +EFIAPI +BdsLibUpdateConsoleVariable ( + IN CHAR16 *ConVarName, + IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath + ); + +/** + Connect the console device base on the variable ConVarName. If + ConVarName is a multi-instance device path, and at least one + instance connects successfully, then this function + will return success. + If the handle associate with one device path node can not + be created successfully, then still give chance to do the dispatch, + which load the missing drivers if possible. + + @param ConVarName The console related variable name: ConIn, ConOut, + ErrOut. + + @retval EFI_NOT_FOUND No console devices were connected successfully + @retval EFI_SUCCESS Connected at least one instance of the console + device path based on the variable ConVarName. + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectConsoleVariable ( + IN CHAR16 *ConVarName + ); + +// +// Bds device path related lib functions +// +/** + Delete the instance in Multi that overlaps with Single. + + @param Multi A pointer to a multi-instance device path data + structure. + @param Single A pointer to a single-instance device path data + structure. + + @return This function removes the device path instances in Multi that overlap + Single, and returns the resulting device path. If there is no + remaining device path as a result, this function will return NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +BdsLibDelPartMatchInstance ( + IN EFI_DEVICE_PATH_PROTOCOL *Multi, + IN EFI_DEVICE_PATH_PROTOCOL *Single + ); + +/** + This function compares a device path data structure to that of all the nodes of a + second device path instance. + + @param Multi A pointer to a multi-instance device path data + structure. + @param Single A pointer to a single-instance device path data + structure. + + @retval TRUE If the Single device path is contained within a + Multi device path. + @retval FALSE The Single device path is not contained within a + Multi device path. + +**/ +BOOLEAN +EFIAPI +BdsLibMatchDevicePaths ( + IN EFI_DEVICE_PATH_PROTOCOL *Multi, + IN EFI_DEVICE_PATH_PROTOCOL *Single + ); + +/** + Connect the specific USB device that matches the RemainingDevicePath, + and whose bus is determined by Host Controller (Uhci or Ehci). + + @param HostControllerPI Uhci (0x00) or Ehci (0x20) or Both uhci and ehci + (0xFF). + @param RemainingDevicePath A short-form device path that starts with the first + element being a USB WWID or a USB Class device + path. + + @retval EFI_SUCCESS The specific Usb device is connected successfully. + @retval EFI_INVALID_PARAMETER Invalid HostControllerPi (not 0x00, 0x20 or 0xFF) + or RemainingDevicePath is not the USB class device path. + @retval EFI_NOT_FOUND The device specified by device path is not found. + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectUsbDevByShortFormDP ( + IN UINT8 HostControllerPI, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Platform Bds initialization. Includes the platform firmware vendor, revision + and so crc check. + +**/ +VOID +EFIAPI +PlatformBdsInit ( + VOID + ); + +/** + The function will execute with as the platform policy, current policy + is driven by boot mode. IBV/OEM can customize this code for their specific + policy action. +**/ +VOID +EFIAPI +PlatformBdsPolicyBehavior ( + VOID + ); + +#endif diff --git a/Include/Intel/Protocol/VgaMiniPort.h b/Include/Intel/Protocol/VgaMiniPort.h new file mode 100644 index 0000000000000000000000000000000000000000..da172a47cf40ad9cb3825909a980ce8bdd4a4183 --- /dev/null +++ b/Include/Intel/Protocol/VgaMiniPort.h @@ -0,0 +1,94 @@ +/** @file + The VGA Mini Port Protocol used to set the text display mode of a VGA controller. + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#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 greater + than MaxModeNumber, then EFI_UNSUPPORTED is returned. If the VGA controller + 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 instance. + @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 not 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 to 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 0x3D5. + /// + UINT64 CrtcDataRegisterOffset; + /// + /// PCI Controller MMIO BAR index of the VGA text mode frame buffer. Typically + /// set to EFI_PCI_IO_PASS_THROUGH_BAR + /// + UINT8 VgaMemoryBar; + /// + /// PCI Controller I/O BAR index of the VGA CRTC address register. Typically + /// set to EFI_PCI_IO_PASS_THROUGH_BAR + /// + UINT8 CrtcAddressRegisterBar; + /// + /// PCI Controller I/O BAR index of the VGA CRTC data register. Typically 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/Legacy/BinDrivers/HfsPlus.inf b/Legacy/BinDrivers/HfsPlus.inf new file mode 100644 index 0000000000000000000000000000000000000000..5c299a395f50dbc14b8078400d05b2b21cb199bc --- /dev/null +++ b/Legacy/BinDrivers/HfsPlus.inf @@ -0,0 +1,25 @@ +## @file +# +# HFS+ Filesystem Driver +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = HfsPlus + FILE_GUID = 6839D927-3CAC-4CF9-B05A-400A623B327E + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Binaries.Ia32] + PE32|IA32/HfsPlusLegacy.efi|* + +[Binaries.X64] + PE32|X64/HfsPlusLegacy.efi|* diff --git a/Legacy/BinDrivers/OpenUsbKbDxe.inf b/Legacy/BinDrivers/OpenUsbKbDxe.inf new file mode 100644 index 0000000000000000000000000000000000000000..f391b54245a0c46609c09cdd263614f005030f8d --- /dev/null +++ b/Legacy/BinDrivers/OpenUsbKbDxe.inf @@ -0,0 +1,25 @@ +## @file +# +# OpenCore USB Keyboard Driver +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = OpenUsbKbDxe + FILE_GUID = B4B18806-349E-4305-A7F3-2BD23C8FC1B2 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Binaries.Ia32] + PE32|IA32/OpenUsbKbDxe.efi|* + +[Binaries.X64] + PE32|X64/OpenUsbKbDxe.efi|* diff --git a/Legacy/BinDrivers/README.md b/Legacy/BinDrivers/README.md new file mode 100644 index 0000000000000000000000000000000000000000..d0e637851f7650514d37eabe34591fb8db56630f --- /dev/null +++ b/Legacy/BinDrivers/README.md @@ -0,0 +1,4 @@ +BinDrivers +========== + +Put binary drivers here and enable them in DuetPkg.fdf. diff --git a/Legacy/BootLoader/Makefile b/Legacy/BootLoader/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e761453a63d331603fa818d7f18588c993b82166 --- /dev/null +++ b/Legacy/BootLoader/Makefile @@ -0,0 +1,22 @@ +DESTDIR ?= bin +BOOTSECTORS = boot0 boot1f32 +MKDIR ?= mkdir + +BOOTSECTOR_SRCS = $(addsuffix .nasm, $(BOOTSECTORS)) +BOOTSECTOR_BINS = $(addprefix $(DESTDIR)/, $(BOOTSECTORS)) + +ifdef NASM_PREFIX +NASM=$(NASM_PREFIX)nasm +else +NASM=nasm +endif + +all: $(BOOTSECTOR_BINS) + +$(BOOTSECTOR_BINS): $(BOOTSECTOR_SRCS) + @$(MKDIR) -p bin + @echo "[NASM] $(@F).nasm -> $@" + @"$(NASM)" $(@F).nasm -f bin -o $@ + +clean: + rm -f $(BOOTSECTOR_BINS) *~ diff --git a/Legacy/BootLoader/boot0.nasm b/Legacy/BootLoader/boot0.nasm new file mode 100644 index 0000000000000000000000000000000000000000..e9ca16e83a5f8e77ca850b3801560e2c22b02457 --- /dev/null +++ b/Legacy/BootLoader/boot0.nasm @@ -0,0 +1,720 @@ +; Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. +; +; @APPLE_LICENSE_HEADER_START@ +; +; Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights +; Reserved. This file contains Original Code and/or Modifications of +; Original Code as defined in and that are subject to the Apple Public +; Source License Version 2.0 (the "License"). You may not use this file +; except in compliance with the License. Please obtain a copy of the +; License at http://www.apple.com/publicsource and read it before using +; this file. +; +; The Original Code and all software distributed under the License are +; distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER +; EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +; INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the +; License for the specific language governing rights and limitations +; under the License. +; +; @APPLE_LICENSE_HEADER_END@ +; +; Boot Loader: boot0 +; +; A small boot sector program written in x86 assembly whose only +; responsibility is to locate the active partition, load the +; partition booter into memory, and jump to the booter's entry point. +; It leaves the boot drive in DL and a pointer to the partition entry in SI. +; This version of boot0 implements hybrid GUID/MBR partition scheme support. +; +; This boot loader must be placed in the Master Boot Record. +; +; In order to coexist with a fdisk partition table (64 bytes), and +; leave room for a two byte signature (0xAA55) in the end, boot0 is +; restricted to 446 bytes (512 - 64 - 2). If boot0 did not have to +; live in the MBR, then we would have 510 bytes to work with. +; +; boot0 is always loaded by the BIOS or another booter to 0:7C00h. +; +; This code is written for the NASM assembler. +; nasm boot0.s -o boot0 +; +; Written by Tamás Kosárszky on 2008-03-10 and JrCs on 2013-05-08. +; With additions by Turbo for EFI System Partition boot support. +; + +; +; Set to 1 to enable obscure debug messages. +; +DEBUG EQU 0 + +; +; Set to 1 to enable verbose mode +; +VERBOSE EQU 0 + +; +; Various constants. +; +kBoot0Segment EQU 0x0000 +kBoot0Stack EQU 0xFFF0 ; boot0 stack pointer +kBoot0LoadAddr EQU 0x7C00 ; boot0 load address +kBoot1LoadAddr EQU 0xE000 ; boot1 load address + +kMBRBuffer EQU 0x1000 ; MBR buffer address +kLBA1Buffer EQU 0x1200 ; LBA1 - GPT Partition Table Header buffer address +kGPTABuffer EQU 0x1400 ; GUID Partition Entry Array buffer address + +kPartTableOffset EQU 0x1be +kMBRPartTable EQU kMBRBuffer + kPartTableOffset + +kSectorBytes EQU 512 ; sector size in bytes +kBootSignature EQU 0xAA55 ; boot sector signature +kFAT32BootCodeOffset EQU 0x5a ; offset of boot code in FAT32 boot sector +kBoot1FAT32Magic EQU 'BO' ; Magic string to detect our boot1f32 code + + +kGPTSignatureLow EQU 'EFI ' ; GUID Partition Table Header Signature +kGPTSignatureHigh EQU 'PART' +kGUIDLastDwordOffs EQU 12 ; last 4 byte offset of a GUID + +kPartCount EQU 4 ; number of paritions per table +kPartTypeFAT32 EQU 0x0c ; FAT32 Filesystem type +kPartTypePMBR EQU 0xee ; On all GUID Partition Table disks a Protective MBR (PMBR) + ; in LBA 0 (that is, the first block) precedes the + ; GUID Partition Table Header to maintain compatibility + ; with existing tools that do not understand GPT partition structures. + ; The Protective MBR has the same format as a legacy MBR + ; and contains one partition entry with an OSType set to 0xEE + ; reserving the entire space used on the disk by the GPT partitions, + ; including all headers. + +kPartActive EQU 0x80 ; active flag enabled +kPartInactive EQU 0x00 ; active flag disabled +kEFISystemGUID EQU 0x3BC93EC9 ; last 4 bytes of EFI System Partition Type GUID: + ; C12A7328-F81F-11D2-BA4B-00A0C93EC93B +kBasicDataGUID EQU 0xC79926B7 ; last 4 bytes of Basic Data System Partition Type GUID: + ; EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 + +; +; Format of fdisk partition entry. +; +; The symbol 'part_size' is automatically defined as an `EQU' +; giving the size of the structure. +; + struc part +.bootid resb 1 ; bootable or not +.head resb 1 ; starting head, sector, cylinder +.sect resb 1 ; +.cyl resb 1 ; +.type resb 1 ; partition type +.endhead resb 1 ; ending head, sector, cylinder +.endsect resb 1 ; +.endcyl resb 1 ; +.lba resd 1 ; starting lba +.sectors resd 1 ; size in sectors + endstruc + +; +; Format of GPT Partition Table Header +; + struc gpth +.Signature resb 8 +.Revision resb 4 +.HeaderSize resb 4 +.HeaderCRC32 resb 4 +.Reserved resb 4 +.MyLBA resb 8 +.AlternateLBA resb 8 +.FirstUsableLBA resb 8 +.LastUsableLBA resb 8 +.DiskGUID resb 16 +.PartitionEntryLBA resb 8 +.NumberOfPartitionEntries resb 4 +.SizeOfPartitionEntry resb 4 +.PartitionEntryArrayCRC32 resb 4 + endstruc + +; +; Format of GUID Partition Entry Array +; + struc gpta +.PartitionTypeGUID resb 16 +.UniquePartitionGUID resb 16 +.StartingLBA resb 8 +.EndingLBA resb 8 +.Attributes resb 8 +.PartitionName resb 72 + endstruc + +; +; Macros. +; +%macro DebugCharMacro 1 + mov al, %1 + call print_char +%endmacro + +%macro LogString 1 + mov di, %1 + call log_string +%endmacro + +%if DEBUG +%define DebugChar(x) DebugCharMacro x +%else +%define DebugChar(x) +%endif + +;-------------------------------------------------------------------------- +; Start of text segment. + + SEGMENT .text + + ORG kBoot0LoadAddr + +;-------------------------------------------------------------------------- +; Boot code is loaded at 0:7C00h. +; +start: + ; + ; Set up the stack to grow down from kBoot0Segment:kBoot0Stack. + ; Interrupts should be off while the stack is being manipulated. + ; + cli ; interrupts off + xor ax, ax ; zero ax + mov ss, ax ; ss <- 0 + mov sp, kBoot0Stack ; sp <- top of stack + sti ; reenable interrupts + + mov es, ax ; es <- 0 + mov ds, ax ; ds <- 0 + + DebugChar('>') + +%if DEBUG + mov al, dl + call print_hex +%endif + + ; + ; Since this code may not always reside in the MBR, always start by + ; loading the MBR to kMBRBuffer and LBA1 to kGPTBuffer. + ; + + xor eax, eax + mov [my_lba], eax ; store LBA sector 0 for read_lba function + mov al, 2 ; load two sectors: MBR and LBA1 + mov bx, kMBRBuffer ; MBR load address + call load + jc error ; MBR load error + + ; + ; Look for the booter partition in the MBR partition table, + ; which is at offset kMBRPartTable. + ; + mov si, kMBRPartTable ; pointer to partition table + call find_boot ; will not return on success + +error: + LogString(boot_error_str) + +hang: + hlt + jmp hang + + +;-------------------------------------------------------------------------- +; Find the active (boot) partition and load the booter from the partition. +; +; Arguments: +; DL = drive number (0x80 + unit number) +; SI = pointer to fdisk partition table. +; +; Clobber list: +; EAX, BX, EBP +; +find_boot: + + ; + ; Check for boot block signature 0xAA55 following the 4 partition + ; entries. + ; + cmp WORD [si + part_size * kPartCount], kBootSignature + jne .exit ; boot signature not found. + + xor bx, bx ; BL will be set to 1 later in case of + ; Protective MBR has been found + +.start_scan: + mov cx, kPartCount ; number of partition entries per table + +.loop: + + ; + ; First scan through the partition table looking for the active + ; partition. + ; +%if DEBUG + mov al, [si + part.type] ; print partition type + call print_hex +%endif + + mov eax, [si + part.lba] ; save starting LBA of current + mov [my_lba], eax ; MBR partition entry for read_lba function + cmp BYTE [si + part.type], 0 ; unused partition? + je .continue ; skip to next entry + cmp BYTE [si + part.type], kPartTypePMBR ; check for Protective MBR + jne .tryToBootIfActive + + mov BYTE [si + part.bootid], kPartInactive ; found Protective MBR + ; clear active flag to make sure this protective + ; partition won't be used as a bootable partition. + mov bl, 1 ; Assume we can deal with GPT but try to scan + ; later if not found any other bootable partitions. + +.tryToBootIfActive: + ; We're going to try to boot a partition if it is active + cmp BYTE [si + part.bootid], kPartActive + jne .continue + + ; + ; Found boot partition, read boot sector to memory. + ; + + xor dh, dh ; Argument for loadBootSector to skip file system signature check. + call loadBootSector + jne .continue + jmp SHORT initBootLoader + +.continue: + add si, BYTE part_size ; advance SI to next partition entry + loop .loop ; loop through all partition entries + + ; + ; Scanned all partitions but not found any with active flag enabled + ; Anyway if we found a protective MBR before we still have a chance + ; for a possible GPT Header at LBA 1 + ; + dec bl + jnz .exit ; didn't find Protective MBR before + call checkGPT + +.exit: + ret ; Giving up. + + + ; + ; Jump to partition booter. The drive number is already in register DL. + ; SI is pointing to the modified partition entry. + ; +initBootLoader: + +DebugChar('J') + +%if VERBOSE + LogString(done_str) +%endif + + jmp kBoot1LoadAddr + + ; + ; Found Protective MBR Partition Type: 0xEE + ; Check for 'EFI PART' string at the beginning + ; of LBA1 for possible GPT Table Header + ; +checkGPT: + push bx + + mov di, kLBA1Buffer ; address of GUID Partition Table Header + cmp DWORD [di], kGPTSignatureLow ; looking for 'EFI ' + jne .exit ; not found. Giving up. + cmp DWORD [di + 4], kGPTSignatureHigh ; looking for 'PART' + jne .exit ; not found. Giving up indeed. + mov si, di + + ; + ; Loading GUID Partition Table Array + ; + mov eax, [si + gpth.PartitionEntryLBA] ; starting LBA of GPT Array + mov [my_lba], eax ; save starting LBA for read_lba function + mov cx, [si + gpth.NumberOfPartitionEntries] ; number of GUID Partition Array entries + mov bx, [si + gpth.SizeOfPartitionEntry] ; size of GUID Partition Array entry + + push bx ; push size of GUID Partition entry + + ; + ; Current GPT Arrays uses 128 partition entries each 128 bytes long + ; 128 entries * 128 bytes long GPT Array entries / 512 bytes per sector = 32 sectors + ; + mov al, 32 ; maximum sector size of GPT Array (hardcoded method) + + mov bx, kGPTABuffer + push bx ; push address of GPT Array + call load ; read GPT Array + pop si ; SI = address of GPT Array + pop bx ; BX = size of GUID Partition Array entry + jc error + + ; + ; Walk through GUID Partition Table Array + ; and load boot record from first supported partition. + ; + ; If it has boot signature (0xAA55) then jump to it + ; otherwise skip to next partition. + ; + +%if VERBOSE + LogString(gpt_str) +%endif + +.gpt_loop: + + mov eax, [si + gpta.PartitionTypeGUID + kGUIDLastDwordOffs] + + ; + ; Try EFI System Partition + ; + cmp eax, kEFISystemGUID ; check current GUID Partition for EFI System Partition GUID type + je .gpt_ok + + ; + ; Also try FAT2 System Partition + ; + cmp eax, kBasicDataGUID ; check current GUID Partition for Basic Data Partition GUID type + jne .gpt_continue + +.gpt_ok: + ; + ; Found a possible good partition try to boot it + ; + + mov eax, [si + gpta.StartingLBA] ; load boot sector from StartingLBA + mov [my_lba], eax + mov dh, 1 ; Argument for loadBootSector to check file system signature. + call loadBootSector + jne .gpt_continue ; no boot loader signature + + mov si, kMBRPartTable ; fake the current GUID Partition + mov [si + part.lba], eax ; as MBR style partition for boot1f32, + mov BYTE [si + part.type], kPartTypeFAT32 ; set filesystem type for cosmetic reasons + jmp SHORT initBootLoader + +.gpt_continue: + + add si, bx ; advance SI to next partition entry + loop .gpt_loop ; loop through all partition entries + +.exit: + pop bx + ret ; no more GUID partitions. Giving up. + + +;-------------------------------------------------------------------------- +; loadBootSector - Load boot sector +; +; Arguments: +; DL = drive number (0x80 + unit number) +; DH = 0 skip file system signature checking +; 1 enable file system signature checking +; [my_lba] = starting LBA. +; +; Returns: +; ZF = 0 if boot sector hasn't kBootSignature +; 1 if boot sector has kBootSignature +; +loadBootSector: + pusha + + mov al, 3 + mov bx, kBoot1LoadAddr + call load + jc error + + or dh, dh + jz .checkBootSignature + +%if VERBOSE + LogString(test_str) +%endif + + ; + ; Looking for boot1f32 magic string. + ; + mov ax, [kBoot1LoadAddr + kFAT32BootCodeOffset] + cmp ax, kBoot1FAT32Magic + jne .exit + +.checkBootSignature: + ; + ; Check for boot block signature 0xAA55 + ; + cmp WORD [kBoot1LoadAddr + kSectorBytes - 2], kBootSignature + +.exit: + + popa + + ret + + +;-------------------------------------------------------------------------- +; load - Load one or more sectors from a partition. +; +; Arguments: +; AL = number of 512-byte sectors to read. +; ES:BX = pointer to where the sectors should be stored. +; DL = drive number (0x80 + unit number) +; [my_lba] = starting LBA. +; +; Returns: +; CF = 0 success +; 1 error +; +load: + push cx + +.ebios: + mov cx, 5 ; load retry count +.ebios_loop: + call read_lba ; use INT13/F42 + jnc .exit + loop .ebios_loop + +.exit: + pop cx + ret + + +;-------------------------------------------------------------------------- +; read_lba - Read sectors from a partition using LBA addressing. +; +; Arguments: +; AL = number of 512-byte sectors to read (valid from 1-127). +; ES:BX = pointer to where the sectors should be stored. +; DL = drive number (0x80 + unit number) +; [my_lba] = starting LBA. +; +; Returns: +; CF = 0 success +; 1 error +; +read_lba: + pushad ; save all registers + mov bp, sp ; save current SP + + ; + ; Create the Disk Address Packet structure for the + ; INT13/F42 (Extended Read Sectors) on the stack. + ; + +; push DWORD 0 ; offset 12, upper 32-bit LBA + push ds ; For sake of saving memory, + push ds ; push DS register, which is 0. + mov ecx, [my_lba] ; offset 8, lower 32-bit LBA + push ecx + push es ; offset 6, memory segment + push bx ; offset 4, memory offset + xor ah, ah ; offset 3, must be 0 + push ax ; offset 2, number of sectors + + ; It pushes 2 bytes with a smaller opcode than if WORD was used + push BYTE 16 ; offset 0-1, packet size + + DebugChar('<') +%if DEBUG + mov eax, ecx + call print_hex +%endif + + ; + ; INT13 Func 42 - Extended Read Sectors + ; + ; Arguments: + ; AH = 0x42 + ; DL = drive number (80h + drive unit) + ; DS:SI = pointer to Disk Address Packet + ; + ; Returns: + ; AH = return status (sucess is 0) + ; carry = 0 success + ; 1 error + ; + ; Packet offset 2 indicates the number of sectors read + ; successfully. + ; + mov si, sp + mov ah, 0x42 + int 0x13 + + jnc .exit + + DebugChar('R') ; indicate INT13/F42 error + + ; + ; Issue a disk reset on error. + ; Should this be changed to Func 0xD to skip the diskette controller + ; reset? + ; + xor ax, ax ; Func 0 + int 0x13 ; INT 13 + stc ; set carry to indicate error + +.exit: + mov sp, bp ; restore SP + popad + ret + + +;-------------------------------------------------------------------------- +; Write a string with 'boot0: ' prefix to the console. +; +; Arguments: +; ES:DI pointer to a NULL terminated string. +; +; Clobber list: +; DI +; +log_string: + pusha + + push di + mov si, log_title_str + call print_string + + pop si + call print_string + + popa + + ret + + +;-------------------------------------------------------------------------- +; Write a string to the console. +; +; Arguments: +; DS:SI pointer to a NULL terminated string. +; +; Clobber list: +; AX, BX, SI +; +print_string: + mov bx, 1 ; BH=0, BL=1 (blue) + cld ; increment SI after each lodsb call +.loop: + lodsb ; load a byte from DS:SI into AL + cmp al, 0 ; Is it a NULL? + je .exit ; yes, all done + mov ah, 0xE ; INT10 Func 0xE + int 0x10 ; display byte in tty mode + jmp short .loop +.exit: + ret + + +%if DEBUG + +;-------------------------------------------------------------------------- +; Write a ASCII character to the console. +; +; Arguments: +; AL = ASCII character. +; +print_char: + pusha + mov bx, 1 ; BH=0, BL=1 (blue) + mov ah, 0x0e ; bios INT 10, Function 0xE + int 0x10 ; display byte in tty mode + popa + ret + + +;-------------------------------------------------------------------------- +; Write the 4-byte value to the console in hex. +; +; Arguments: +; EAX = Value to be displayed in hex. +; +print_hex: + pushad + mov cx, WORD 4 + bswap eax +.loop: + push ax + ror al, 4 + call print_nibble ; display upper nibble + pop ax + call print_nibble ; display lower nibble + ror eax, 8 + loop .loop + + mov al, 10 ; carriage return + call print_char + mov al, 13 + call print_char + + popad + ret + +print_nibble: + and al, 0x0f + add al, '0' + cmp al, '9' + jna .print_ascii + add al, 'A' - '9' - 1 +.print_ascii: + call print_char + ret + +getc: + pusha + mov ah, 0 + int 0x16 + popa + ret +%endif ;DEBUG + + +;-------------------------------------------------------------------------- +; NULL terminated strings. +; + +%if VERBOSE +gpt_str db 'GPT', 0 +test_str db 'test', 0 +done_str db 'done', 0 +%endif + +boot_error_str db 'error', 0 + +;-------------------------------------------------------------------------- +; Pad the rest of the 512 byte sized booter with zeroes. The last +; two bytes is the mandatory boot sector signature. +; +; If the booter code becomes too large, then nasm will complain +; that the 'times' argument is negative. + +; +; According to EFI specification, maximum boot code size is 440 bytes +; + +pad_boot: + times 428-($-$$) db 0 ; 428 = 440 - len(log_title_str) + +log_title_str: + db 10, 13, 'boot0af: ', 0 ; can be use as signature + +pad_table_and_sig: + times 510-($-$$) db 0 + dw kBootSignature + + ABSOLUTE 0xE400 + +; +; In memory variables. +; +my_lba resd 1 ; Starting LBA for read_lba function + +; END diff --git a/Legacy/BootLoader/boot1f32.nasm b/Legacy/BootLoader/boot1f32.nasm new file mode 100644 index 0000000000000000000000000000000000000000..11b0bb625304b0ae9c3719f2746bb8a1125fcffe --- /dev/null +++ b/Legacy/BootLoader/boot1f32.nasm @@ -0,0 +1,604 @@ +; Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. +; +; @APPLE_LICENSE_HEADER_START@ +; +; Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights +; Reserved. This file contains Original Code and/or Modifications of +; Original Code as defined in and that are subject to the Apple Public +; Source License Version 2.0 (the "License"). You may not use this file +; except in compliance with the License. Please obtain a copy of the +; License at http://www.apple.com/publicsource and read it before using +; this file. +; +; The Original Code and all software distributed under the License are +; distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER +; EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +; INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the +; License for the specific language governing rights and limitations +; under the License. +; +; @APPLE_LICENSE_HEADER_END@ +; +; Partition Boot Loader: boot1f32 +; +; This program is designed to reside in sector 0 of a FAT32 partition. +; It expects that the MBR has left the drive number in DL +; and a pointer to the partition entry in SI. +; +; This version requires a BIOS with EBIOS (LBA) support. +; +; This code is written for the NASM assembler. +; nasm boot1f32.s -o boot1f32 +; +; dd if=origbs of=newbs skip=3 seek=3 bs=1 count=87 conv=notrunc +; + +; +; This version of boot1f32 tries to find a stage2 boot file in the root folder. +; +; Written by mackerintel on 2009-01-26 +; + +; +; Set to 1 to enable obscure debug messages. +; +DEBUG EQU 0 + +; +; Set to 1 to enable verbose mode. +; +VERBOSE EQU 0 + +; +; Various constants. +; +NULL EQU 0 +CR EQU 0x0D +LF EQU 0x0A + +maxSectorCount EQU 64 ; maximum sector count for readSectors +kSectorBytes EQU 512 ; sector size in bytes +kBootSignature EQU 0xAA55 ; boot sector signature + +kBoot1StackAddress EQU 0xFFF0 ; boot1 stack pointer +kBoot1LoadAddr EQU 0xE000 ; boot1 load address + +kBoot2Sectors EQU (480 * 1024 - 512) / kSectorBytes ; max size of 'boot' file in sectors +kBoot2Segment EQU 0x2000 ; boot2 load segment +kBoot2Address EQU kSectorBytes ; boot2 load address + +FATBUF EQU 0x7000 ; Just place for one sectors +DIRBUFSEG EQU 0x1000 ; Cluster sizes >64KB aren't supported + +; +; Format of fdisk partition entry. +; +; The symbol 'part_size' is automatically defined as an `EQU' +; giving the size of the structure. +; + struc part +.bootid resb 1 ; bootable or not +.head resb 1 ; starting head, sector, cylinder +.sect resb 1 ; +.cyl resb 1 ; +.type resb 1 ; partition type +.endhead resb 1 ; ending head, sector, cylinder +.endsect resb 1 ; +.endcyl resb 1 ; +.lba resd 1 ; starting lba +.sectors resd 1 ; size in sectors + endstruc + + struc direntry +.nameext resb 11 +.attr resb 1 +.nused1 resb 8 +.highclus resw 1 +.nused2 resb 4 +.lowclus resw 1 +.size resd 1 + endstruc + + +; +; Macros. +; +%macro jmpabs 1 + push WORD %1 + ret +%endmacro + +%macro DebugCharMacro 1 + pushad + mov al, %1 + call print_char + call getc + popad +%endmacro + +%macro PrintCharMacro 1 + pushad + mov al, %1 + call print_char + popad +%endmacro + +%macro PutCharMacro 1 + call print_char +%endmacro + +%macro PrintHexMacro 1 + call print_hex +%endmacro + +%macro PrintString 1 + mov si, %1 + call print_string +%endmacro + +%macro LogString 1 + mov di, %1 + call log_string +%endmacro + +%if DEBUG + %define DebugChar(x) DebugCharMacro x + %define PrintChar(x) PrintCharMacro x + %define PutChar(x) PutCharMacro + %define PrintHex(x) PrintHexMacro x +%else + %define DebugChar(x) + %define PrintChar(x) + %define PutChar(x) + %define PrintHex(x) +%endif + +;-------------------------------------------------------------------------- +; Start of text segment. + + SEGMENT .text + + ORG kBoot1LoadAddr + + jmp start + times 3-($-$$) nop + +gOEMName times 8 db 0 ;OEMNAME +gBPS dw 0 +gSPC db 0 +gReservedSectors dw 0 +gNumFats db 0 +gCrap1 times 11 db 0 +gPartLBA dd 0 +gPartSize dd 0 +gSectPerFat dd 0 +gCrap2 times 4 db 0 +gRootCluster dd 0 +gCrap3 times 16 db 0 + +gBIOSDriveNumber db 0 +gExtInfo times 25 db 0 +gFileName db "BOOT " ; Used as a magic string in boot0 + +;-------------------------------------------------------------------------- +; Boot code is loaded at 0:E000h. +; +start: + ; + ; set up the stack to grow down from kBoot1StackSegment:kBoot1StackAddress. + ; Interrupts should be off while the stack is being manipulated. + ; + cli ; interrupts off + xor eax, eax ; zero ax + mov ss, ax ; ss <- 0 + mov sp, kBoot1StackAddress ; sp <- top of stack + sti ; reenable interrupts + + mov ds, ax ; ds <- 0 + mov es, ax ; es <- 0 + + ; + ; Initializing global variables. + ; + mov ax, word [gReservedSectors] + add eax, [si + part.lba] + mov [gPartLBA], eax ; save the current FAT LBA offset + mov [gBIOSDriveNumber], dl ; save BIOS drive number + xor eax,eax + mov al, [gNumFats] + mul dword [gSectPerFat] + mov [gSectPerFat], eax + +;-------------------------------------------------------------------------- +; Find stage2 boot file in a FAT32 Volume's root folder. +; +findRootBoot: + +%if VERBOSE + LogString(init_str) +%endif + + mov eax, [gRootCluster] + +nextdirclus: + mov edx, DIRBUFSEG<<4 + call readCluster + jc error + xor si, si + mov bl, [gSPC] + shl bx, 9 + add bx, si + +nextdirent: + mov di, gFileName + push ds + push DIRBUFSEG + pop ds + mov cl, [si] + test cl, cl + jz dserror + mov cx, 11 + repe cmpsb + jz direntfound + +falsealert: + pop ds + add cl, 21 + add si, cx + cmp si, bx + jz nextdirclus + jmp nextdirent + +direntfound: + lodsb + test al, 0x18 + jnz falsealert + push WORD [si + direntry.highclus - 12] + push WORD [si + direntry.lowclus - 12] + pop eax + pop ds + mov edx, (kBoot2Segment << 4) + kBoot2Address + +cont_read: + push edx + call readCluster + pop edx + pushf + xor ebx,ebx + mov bl, [gSPC] + shl ebx, 9 + add edx, ebx + popf + jnc cont_read + +boot2: + +%if DEBUG + DebugChar ('!') +%endif + + mov dl, [gBIOSDriveNumber] ; load BIOS drive number + jmp kBoot2Segment:kBoot2Address + +dserror: + pop ds + +error: + +%if VERBOSE + LogString(error_str) +%endif + +hang: + hlt + jmp hang + + ; readCluster - Reads cluster EAX to (EDX), updates EAX to next cluster +readCluster: + cmp eax, 0x0ffffff8 + jb do_read + stc + ret + +do_read: + push eax + xor ecx,ecx + dec eax + dec eax + mov cl, [gSPC] + push edx + mul ecx + pop edx + add eax, [gSectPerFat] + mov ecx, eax + xor ah,ah + mov al, [gSPC] + call readSectors + jc clusend + pop ecx + push cx + shr ecx, 7 + xor ax, ax + inc ax + mov edx, FATBUF + call readSectors + jc clusend + pop si + and si, 0x7f + shl si, 2 + mov eax, [FATBUF + si] + and eax, 0x0fffffff + clc + ret + +clusend: + pop eax + ret + +;-------------------------------------------------------------------------- +; readSectors - Reads more than 127 sectors using LBA addressing. +; +; Arguments: +; AX = number of 512-byte sectors to read (valid from 1-1280). +; EDX = pointer to where the sectors should be stored. +; ECX = sector offset in partition +; +; Returns: +; CF = 0 success +; 1 error +; +readSectors: + pushad + mov bx, ax + +.loop: + xor eax, eax ; EAX = 0 + mov al, bl ; assume we reached the last block. + cmp bx, maxSectorCount ; check if we really reached the last block + jb .readBlock ; yes, BX < MaxSectorCount + mov al, maxSectorCount ; no, read MaxSectorCount + +.readBlock: + call readLBA + sub bx, ax ; decrease remaning sectors with the read amount + jz .exit ; exit if no more sectors left to be loaded + add ecx, eax ; adjust LBA sector offset + shl ax, 9 ; convert sectors to bytes + add edx, eax ; adjust target memory location + jmp .loop ; read remaining sectors + +.exit: + popad + ret + +;-------------------------------------------------------------------------- +; readLBA - Read sectors from a partition using LBA addressing. +; +; Arguments: +; AL = number of 512-byte sectors to read (valid from 1-127). +; EDX = pointer to where the sectors should be stored. +; ECX = sector offset in partition +; [bios_drive_number] = drive number (0x80 + unit number) +; +; Returns: +; CF = 0 success +; 1 error +; +readLBA: + pushad ; save all registers + push es ; save ES + mov bp, sp ; save current SP + + ; + ; Convert EDX to segment:offset model and set ES:BX + ; + ; Some BIOSes do not like offset to be negative while reading + ; from hard drives. This usually leads to "boot1: error" when trying + ; to boot from hard drive, while booting normally from USB flash. + ; The routines, responsible for this are apparently different. + ; Thus we split linear address slightly differently for these + ; capricious BIOSes to make sure offset is always positive. + ; + + mov bx, dx ; save offset to BX + and bh, 0x0f ; keep low 12 bits + shr edx, 4 ; adjust linear address to segment base + xor dl, dl ; mask low 8 bits + mov es, dx ; save segment to ES + + ; + ; Create the Disk Address Packet structure for the + ; INT13/F42 (Extended Read Sectors) on the stack. + ; + + ; push DWORD 0 ; offset 12, upper 32-bit LBA + push ds ; For sake of saving memory, + push ds ; push DS register, which is 0. + + add ecx, [gPartLBA] ; offset 8, lower 32-bit LBA + push ecx + + push es ; offset 6, memory segment + + push bx ; offset 4, memory offset + + xor ah, ah ; offset 3, must be 0 + push ax ; offset 2, number of sectors + + push WORD 16 ; offset 0-1, packet size + + ; + ; INT13 Func 42 - Extended Read Sectors + ; + ; Arguments: + ; AH = 0x42 + ; [bios_drive_number] = drive number (0x80 + unit number) + ; DS:SI = pointer to Disk Address Packet + ; + ; Returns: + ; AH = return status (sucess is 0) + ; carry = 0 success + ; 1 error + ; + ; Packet offset 2 indicates the number of sectors read + ; successfully. + ; + mov dl, [gBIOSDriveNumber] ; load BIOS drive number + mov si, sp + mov ah, 0x42 + int 0x13 + + jc error + + ; + ; Issue a disk reset on error. + ; Should this be changed to Func 0xD to skip the diskette controller + ; reset? + ; +; xor ax, ax ; Func 0 +; int 0x13 ; INT 13 +; stc ; set carry to indicate error + +.exit: + mov sp, bp ; restore SP + pop es ; restore ES + popad + ret + +%if VERBOSE + +;-------------------------------------------------------------------------- +; Write a string with 'boot1: ' prefix to the console. +; +; Arguments: +; ES:DI pointer to a NULL terminated string. +; +; Clobber list: +; DI +; +log_string: + pushad + + push di + mov si, log_title_str + call print_string + + pop si + call print_string + + popad + + ret + +;------------------------------------------------------------------------- +; Write a string to the console. +; +; Arguments: +; DS:SI pointer to a NULL terminated string. +; +; Clobber list: +; AX, BX, SI +; +print_string: + mov bx, 1 ; BH=0, BL=1 (blue) + +.loop: + lodsb ; load a byte from DS:SI into AL + cmp al, 0 ; Is it a NULL? + je .exit ; yes, all done + mov ah, 0xE ; INT10 Func 0xE + int 0x10 ; display byte in tty mode + jmp .loop + +.exit: + ret + +%endif ; VERBOSE + +%if DEBUG + +;-------------------------------------------------------------------------- +; Write the 4-byte value to the console in hex. +; +; Arguments: +; EAX = Value to be displayed in hex. +; +print_hex: + pushad + mov cx, WORD 4 + bswap eax +.loop: + push ax + ror al, 4 + call print_nibble ; display upper nibble + pop ax + call print_nibble ; display lower nibble + ror eax, 8 + loop .loop + + popad + ret + +print_nibble: + and al, 0x0f + add al, '0' + cmp al, '9' + jna .print_ascii + add al, 'A' - '9' - 1 +.print_ascii: + call print_char + ret + +;-------------------------------------------------------------------------- +; getc - wait for a key press +; +getc: + pushad + mov ah, 0 + int 0x16 + popad + ret + +;-------------------------------------------------------------------------- +; Write a ASCII character to the console. +; +; Arguments: +; AL = ASCII character. +; +print_char: + pushad + mov bx, 1 ; BH=0, BL=1 (blue) + mov ah, 0x0e ; bios INT 10, Function 0xE + int 0x10 ; display byte in tty mode + popad + ret + +%endif ; DEBUG + +;-------------------------------------------------------------------------- +; Static data. +; + +%if VERBOSE +log_title_str db CR, LF, 'b1f: ', NULL +init_str db 'init', NULL +error_str db 'error', NULL +%endif + +;-------------------------------------------------------------------------- +; Pad the rest of the 512 byte sized sector with zeroes. The last +; two bytes is the mandatory boot sector signature. +; +; If the booter code becomes too large, then nasm will complain +; that the 'times' argument is negative. + +pad_table_and_sig: + times 496-($-$$) db 0 + ; We will put volume magic identifier here + times 14 db 0 + dw kBootSignature + + ABSOLUTE kBoot1LoadAddr + kSectorBytes + +; END diff --git a/Legacy/BootPlatform/AcpiResetDxe/Reset.c b/Legacy/BootPlatform/AcpiResetDxe/Reset.c new file mode 100644 index 0000000000000000000000000000000000000000..ab105b4f5468c331f5d5163f5356ec9bc13e6815 --- /dev/null +++ b/Legacy/BootPlatform/AcpiResetDxe/Reset.c @@ -0,0 +1,212 @@ +/*++ @file + Reset Architectural Protocol implementation. + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +--*/ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +/// +/// Handle for the Reset Architectural Protocol +/// +EFI_HANDLE mResetHandle = NULL; + +/// +/// Copy of ACPI Description HOB in runtime memory +/// +EFI_ACPI_DESCRIPTION mAcpiDescription; + +/** + Reset the system. + + @param[in] ResetType Warm or cold + @param[in] ResetStatus Possible cause of reset + @param[in] DataSize Size of ResetData in bytes + @param[in] ResetData Optional Unicode string + +**/ +VOID +EFIAPI +EfiAcpiResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ) +{ + UINT8 Dev; + UINT8 Func; + UINT8 Register; + + switch (ResetType) { + case EfiResetShutdown: + // + // 1. Write SLP_TYPa + // + if ((mAcpiDescription.PM1a_CNT_BLK.Address != 0) && (mAcpiDescription.SLP_TYPa != 0)) { + switch (mAcpiDescription.PM1a_CNT_BLK.AddressSpaceId) { + case EFI_ACPI_3_0_SYSTEM_IO: + IoAndThenOr16 ((UINTN)mAcpiDescription.PM1a_CNT_BLK.Address, 0xc3ff, (UINT16)(0x2000 | (mAcpiDescription.SLP_TYPa << 10))); + break; + case EFI_ACPI_3_0_SYSTEM_MEMORY: + MmioAndThenOr16 ((UINTN)mAcpiDescription.PM1a_CNT_BLK.Address, 0xc3ff, (UINT16)(0x2000 | (mAcpiDescription.SLP_TYPa << 10))); + break; + } + } + + // + // 2. Write SLP_TYPb + // + if ((mAcpiDescription.PM1b_CNT_BLK.Address != 0) && (mAcpiDescription.SLP_TYPb != 0)) { + switch (mAcpiDescription.PM1b_CNT_BLK.AddressSpaceId) { + case EFI_ACPI_3_0_SYSTEM_IO: + IoAndThenOr16 ((UINTN)mAcpiDescription.PM1b_CNT_BLK.Address, 0xc3ff, (UINT16)(0x2000 | (mAcpiDescription.SLP_TYPb << 10))); + break; + case EFI_ACPI_3_0_SYSTEM_MEMORY: + MmioAndThenOr16 ((UINTN)mAcpiDescription.PM1b_CNT_BLK.Address, 0xc3ff, (UINT16)(0x2000 | (mAcpiDescription.SLP_TYPb << 10))); + break; + } + } + // + // If Shutdown fails, then let fall through to reset + // + case EfiResetWarm: + case EfiResetCold: + if ((mAcpiDescription.RESET_REG.Address != 0) && + ((mAcpiDescription.RESET_REG.AddressSpaceId == EFI_ACPI_3_0_SYSTEM_IO) || + (mAcpiDescription.RESET_REG.AddressSpaceId == EFI_ACPI_3_0_SYSTEM_MEMORY) || + (mAcpiDescription.RESET_REG.AddressSpaceId == EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE))) { + // + // Use ACPI System Reset + // + switch (mAcpiDescription.RESET_REG.AddressSpaceId) { + case EFI_ACPI_3_0_SYSTEM_IO: + // + // Send reset request through I/O port register + // + IoWrite8 ((UINTN)mAcpiDescription.RESET_REG.Address, mAcpiDescription.RESET_VALUE); + // + // Halt + // + CpuDeadLoop (); + case EFI_ACPI_3_0_SYSTEM_MEMORY: + // + // Send reset request through MMIO register + // + MmioWrite8 ((UINTN)mAcpiDescription.RESET_REG.Address, mAcpiDescription.RESET_VALUE); + // + // Halt + // + CpuDeadLoop (); + case EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE: + // + // Send reset request through PCI register + // + Register = (UINT8)mAcpiDescription.RESET_REG.Address; + Func = (UINT8) (RShiftU64 (mAcpiDescription.RESET_REG.Address, 16) & 0x7); + Dev = (UINT8) (RShiftU64 (mAcpiDescription.RESET_REG.Address, 32) & 0x1F); + PciWrite8 (PCI_LIB_ADDRESS (0, Dev, Func, Register), mAcpiDescription.RESET_VALUE); + // + // Halt + // + CpuDeadLoop (); + } + } + + // + // If system comes here, means ACPI reset is not supported, so do Legacy System Reset, assume 8042 available + // + IoWrite8 (0x64, 0xfe); + CpuDeadLoop (); + + default: + break; + } + + // + // Given we should have reset getting here would be bad + // + ASSERT (FALSE); + CpuDeadLoop(); +} + +/** + Initialize the state information for the Reset Architectural Protocol. + + @param[in] ImageHandle Image handle of the loaded driver + @param[in] SystemTable Pointer to the System Table + + @retval EFI_SUCCESS Thread can be successfully created + @retval EFI_UNSUPPORTED Cannot find the info to reset system + +**/ +EFI_STATUS +EFIAPI +InitializeReset ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HOB_GUID_TYPE *HobAcpiDescription; + + // + // Make sure the Reset Architectural Protocol is not already installed in the system + // + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiResetArchProtocolGuid); + + // + // Get ACPI Description HOB + // + HobAcpiDescription = GetFirstGuidHob (&gEfiAcpiDescriptionGuid); + if (HobAcpiDescription == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Copy it to Runtime Memory + // + ASSERT (sizeof (EFI_ACPI_DESCRIPTION) == GET_GUID_HOB_DATA_SIZE (HobAcpiDescription)); + CopyMem (&mAcpiDescription, GET_GUID_HOB_DATA (HobAcpiDescription), sizeof (EFI_ACPI_DESCRIPTION)); + + DEBUG ((DEBUG_INFO, "ACPI Reset Base - %lx\n", mAcpiDescription.RESET_REG.Address)); + DEBUG ((DEBUG_INFO, "ACPI Reset Value - %02x\n", (UINTN)mAcpiDescription.RESET_VALUE)); + DEBUG ((DEBUG_INFO, "IAPC support - %x\n", (UINTN)(mAcpiDescription.IAPC_BOOT_ARCH))); + + // + // Hook the runtime service table + // + SystemTable->RuntimeServices->ResetSystem = EfiAcpiResetSystem; + + // + // Install the Reset Architectural Protocol onto a new handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mResetHandle, + &gEfiResetArchProtocolGuid, NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Legacy/BootPlatform/AcpiResetDxe/Reset.inf b/Legacy/BootPlatform/AcpiResetDxe/Reset.inf new file mode 100644 index 0000000000000000000000000000000000000000..a515ccce2fae5ee95c18b77d8bb3c7ca14aabd9e --- /dev/null +++ b/Legacy/BootPlatform/AcpiResetDxe/Reset.inf @@ -0,0 +1,47 @@ +## @file +# Component description file for AcpiResetDxe module. +# +# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AcpiReset + FILE_GUID = 928EF6D4-72BC-4686-B57B-1EEB6ABD4F93 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InitializeReset + +[Packages] + MdePkg/MdePkg.dec + OpenCorePkg/OpenDuetPkg.dec + +[LibraryClasses] + DebugLib + UefiBootServicesTableLib + UefiDriverEntryPoint + IoLib + PciLib + HobLib + BaseLib + BaseMemoryLib + +[Sources] + Reset.c + +[Protocols] + gEfiResetArchProtocolGuid + +[Guids] + gEfiAcpiDescriptionGuid + +[Depex] + TRUE diff --git a/Legacy/BootPlatform/BdsDxe/Bds.h b/Legacy/BootPlatform/BdsDxe/Bds.h new file mode 100644 index 0000000000000000000000000000000000000000..9261f14fb3045cdb3ae46f2a2728c0e43b9602b9 --- /dev/null +++ b/Legacy/BootPlatform/BdsDxe/Bds.h @@ -0,0 +1,53 @@ +/** @file + Head file for BDS Architectural Protocol implementation + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _BDS_MODULE_H_ +#define _BDS_MODULE_H_ + +#include + +/** + + Install Boot Device Selection Protocol + + @param ImageHandle The image handle. + @param SystemTable The system table. + + @retval EFI_SUCEESS BDS has finished initializing. + Return the dispatcher and recall BDS.Entry + @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface + +**/ +EFI_STATUS +EFIAPI +BdsInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + + Service routine for BdsInstance->Entry(). Devices are connected, the + consoles are initialized, and the boot options are tried. + + @param This Protocol Instance structure. + +**/ +VOID +EFIAPI +BdsEntry ( + IN EFI_BDS_ARCH_PROTOCOL *This + ); + +#endif diff --git a/Legacy/BootPlatform/BdsDxe/BdsDxe.inf b/Legacy/BootPlatform/BdsDxe/BdsDxe.inf new file mode 100644 index 0000000000000000000000000000000000000000..d10c16190688f347464a7abf0df8dc31eabcaa54 --- /dev/null +++ b/Legacy/BootPlatform/BdsDxe/BdsDxe.inf @@ -0,0 +1,86 @@ +## @file +# +# BDSDxe module is core driver for BDS phase. +# When DxeCore dispatching all DXE driver, this module will produce architecture protocol +# gEfiBdsArchProtocolGuid. After DxeCore finish dispatching, DxeCore will invoke Entry +# interface of protocol gEfiBdsArchProtocolGuid, then BDS phase is entered. +# +# Generally, this module take reposiblity to connect all necessary devices for platform boot, +# these boot device path are hold in PlatformBdsLib library instance produced by platform. +# For legacy boot, BDS will transfer control to legacy BIOS after legacy boot device is select. +# For EFI boot, BDS will load boot loader file EFI\BOOT\BOOTIA32.EFI, EFI\BOOT\BOOTX64.EFI, +# EFI\BOOT\BOOTIA64.EFI file from selected boot device and transfer control to boot loader. +# +# BDSDxe also maintain the UI for "Boot Manager, Boot Maintaince Manager, Device Manager" which +# is used for user to configure boot option or maintain hardware device. +# +# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BdsDxe + MODULE_UNI_FILE = BdsDxe.uni + FILE_GUID = FC5C7020-1A48-4198-9BE2-EAD5ABC8CF2F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = BdsInitialize + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + Bds.h + BdsEntry.c + +[Packages] + OpenCorePkg/OpenDuetPkg.dec + OpenCorePkg/OpenCorePkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + DuetBdsLib + MemoryAllocationLib + PcdLib + PrintLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + UefiRuntimeServicesTableLib + +[Guids] + gEfiEndOfDxeEventGroupGuid + +[Protocols] + gEfiSimpleFileSystemProtocolGuid ## PROTOCOL CONSUMES + gEfiCpuArchProtocolGuid + gEdkiiVariableLockProtocolGuid ## PROTOCOL CONSUMES + gEfiBdsArchProtocolGuid ## PROTOCOL PRODUCES + gEfiCapsuleArchProtocolGuid ## PROTOCOL PRODUCES + gEfiBlockIoProtocolGuid + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision ## CONSUMES + +[Depex] + TRUE diff --git a/Legacy/BootPlatform/BdsDxe/BdsDxe.uni b/Legacy/BootPlatform/BdsDxe/BdsDxe.uni new file mode 100644 index 0000000000000000000000000000000000000000..b0ff98b32e44f254f5b4b6eeb1ea6f5700dfaa90 --- /dev/null +++ b/Legacy/BootPlatform/BdsDxe/BdsDxe.uni @@ -0,0 +1,33 @@ +// /** @file +// BDSDxe module is core driver for BDS phase. +// +// When DxeCore dispatching all DXE driver, this module will produce architecture protocol +// gEfiBdsArchProtocolGuid. After DxeCore finish dispatching, DxeCore will invoke Entry +// interface of protocol gEfiBdsArchProtocolGuid, then BDS phase is entered. +// +// Generally, this module take reposiblity to connect all necessary devices for platform boot, +// these boot device path are hold in PlatformBdsLib library instance produced by platform. +// For legacy boot, BDS will transfer control to legacy BIOS after legacy boot device is select. +// For EFI boot, BDS will load boot loader file EFI\BOOT\BOOTIA32.EFI, EFI\BOOT\BOOTX64.EFI, +// EFI\BOOT\BOOTIA64.EFI file from selected boot device and transfer control to boot loader. +// +// BDSDxe also maintain the UI for "Boot Manager, Boot Maintaince Manager, Device Manager" which +// is used for user to configure boot option or maintain hardware device. +// +// Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "BDSDxe module is core driver for BDS phase" + +#string STR_MODULE_DESCRIPTION #language en-US "When DxeCore dispatching all DXE driver, this module will produce architecture protocol gEfiBdsArchProtocolGuid. After DxeCore finishes dispatching, DxeCore will invoke the Entry interface of protocol gEfiBdsArchProtocolGuid. Then BDS phase is entered. Generally, this module takes reposiblity to connect all necessary devices for platform boot. These boot device paths are held in PlatformBdsLib a library instance produced by the platform. For legacy boot, BDS will transfer control to legacy BIOS after legacy boot device is selected. For EFI boot, BDS will load boot loader file EFI\BOOT\BOOTIA32.EFI, EFI\BOOT\BOOTX64.EFI, EFI\BOOT\BOOTIA64.EFI files from selected boot devices, and transfers control to the boot loader. BDSDxe also maintains the UI for \"Boot Manager, Boot Maintaince Manager, Device Manager\", which is used by the user to configure boot options or to maintain hardware devices." + diff --git a/Legacy/BootPlatform/BdsDxe/BdsEntry.c b/Legacy/BootPlatform/BdsDxe/BdsEntry.c new file mode 100644 index 0000000000000000000000000000000000000000..800a3e6b863b17249525f3f1bef8aefd14b58529 --- /dev/null +++ b/Legacy/BootPlatform/BdsDxe/BdsEntry.c @@ -0,0 +1,490 @@ +/** @file + This module produce main entry for BDS phase - BdsEntry. + When this module was dispatched by DxeCore, gEfiBdsArchProtocolGuid will be installed + which contains interface of BdsEntry. + After DxeCore finish DXE phase, gEfiBdsArchProtocolGuid->BdsEntry will be invoked + to enter BDS phase. + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Bds.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/// +/// BDS arch protocol instance initial value. +/// +EFI_HANDLE gBdsHandle = NULL; + +EFI_BDS_ARCH_PROTOCOL gBds = { + BdsEntry +}; + +/// +/// The read-only variables defined in UEFI Spec. +/// +CHAR16 *mReadOnlyVariables[] = { + L"PlatformLangCodes", + L"LangCodes", + L"BootOptionSupport", + L"HwErrRecSupport", + L"OsIndicationsSupported" + }; + +/** + + Install Boot Device Selection Protocol + + @param ImageHandle The image handle. + @param SystemTable The system table. + + @retval EFI_SUCEESS BDS has finished initializing. + Return the dispatcher and recall BDS.Entry + @retval Other Return status from AllocatePool() or gBS->InstallProtocolInterface + +**/ +EFI_STATUS +EFIAPI +BdsInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + VOID *ReturnUnsupported; + +#ifdef MDE_CPU_X64 + STATIC UINT8 mReturnUnsupported[] = {0x48, 0xB8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC3}; +#else + STATIC UINT8 mReturnUnsupported[] = {0xB8, 0x03, 0x00, 0x00, 0x80, 0xC3}; +#endif + + // + // Provide dummy functions + // + Status = gBS->AllocatePool (EfiRuntimeServicesCode, sizeof (mReturnUnsupported), (VOID **) &ReturnUnsupported); + ASSERT_EFI_ERROR (Status); + CopyMem (ReturnUnsupported, mReturnUnsupported, sizeof (mReturnUnsupported)); + gRT->UpdateCapsule = (EFI_UPDATE_CAPSULE) ReturnUnsupported; + gRT->QueryCapsuleCapabilities = (EFI_QUERY_CAPSULE_CAPABILITIES) ReturnUnsupported; + + // + // Install protocol interface + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &gBdsHandle, + &gEfiBdsArchProtocolGuid, &gBds, + &gEfiCapsuleArchProtocolGuid, NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +STATIC +EFI_STATUS +BdsCheckSignature ( + IN EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + volatile BOOT1_LOADER *SelfSignature; + BOOT1_LOADER *DiskSignature; + UINTN DiskSignatureSize; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + UINTN Index; + UINT8 NonZero; + + SelfSignature = (volatile BOOT1_LOADER *) (BOOT1_BASE); + + if (SelfSignature->Magic != BOOT1_MAGIC) { + return EFI_UNSUPPORTED; + } + + Status = gBS->HandleProtocol ( + Handle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + DiskSignatureSize = ALIGN_VALUE ( + MAX (sizeof (*DiskSignature), BlockIo->Media->BlockSize), + BlockIo->Media->BlockSize + ); + DiskSignature = AllocatePool (DiskSignatureSize); + + if (DiskSignature == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = BlockIo->ReadBlocks ( + BlockIo, + BlockIo->Media->MediaId, + 0, + DiskSignatureSize, + DiskSignature + ); + + if (!EFI_ERROR (Status) && DiskSignature->Magic == SelfSignature->Magic) { + NonZero = 0; + + for (Index = 0; Index < sizeof (SelfSignature->Signature); ++Index) { + if (SelfSignature->Signature[Index] != DiskSignature->Signature[Index]) { + Status = EFI_NOT_FOUND; + break; + } + NonZero |= SelfSignature->Signature[Index]; + } + + if (NonZero == 0) { + Status = EFI_NOT_FOUND; + } + } else { + Status = EFI_UNSUPPORTED; + } + + FreePool (DiskSignature); + + return Status; +} + +/** + + This function attempts to boot for the boot order specified + by platform policy. + +**/ +STATIC +VOID +BdsBootDeviceSelect ( + IN BOOLEAN RequireValidDisk + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_HANDLE *FileSystemHandles; + UINTN NumberFileSystemHandles; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_HANDLE ImageHandle; + + // + // Signal the EVT_SIGNAL_READY_TO_BOOT event + // + EfiSignalEventReadyToBoot (); + + // + // If there is simple file protocol which does not consume block Io protocol, create a boot option for it here. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &NumberFileSystemHandles, + &FileSystemHandles + ); + + if (EFI_ERROR (Status)) { + return; + } + + for (Index = 0; Index < NumberFileSystemHandles; Index++) { + // + // Check matching volume DuetPkg was booted from. + // + if (RequireValidDisk) { + Status = BdsCheckSignature (FileSystemHandles[Index]); + if (EFI_ERROR (Status)) { + continue; + } + } + + // + // Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI + // machinename is ia32, ia64, x64, ... + // + DevicePath = FileDevicePath ( + FileSystemHandles[Index], + L"\\EFI\\OC\\OpenCore.efi" + ); + + if (DevicePath == NULL) { + continue; + } + + ImageHandle = NULL; + Status = gBS->LoadImage ( + TRUE, + gImageHandle, + DevicePath, + NULL, + 0, + &ImageHandle + ); + + if (!EFI_ERROR (Status)) { + gBS->StartImage ( + ImageHandle, + 0, + NULL + ); + } + + FreePool (DevicePath); + } + + if (NumberFileSystemHandles != 0) { + FreePool (FileSystemHandles); + } +} + +/** + + Validate input console variable data. + + If found the device path is not a valid device path, remove the variable. + + @param VariableName Input console variable name. + +**/ +STATIC +VOID +BdsFormalizeConsoleVariable ( + IN CHAR16 *VariableName + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN VariableSize; + + DevicePath = BdsLibGetVariableAndSize ( + VariableName, + &gEfiGlobalVariableGuid, + &VariableSize + ); + if ((DevicePath != NULL) && !IsDevicePathValid (DevicePath, VariableSize)) { + Status = gRT->SetVariable ( + VariableName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + NULL + ); + ASSERT_EFI_ERROR (Status); + } +} + +/** + + Formalize Bds global variables. + + 1. For ConIn/ConOut/ConErr, if found the device path is not a valid device path, remove the variable. + 2. For OsIndicationsSupported, Create a BS/RT/UINT64 variable to report caps + 3. Delete OsIndications variable if it is not NV/BS/RT UINT64 + Item 3 is used to solve case when OS corrupts OsIndications. Here simply delete this NV variable. + +**/ +STATIC +VOID +BdsFormalizeEfiGlobalVariable ( + VOID + ) +{ + UINT64 OsIndicationSupport; + + // + // Validate Console variable. + // + BdsFormalizeConsoleVariable (L"ConIn"); + BdsFormalizeConsoleVariable (L"ConOut"); + BdsFormalizeConsoleVariable (L"ErrOut"); + + // + // OS indicater support variable + // + OsIndicationSupport = EFI_OS_INDICATIONS_BOOT_TO_FW_UI \ + | EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED; + + gRT->SetVariable ( + L"OsIndicationsSupported", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(UINT64), + &OsIndicationSupport + ); + +} + +/** + Set language related EFI Variables. + +**/ +STATIC +VOID +InitializeLanguage ( + VOID + ) +{ + CHAR8 *PlatformLangCodes; + CHAR8 *PlatformLang; + + PlatformLangCodes = (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes); + PlatformLang = (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang); + + gRT->SetVariable ( + L"PlatformLangCodes", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + AsciiStrSize (PlatformLangCodes), + PlatformLangCodes + ); + + + gRT->SetVariable ( + L"PlatformLang", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + AsciiStrSize (PlatformLang), + PlatformLang + ); +} + +/** + + Service routine for BdsInstance->Entry(). Devices are connected, the + consoles are initialized, and the boot options are tried. + + @param This Protocol Instance structure. + +**/ +VOID +EFIAPI +BdsEntry ( + IN EFI_BDS_ARCH_PROTOCOL *This + ) +{ + CHAR16 *FirmwareVendor; + EFI_STATUS Status; + UINT16 BootTimeOut; + UINTN Index; + EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; + + // + // Fill in FirmwareVendor and FirmwareRevision from PCDs + // + FirmwareVendor = (CHAR16 *) PcdGetPtr (PcdFirmwareVendor); + gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor); + ASSERT (gST->FirmwareVendor != NULL); + gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision); + + // + // Fixup Table CRC after we updated Firmware Vendor and Revision + // + gST->Hdr.CRC32 = 0; + gBS->CalculateCrc32 (gST, sizeof (EFI_SYSTEM_TABLE), &gST->Hdr.CRC32); + + // + // Validate Variable. + // TODO: Explore. + // + BdsFormalizeEfiGlobalVariable (); + + // + // Mark the read-only variables if the Variable Lock protocol exists + // + Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock); + DEBUG ((EFI_D_INFO, "[BdsDxe] Locate Variable Lock protocol - %r\n", Status)); + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < sizeof (mReadOnlyVariables) / sizeof (mReadOnlyVariables[0]); Index++) { + Status = VariableLock->RequestToLock (VariableLock, mReadOnlyVariables[Index], &gEfiGlobalVariableGuid); + ASSERT_EFI_ERROR (Status); + } + } + + // + // Initialize L"Timeout" EFI global variable. + // + BootTimeOut = 0; + gRT->SetVariable ( + L"Timeout", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (UINT16), + &BootTimeOut + ); + + // + // Platform specific code + // Initialize the platform specific string and language + // + InitializeLanguage (); + + // + // Do the platform init, can be customized by OEM/IBV + // + PlatformBdsInit (); + + // + // Signal EndOfDxe + // + EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid); + + // + // Setup some platform policy here + // + PlatformBdsPolicyBehavior (); + + // + // BDS select the boot device to load OS + // + BdsBootDeviceSelect (TRUE); + + // + // Try to boot any volume + // + gST->ConOut->OutputString (gST->ConOut, L"BOOT MISMATCH!\r\n"); + gBS->Stall (3000000); + BdsBootDeviceSelect (FALSE); + + // + // Abort with error. + // + gST->ConOut->OutputString (gST->ConOut, L"BOOT FAIL!\r\n"); + gBS->Stall (3000000); + CpuDeadLoop (); + + // + // Only assert here since this is the right behavior, we should never + // return back to DxeCore. + // + ASSERT (FALSE); +} diff --git a/Legacy/BootPlatform/BiosVideo/BiosVideo.c b/Legacy/BootPlatform/BiosVideo/BiosVideo.c new file mode 100644 index 0000000000000000000000000000000000000000..0d406130dd007410b324336a996d677105c33230 --- /dev/null +++ b/Legacy/BootPlatform/BiosVideo/BiosVideo.c @@ -0,0 +1,2547 @@ +/** @file + + BiosVideo driver produce EFI_GRAPHIC_OUTPUT_PROTOCOL via LegacyBios Video rom. + +Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BiosVideo.h" + +// +// EFI Driver Binding Protocol Instance +// +EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding = { + BiosVideoDriverBindingSupported, + BiosVideoDriverBindingStart, + BiosVideoDriverBindingStop, + 0x3, + NULL, + NULL +}; + +// +// Global lookup tables for VGA graphics modes +// +UINT8 mVgaLeftMaskTable[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; + +UINT8 mVgaRightMaskTable[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; + +UINT8 mVgaBitMaskTable[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + +EFI_LEGACY_8259_PROTOCOL *mLegacy8259 = NULL; +THUNK_CONTEXT mThunkContext; + +EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor[] = { + // + // {B, G, R, reserved} + // + {0x00, 0x00, 0x00, 0x00}, // BLACK + {0x98, 0x00, 0x00, 0x00}, // LIGHTBLUE + {0x00, 0x98, 0x00, 0x00}, // LIGHGREEN + {0x98, 0x98, 0x00, 0x00}, // LIGHCYAN + {0x00, 0x00, 0x98, 0x00}, // LIGHRED + {0x98, 0x00, 0x98, 0x00}, // MAGENTA + {0x00, 0x98, 0x98, 0x00}, // BROWN + {0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY + {0x10, 0x10, 0x10, 0x00}, + {0xff, 0x10, 0x10, 0x00}, // BLUE + {0x10, 0xff, 0x10, 0x00}, // LIME + {0xff, 0xff, 0x10, 0x00}, // CYAN + {0x10, 0x10, 0xff, 0x00}, // RED + {0xf0, 0x10, 0xff, 0x00}, // FUCHSIA + {0x10, 0xff, 0xff, 0x00}, // YELLOW + {0xff, 0xff, 0xff, 0x00} // WHITE +}; + +/** + Install child handle for a detect BiosVideo device and install related protocol + into this handle, such as EFI_GRAPHIC_OUTPUT_PROTOCOL. + + @param This Instance pointer of EFI_DRIVER_BINDING_PROTOCOL + @param ParentHandle Parent's controller handle + @param ParentPciIo Parent's EFI_PCI_IO_PROTOCOL instance pointer + @param ParentLegacy8259 Parent's EFI_LEGACY_8259_PROTOCOL instance pointer + @param ParentDevicePath Parent's BIOS Video controller device path + @param RemainingDevicePath Remaining device path node instance for children. + + @return whether success to create children handle for a VGA device and install + related protocol into new children handle. + +**/ +EFI_STATUS +BiosVideoChildHandleInstall ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ParentHandle, + IN EFI_PCI_IO_PROTOCOL *ParentPciIo, + IN EFI_LEGACY_8259_PROTOCOL *ParentLegacy8259, + IN THUNK_CONTEXT *ThunkContext, + 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 + ) +; + +/** + Collect the resource from destroyed bios video device. + + @param BiosVideoPrivate Video child device private data structure +**/ + +VOID +BiosVideoDeviceReleaseResource ( + BIOS_VIDEO_DEV *BiosVideoPrivate + ) +; + +/** + Driver Entry Point. + + @param ImageHandle Handle of driver image. + @param SystemTable Pointer to system table. + + @return EFI_STATUS +**/ +EFI_STATUS +EFIAPI +BiosVideoDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gBiosVideoDriverBinding, + ImageHandle, + &gBiosVideoComponentName, + &gBiosVideoComponentName2 + ); + + return Status; +} + +/** + Test to see if Bios Video could be supported on the Controller. + + @param This Pointer to driver binding protocol + @param Controller Controller handle to connect + @param RemainingDevicePath A pointer to the remaining portion of a device path + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +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_8259_PROTOCOL *LegacyBios; + EFI_PCI_IO_PROTOCOL *PciIo; + + // + // See if the Legacy 8259 Protocol is available + // + Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (!BiosVideoIsVga (PciIo)) { + Status = EFI_UNSUPPORTED; + } + + 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 device 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; + + PciIo = NULL; + // + // Prepare for status code + // + Status = gBS->HandleProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Open the IO Abstraction(s) needed + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Establish legacy environment for thunk call for all children handle. + // + if (mLegacy8259 == NULL) { + Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &mLegacy8259); + if (EFI_ERROR (Status)) { + goto Done; + } + + InitializeBiosIntCaller(&mThunkContext); + InitializeInterruptRedirection(mLegacy8259); + } + + // + // Create child handle and install GraphicsOutputProtocol on it + // + Status = BiosVideoChildHandleInstall ( + This, + Controller, + PciIo, + mLegacy8259, + &mThunkContext, + ParentDevicePath, + RemainingDevicePath + ); + +Done: + if (EFI_ERROR (Status)) { + if (PciIo != NULL) { + // + // Release PCI I/O Protocols on the controller handle. + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + } + + return Status; +} + +/** + Stop this driver on Controller + + @param This Protocol instance pointer. + @param Controller Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed Controller. + @retval other This driver was not removed from this device. + +**/ +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; + + if (NumberOfChildren == 0) { + // + // Close PCI I/O protocol on the controller handle + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; + } + + AllChildrenStopped = TRUE; + for (Index = 0; Index < NumberOfChildren; Index++) { + Status = BiosVideoChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]); + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Install child handle for a detect BiosVideo device and install related protocol + into this handle, such as EFI_GRAPHIC_OUTPUT_PROTOCOL. + + @param This Instance pointer of EFI_DRIVER_BINDING_PROTOCOL + @param ParentHandle Parent's controller handle + @param ParentPciIo Parent's EFI_PCI_IO_PROTOCOL instance pointer + @param ParentLegacy8259 Parent's EFI_LEGACY_8259_PROTOCOL instance pointer + @param ParentDevicePath Parent's BIOS Video controller device path + @param RemainingDevicePath Remaining device path node instance for children. + + @return whether success to create children handle for a VGA device and install + related protocol into new children handle. + +**/ +EFI_STATUS +BiosVideoChildHandleInstall ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ParentHandle, + IN EFI_PCI_IO_PROTOCOL *ParentPciIo, + IN EFI_LEGACY_8259_PROTOCOL *ParentLegacy8259, + IN THUNK_CONTEXT *ParentThunkContext, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + BIOS_VIDEO_DEV *BiosVideoPrivate; + ACPI_ADR_DEVICE_PATH AcpiDeviceNode; + + // + // Allocate the private device structure for video device + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (BIOS_VIDEO_DEV), + (VOID**) &BiosVideoPrivate + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + ZeroMem (BiosVideoPrivate, sizeof (BIOS_VIDEO_DEV)); + + if (!BiosVideoIsVga (ParentPciIo)) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + BiosVideoPrivate->VgaCompatible = TRUE; + + // + // Initialize the child private structure + // + BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE; + BiosVideoPrivate->Handle = NULL; + + // + // Fill in Graphics Output specific mode structures + // + BiosVideoPrivate->HardwareNeedsStarting = TRUE; + BiosVideoPrivate->ModeData = NULL; + BiosVideoPrivate->LineBuffer = NULL; + BiosVideoPrivate->VgaFrameBuffer = NULL; + BiosVideoPrivate->VbeFrameBuffer = NULL; + + // + // Fill in the VGA Mini Port Protocol fields + // + BiosVideoPrivate->VgaMiniPort.SetMode = BiosVideoVgaMiniPortSetMode; + BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset = 0xb8000; + BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4; + BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset = 0x3d5; + BiosVideoPrivate->VgaMiniPort.VgaMemoryBar = EFI_PCI_IO_PASS_THROUGH_BAR; + BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR; + BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar = EFI_PCI_IO_PASS_THROUGH_BAR; + + // + // Assume that Graphics Output Protocol will be produced until proven otherwise + // + BiosVideoPrivate->ProduceGraphicsOutput = TRUE; + + // + // Child handle need to consume the Legacy Bios protocol + // + BiosVideoPrivate->Legacy8259 = ParentLegacy8259; + BiosVideoPrivate->ThunkContext = ParentThunkContext; + + // + // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally + // + BiosVideoPrivate->PciIo = ParentPciIo; + + // + // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output + // + Status = BiosVideoCheckForVbe (BiosVideoPrivate); + if (EFI_ERROR (Status)) { + // + // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support + // for the standard 640x480 16 color VGA mode + // + if (BiosVideoPrivate->VgaCompatible) { + Status = BiosVideoCheckForVga (BiosVideoPrivate); + } + + if (EFI_ERROR (Status)) { + // + // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do + // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol. + // + BiosVideoPrivate->ProduceGraphicsOutput = FALSE; + + // + // INT services are available, so on the 80x25 and 80x50 text mode are supported + // + BiosVideoPrivate->VgaMiniPort.MaxMode = 2; + } + } + + if (BiosVideoPrivate->ProduceGraphicsOutput) { + if (RemainingDevicePath == NULL) { + ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH)); + AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH; + AcpiDeviceNode.Header.SubType = ACPI_ADR_DP; + AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0); + SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH)); + + BiosVideoPrivate->DevicePath = AppendDevicePathNode ( + ParentDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode + ); + } else { + BiosVideoPrivate->DevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath); + } + + // + // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &BiosVideoPrivate->Handle, + &gEfiDevicePathProtocolGuid, + BiosVideoPrivate->DevicePath, + &gEfiGraphicsOutputProtocolGuid, + &BiosVideoPrivate->GraphicsOutput, + &gEfiEdidDiscoveredProtocolGuid, + &BiosVideoPrivate->EdidDiscovered, + &gEfiEdidActiveProtocolGuid, + &BiosVideoPrivate->EdidActive, + NULL + ); + + if (!EFI_ERROR (Status)) { + // + // Open the Parent Handle for the child + // + Status = gBS->OpenProtocol ( + ParentHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &BiosVideoPrivate->PciIo, + This->DriverBindingHandle, + BiosVideoPrivate->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + goto Done; + } + } + } else { + // + // Install VGA Mini Port Protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &BiosVideoPrivate->Handle, + &gEfiVgaMiniPortProtocolGuid, + &BiosVideoPrivate->VgaMiniPort, + NULL + ); + } + +Done: + if (EFI_ERROR (Status)) { + // + // 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; + 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 = NULL; + GraphicsOutput = NULL; + PciIo = NULL; + + Status = gBS->OpenProtocol ( + Handle, + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &GraphicsOutput, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput); + } + + Status = gBS->OpenProtocol ( + Handle, + &gEfiVgaMiniPortProtocolGuid, + (VOID **) &VgaMiniPort, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort); + } + + if (BiosVideoPrivate == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Close PCI I/O protocol that opened by child handle + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + // + // Uninstall protocols on child handle + // + if (BiosVideoPrivate->ProduceGraphicsOutput) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + BiosVideoPrivate->Handle, + &gEfiDevicePathProtocolGuid, + BiosVideoPrivate->DevicePath, + &gEfiGraphicsOutputProtocolGuid, + &BiosVideoPrivate->GraphicsOutput, + &gEfiEdidDiscoveredProtocolGuid, + &BiosVideoPrivate->EdidDiscovered, + &gEfiEdidActiveProtocolGuid, + &BiosVideoPrivate->EdidActive, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + BiosVideoPrivate->Handle, + &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; + } + + ZeroMem (&Regs, sizeof (Regs)); + + // + // Set the 80x25 Text VGA Mode + // + Regs.H.AH = 0x00; + Regs.H.AL = 0x03; + LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + + Regs.H.AH = 0x11; + Regs.H.AL = 0x14; + Regs.H.BL = 0; + LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + + // + // Do not disable IO/memory decode since that would prevent legacy ROM from working + // + + // + // Release all allocated resources + // + BiosVideoDeviceReleaseResource (BiosVideoPrivate); + + return EFI_SUCCESS; +} + +/** + Collect the resource from destroyed bios video device. + + @param BiosVideoPrivate Video child device private data structure + +**/ +VOID +BiosVideoDeviceReleaseResource ( + BIOS_VIDEO_DEV *BiosVideoPrivate + ) +{ + if (BiosVideoPrivate == NULL) { + return ; + } + + // + // Release all the resourses occupied by the BIOS_VIDEO_DEV + // + + // + // Free VGA Frame Buffer + // + if (BiosVideoPrivate->VgaFrameBuffer != NULL) { + gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer); + } + // + // Free VBE Frame Buffer + // + if (BiosVideoPrivate->VbeFrameBuffer != NULL) { + gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer); + } + // + // Free line buffer + // + if (BiosVideoPrivate->LineBuffer != NULL) { + gBS->FreePool (BiosVideoPrivate->LineBuffer); + } + // + // Free mode data + // + if (BiosVideoPrivate->ModeData != NULL) { + gBS->FreePool (BiosVideoPrivate->ModeData); + } + // + // Free memory allocated below 1MB + // + if (BiosVideoPrivate->PagesBelow1MB != 0) { + gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->NumberOfPagesBelow1MB); + } + + if (BiosVideoPrivate->VbeSaveRestorePages != 0) { + gBS->FreePages (BiosVideoPrivate->VbeSaveRestoreBuffer, BiosVideoPrivate->VbeSaveRestorePages); + } + // + // Free graphics output protocol occupied resource + // + if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) { + if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) { + gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); + } + gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode); + } + // + // Free EDID discovered protocol occupied resource + // + if (BiosVideoPrivate->EdidDiscovered.Edid != NULL) { + gBS->FreePool (BiosVideoPrivate->EdidDiscovered.Edid); + } + // + // Free EDID active protocol occupied resource + // + if (BiosVideoPrivate->EdidActive.Edid != NULL) { + gBS->FreePool (BiosVideoPrivate->EdidActive.Edid); + } + + if (BiosVideoPrivate->DevicePath!= NULL) { + gBS->FreePool (BiosVideoPrivate->DevicePath); + } + + gBS->FreePool (BiosVideoPrivate); + + return ; +} + +#define PCI_DEVICE_ENABLED (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE) + + +/** + Judge whether this device is VGA device. + + @param PciIo Parent PciIo protocol instance pointer + + @retval TRUE Is vga device + @retval FALSE Is no vga device +**/ +BOOLEAN +BiosVideoIsVga ( + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + EFI_STATUS Status; + BOOLEAN VgaCompatible; + PCI_TYPE00 Pci; + + VgaCompatible = FALSE; + + // + // Read the PCI Configuration Header + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + return VgaCompatible; + } + + // + // See if this is a VGA compatible controller or not + // + if ((Pci.Hdr.Command & PCI_DEVICE_ENABLED) == PCI_DEVICE_ENABLED) { + if (Pci.Hdr.ClassCode[2] == PCI_CLASS_OLD && Pci.Hdr.ClassCode[1] == PCI_CLASS_OLD_VGA) { + // + // Base Class 0x00 Sub-Class 0x01 - Backward compatible VGA device + // + VgaCompatible = TRUE; + } + + if (Pci.Hdr.ClassCode[2] == PCI_CLASS_DISPLAY && Pci.Hdr.ClassCode[1] == PCI_CLASS_DISPLAY_VGA && Pci.Hdr.ClassCode[0] == 0x00) { + // + // Base Class 3 Sub-Class 0 Programming interface 0 - VGA compatible Display controller + // + VgaCompatible = TRUE; + } + } + + return VgaCompatible; +} + + +/** + Check for VBE device + + @param BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure + + @retval EFI_SUCCESS VBE device found + +**/ +EFI_STATUS +EFIAPI +BiosVideoCheckForVbe ( + IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate + ) +{ + EFI_STATUS Status; + IA32_REGISTER_SET Regs; + UINT16 *ModeNumberPtr; + BIOS_VIDEO_MODE_DATA *ModeBuffer; + BIOS_VIDEO_MODE_DATA *CurrentModeData; + UINTN PreferMode; + UINTN ModeNumber; + VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *GraphicsOutputMode; + UINT32 HighestHorizontalResolution; + UINT32 HighestVerticalResolution; + UINTN HighestResolutionMode; + + // + // Allocate buffer under 1MB for VBE data structures + // + BiosVideoPrivate->NumberOfPagesBelow1MB = 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 = LEGACY_REGION_BASE - 1; + + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + BiosVideoPrivate->NumberOfPagesBelow1MB, + &BiosVideoPrivate->PagesBelow1MB + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (&ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING)); + + // + // Fill in the Graphics Output Protocol + // + BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode; + BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode; + BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVbeBlt; + BiosVideoPrivate->GraphicsOutput.Mode = NULL; + + // + // Fill in the VBE related data structures + // + BiosVideoPrivate->VbeInformationBlock = (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB); + BiosVideoPrivate->VbeModeInformationBlock = (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1); + BiosVideoPrivate->VbeEdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1); + BiosVideoPrivate->VbeCrtcInformationBlock = (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeEdidDataBlock + 1); + BiosVideoPrivate->VbeSaveRestorePages = 0; + BiosVideoPrivate->VbeSaveRestoreBuffer = 0; + + HighestHorizontalResolution = 0; + HighestVerticalResolution = 0; + HighestResolutionMode = 0; + + // + // Test to see if the Video Adapter is compliant with VBE 3.0 + // + // INT 10 - VESA SuperVGA BIOS (VBE) - GET SuperVGA INFORMATION + // + // AX = 4F00h + // ES:DI -> buffer for SuperVGA information (see #00077) + // Return: AL = 4Fh if function supported + // AH = status + // 00h successful + // ES:DI buffer filled + // 01h failed + // ---VBE v2.0--- + // 02h function not supported by current hardware configuration + // 03h function invalid in current video mode + // Desc: determine whether VESA BIOS extensions are present and the capabilities + // supported by the display adapter + // + ZeroMem (&Regs, sizeof (Regs)); + Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION; + ZeroMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK)); + BiosVideoPrivate->VbeInformationBlock->VESASignature = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE; + Regs.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock); + Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock); + + LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + + Status = EFI_DEVICE_ERROR; + + // + // See if the VESA call succeeded + // + if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + return Status; + } + // + // Check for 'VESA' signature + // + if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) { + return Status; + } + + BiosVideoPrivate->EdidDiscovered.SizeOfEdid = 0; + BiosVideoPrivate->EdidDiscovered.Edid = NULL; + + BiosVideoPrivate->EdidActive.SizeOfEdid = 0; + BiosVideoPrivate->EdidActive.Edid = NULL; + + // + // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode + // + ModeNumberPtr = (UINT16 *) + ( + (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) | + ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff) + ); + + PreferMode = 0; + ModeNumber = 0; + + for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; ModeNumberPtr++) { + // + // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number. + // + if ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) { + continue; + } + // + // Get the information about the mode + // + // INT 10 - VESA SuperVGA BIOS - GET SuperVGA MODE INFORMATION + // + // AX = 4F01h + // CX = SuperVGA video mode (see #04082 for bitfields) + // ES:DI -> 256-byte buffer for mode information (see #00079) + // Return: AL = 4Fh if function supported + // AH = status + // 00h successful + // ES:DI buffer filled + // 01h failed + // Desc: determine the attributes of the specified video mode + // + ZeroMem (&Regs, sizeof (Regs)); + Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION; + Regs.X.CX = *ModeNumberPtr; + ZeroMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK)); + Regs.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock); + Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock); + + LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + + // + // See if the call succeeded. If it didn't, then try the next mode. + // + if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + continue; + } + // + // See if the mode supports color. If it doesn't then try the next mode. + // + if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 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) == 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) == 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 sure the + // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel + // + if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) { + continue; + } + + if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) { + continue; + } + + if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 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 == 0) { + continue; + } + // + // Skip modes not supported by the hardware. + // + if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_HARDWARE) == 0) { + continue; + } + // + // Skip resolutions lower then 640x480. + // + if (BiosVideoPrivate->VbeModeInformationBlock->XResolution < 640 || + BiosVideoPrivate->VbeModeInformationBlock->YResolution < 480) { + continue; + } + + // + // Record the highest resolution mode to set later. + // + if ((BiosVideoPrivate->VbeModeInformationBlock->XResolution >= HighestHorizontalResolution) + && (BiosVideoPrivate->VbeModeInformationBlock->YResolution >= HighestVerticalResolution)) { + HighestHorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution; + HighestVerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution; + HighestResolutionMode = (UINT16) ModeNumber; + PreferMode = HighestResolutionMode; + } + + // + // Add mode to the list of available modes + // + ModeNumber ++; + Status = gBS->AllocatePool ( + EfiBootServicesData, + ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA), + (VOID **) &ModeBuffer + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + if (ModeNumber > 1) { + CopyMem ( + ModeBuffer, + BiosVideoPrivate->ModeData, + (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA) + ); + } + + if (BiosVideoPrivate->ModeData != NULL) { + gBS->FreePool (BiosVideoPrivate->ModeData); + } + + CurrentModeData = &ModeBuffer[ModeNumber - 1]; + CurrentModeData->VbeModeNumber = *ModeNumberPtr; + if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) { + CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine; + CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition; + CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1); + CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition; + CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1); + CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition; + CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1); + CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition; + CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1); + } else { + CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine; + CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition; + CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1); + CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition; + CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1); + CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition; + CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1); + CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition; + CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1); + } + CurrentModeData->PixelFormat = PixelBitMask; + if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) && + (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) { + if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) { + CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor; + } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) { + CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor; + } + } + CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position; + CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position; + CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position; + CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position; + + CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr; + CurrentModeData->FrameBufferSize = BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024; + CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution; + CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution; + + CurrentModeData->BitsPerPixel = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel; + + BiosVideoPrivate->ModeData = ModeBuffer; + } + // + // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT + // + if (ModeNumber == 0) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + // + // Allocate buffer for Graphics Output Protocol mode information + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE), + (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode + ); + if (EFI_ERROR (Status)) { + goto Done; + } + GraphicsOutputMode = BiosVideoPrivate->GraphicsOutput.Mode; + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), + (VOID **) &GraphicsOutputMode->Info + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + GraphicsOutputMode->MaxMode = (UINT32) ModeNumber; + // + // Current mode is unknow till now, set it to an invalid mode. + // + GraphicsOutputMode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER; + + // + // Find the best mode to initialize + // + Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode); + if (EFI_ERROR (Status)) { + for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) { + Status = BiosVideoGraphicsOutputSetMode ( + &BiosVideoPrivate->GraphicsOutput, + (UINT32) PreferMode + ); + if (!EFI_ERROR (Status)) { + break; + } + } + } + +Done: + // + // If there was an error, then free the mode structure + // + if (EFI_ERROR (Status)) { + if (BiosVideoPrivate->ModeData != NULL) { + gBS->FreePool (BiosVideoPrivate->ModeData); + } + if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) { + if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) { + gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); + } + gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode); + } + } + + return Status; +} + +/** + Check for VGA device + + @param BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure + + @retval EFI_SUCCESS Standard VGA device found +**/ +EFI_STATUS +EFIAPI +BiosVideoCheckForVga ( + IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate + ) +{ + EFI_STATUS Status; + BIOS_VIDEO_MODE_DATA *ModeBuffer; + + // + // Fill in the Graphics Output Protocol + // + BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode; + BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode; + BiosVideoPrivate->GraphicsOutput.Blt = BiosVideoGraphicsOutputVgaBlt; + + // + // Allocate buffer for Graphics Output Protocol mode information + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE), + (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode + ); + if (EFI_ERROR (Status)) { + goto Done; + } + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), + (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode->Info + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Add mode to the list of available modes + // + BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (BIOS_VIDEO_MODE_DATA), + (VOID **) &ModeBuffer + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + ModeBuffer->VbeModeNumber = 0x0012; + ModeBuffer->BytesPerScanLine = 640; + ModeBuffer->LinearFrameBuffer = (VOID *) (UINTN) (0xa0000); + ModeBuffer->FrameBufferSize = 0; + ModeBuffer->HorizontalResolution = 640; + ModeBuffer->VerticalResolution = 480; + ModeBuffer->BitsPerPixel = 8; + ModeBuffer->PixelFormat = PixelBltOnly; + ModeBuffer->ColorDepth = 32; + ModeBuffer->RefreshRate = 60; + + BiosVideoPrivate->ModeData = ModeBuffer; + + // + // Test to see if the Video Adapter support the 640x480 16 color mode + // + BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER; + Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0); + +Done: + // + // If there was an error, then free the mode structure + // + if (EFI_ERROR (Status)) { + if (BiosVideoPrivate->ModeData != NULL) { + gBS->FreePool (BiosVideoPrivate->ModeData); + } + if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) { + if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) { + gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info); + } + gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode); + } + } + 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 Info buffer. + @param Info - Caller allocated buffer that returns information about ModeNumber. + + @return EFI_SUCCESS - Mode information returned. + EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode. + EFI_NOT_STARTED - Video display is not initialized. Call SetMode () + 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; + EFI_STATUS Status; + BIOS_VIDEO_MODE_DATA *ModeData; + + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + + if (BiosVideoPrivate->HardwareNeedsStarting) { + return EFI_NOT_STARTED; + } + + if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), + (VOID**) Info + ); + if (EFI_ERROR (Status)) { + return Status; + } + + *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + + ModeData = &BiosVideoPrivate->ModeData[ModeNumber]; + (*Info)->Version = 0; + (*Info)->HorizontalResolution = ModeData->HorizontalResolution; + (*Info)->VerticalResolution = ModeData->VerticalResolution; + (*Info)->PixelFormat = ModeData->PixelFormat; + (*Info)->PixelInformation = ModeData->PixelBitMask; + + (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->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. + + @return EFI_SUCCESS - Graphics mode was changed. + EFI_DEVICE_ERROR - The device had an error and could not complete the request. + EFI_UNSUPPORTED - ModeNumber is not supported by this device. + +**/ +STATIC +EFI_STATUS +BiosVideoSetModeWorker ( + IN BIOS_VIDEO_DEV *BiosVideoPrivate, + IN BIOS_VIDEO_MODE_DATA *ModeData, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + IA32_REGISTER_SET Regs; + + if (BiosVideoPrivate->LineBuffer != NULL) { + FreePool (BiosVideoPrivate->LineBuffer); + BiosVideoPrivate->LineBuffer = NULL; + } + + if (BiosVideoPrivate->VgaFrameBuffer != NULL) { + FreePool (BiosVideoPrivate->VgaFrameBuffer); + BiosVideoPrivate->VgaFrameBuffer = NULL; + } + + if (BiosVideoPrivate->VbeFrameBuffer != NULL) { + FreePool (BiosVideoPrivate->VbeFrameBuffer); + BiosVideoPrivate->VbeFrameBuffer = NULL; + } + + BiosVideoPrivate->LineBuffer = (UINT8 *) AllocatePool (ModeData->BytesPerScanLine); + if (NULL == 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 = (UINT8 *) AllocatePool (4 * 480 * 80); + if (NULL == BiosVideoPrivate->VgaFrameBuffer) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Set VGA Mode + // + Regs.X.AX = ModeData->VbeModeNumber; + LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + } else { + // + // Allocate a working buffer for BLT operations to the VBE frame buffer + // + BiosVideoPrivate->VbeFrameBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool ( + ModeData->BytesPerScanLine * ModeData->VerticalResolution + ); + if (NULL == BiosVideoPrivate->VbeFrameBuffer) { + return EFI_OUT_OF_RESOURCES; + } + // + // Set VBE mode + // + Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE; + Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER); + ZeroMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK)); + Regs.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock); + Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock); + + LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + + // + // Check to see if the call succeeded + // + if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) { + return EFI_DEVICE_ERROR; + } + } + + return EFI_SUCCESS; +} + +/** + + Graphics Output protocol interface to set video mode + + + @param This - Protocol instance pointer. + @param ModeNumber - The mode number to be set. + + @return EFI_SUCCESS - Graphics mode was changed. + EFI_DEVICE_ERROR - The device had an error and could not complete the request. + EFI_UNSUPPORTED - ModeNumber is not supported by this device. + +**/ +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; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + + ModeData = &BiosVideoPrivate->ModeData[ModeNumber]; + + if (ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + if (ModeNumber == This->Mode->Mode) { + return EFI_SUCCESS; + } + + Status = BiosVideoSetModeWorker (BiosVideoPrivate, ModeData, BiosVideoPrivate->DevicePath); + if (EFI_ERROR (Status)) { + return Status; + } + + This->Mode->Mode = ModeNumber; + This->Mode->Info->Version = 0; + This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution; + This->Mode->Info->VerticalResolution = ModeData->VerticalResolution; + This->Mode->Info->PixelFormat = ModeData->PixelFormat; + This->Mode->Info->PixelInformation = ModeData->PixelBitMask; + This->Mode->Info->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel; + This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + + // + // Frame BufferSize remain unchanged + // + This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS)(UINTN)ModeData->LinearFrameBuffer; + This->Mode->FrameBufferSize = ModeData->FrameBufferSize; + + BiosVideoPrivate->HardwareNeedsStarting = FALSE; + + return EFI_SUCCESS; +} + +/** + + Update physical frame buffer, copy 4 bytes block, then copy remaining bytes. + + + @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 BltOperation + @param DestinationY - The Y coordinate of the destination for BltOperation + @param TotalBytes - The total bytes of copy + @param VbePixelWidth - Bytes per pixel + @param BytesPerScanLine - Bytes per scan line + + @return None. + +**/ +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 = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth; + + // + // If TotalBytes is less than 4 bytes, only start byte copy. + // + if (TotalBytes < 4) { + Status = 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 = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3; + + if (UnalignedBytes != 0) { + Status = PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) FrameBufferAddr, + UnalignedBytes, + VbeBuffer + ); + ASSERT_EFI_ERROR (Status); + FrameBufferAddr += UnalignedBytes; + VbeBuffer += UnalignedBytes; + } + + // + // Calculate 4-byte block count and remaining bytes. + // + CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2; + RemainingBytes = (TotalBytes - UnalignedBytes) & 3; + + // + // Copy 4-byte block and remaining bytes to physical frame buffer. + // + if (CopyBlockNum != 0) { + Status = PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint32, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) FrameBufferAddr, + CopyBlockNum, + VbeBuffer + ); + ASSERT_EFI_ERROR (Status); + } + + if (RemainingBytes != 0) { + FrameBufferAddr += (CopyBlockNum << 2); + VbeBuffer += (CopyBlockNum << 2); + Status = PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) FrameBufferAddr, + RemainingBytes, + VbeBuffer + ); + ASSERT_EFI_ERROR (Status); + } +} + +// +// BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes +// +/** + + Graphics Output protocol instance to block transfer for VBE device + + + @param This - Pointer to Graphics Output protocol instance + @param BltBuffer - The data to transfer to screen + @param BltOperation - The operation to perform + @param SourceX - The X coordinate of the source for BltOperation + @param SourceY - The Y coordinate of the source for BltOperation + @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 rectangle in pixels + @param Height - The height of a rectangle in the blt rectangle in pixels + @param Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation. + If a Delta of 0 is used, the entire BltBuffer will be operated on. + If a subrectangle of the BltBuffer is used, then Delta represents + the number of bytes in a row of the BltBuffer. + + @return EFI_INVALID_PARAMETER - Invalid parameter passed in + 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; + 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; + + if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) { + return EFI_INVALID_PARAMETER; + } + + if (Width == 0 || Height == 0) { + return EFI_INVALID_PARAMETER; + } + + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + Mode = &BiosVideoPrivate->ModeData[This->Mode->Mode]; + PciIo = BiosVideoPrivate->PciIo; + + VbeFrameBuffer = BiosVideoPrivate->VbeFrameBuffer; + MemAddress = Mode->LinearFrameBuffer; + BytesPerScanLine = Mode->BytesPerScanLine; + VbePixelWidth = Mode->BitsPerPixel / 8; + BltUint8 = (UINT8 *) BltBuffer; + TotalBytes = Width * VbePixelWidth; + + // + // 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 == 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 == 0) { + Delta = 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 = gBS->RaiseTPL (TPL_NOTIFY); + + switch (BltOperation) { + case EfiBltVideoToBltBuffer: + for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) { + Blt = (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_GRAPHICS_OUTPUT_BLT_PIXEL + // + VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth)); + for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) { + Pixel = *(UINT32 *) (VbeBuffer); + Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask); + Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask); + Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask); + Blt->Reserved = 0; + Blt++; + VbeBuffer += VbePixelWidth; + } + + } + break; + + case EfiBltVideoToVideo: + for (Index = 0; Index < Height; Index++) { + if (DestinationY <= SourceY) { + SrcY = SourceY + Index; + DstY = DestinationY + Index; + } else { + SrcY = SourceY + Height - Index - 1; + DstY = DestinationY + Height - Index - 1; + } + + VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth); + VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth); + + CopyMem ( + VbeBuffer, + VbeBuffer1, + TotalBytes + ); + + // + // Update physical frame buffer. + // + CopyVideoBuffer ( + PciIo, + VbeBuffer, + MemAddress, + DestinationX, + DstY, + TotalBytes, + VbePixelWidth, + BytesPerScanLine + ); + } + break; + + case EfiBltVideoFill: + VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth); + Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8; + // + // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer + // + Pixel = ((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 = 0; Index < Width; Index++) { + CopyMem ( + VbeBuffer, + &Pixel, + VbePixelWidth + ); + VbeBuffer += VbePixelWidth; + } + + VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth); + for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) { + CopyMem ( + (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth), + VbeBuffer, + TotalBytes + ); + } + for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) { + // + // Update physical frame buffer. + // + CopyVideoBuffer ( + PciIo, + VbeBuffer, + MemAddress, + DestinationX, + DstY, + TotalBytes, + VbePixelWidth, + BytesPerScanLine + ); + } + break; + + case EfiBltBufferToVideo: + for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) { + Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth)); + for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) { + // + // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer + // + Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) | + ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) | + ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position); + CopyMem ( + VbeBuffer, + &Pixel, + VbePixelWidth + ); + Blt++; + VbeBuffer += VbePixelWidth; + } + + VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth)); + + // + // Update physical frame buffer. + // + CopyVideoBuffer ( + PciIo, + VbeBuffer, + MemAddress, + DestinationX, + DstY, + TotalBytes, + VbePixelWidth, + BytesPerScanLine + ); + } + break; + default: + break; + } + + gBS->RestoreTPL (OriginalTPL); + + return EFI_SUCCESS; +} + +/** + + 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 + +**/ +STATIC +VOID +WriteGraphicsController ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINTN Address, + IN UINTN Data + ) +{ + Address = 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_MODE_0 + ); + + for (BitPlane = 0, FrameBufferOffset = 0; + BitPlane < VGA_NUMBER_OF_BIT_PLANES; + BitPlane++, FrameBufferOffset += 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 = HardwareBuffer; + Destination = MemoryBuffer + FrameBufferOffset; + + for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) { + PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint8, + (UINT8) EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64)(UINTN) Source, + WidthInBytes, + (VOID *) Destination + ); + } + } +} + +/** + + Internal routine to convert VGA color to Graphics Output color + + + @param MemoryBuffer - Buffer containing VGA color + @param X - The X coordinate of pixel on screen + @param Y - The Y coordinate of pixel on screen + @param BltBuffer - Buffer to contain converted Graphics Output color + + @return None + +**/ +VOID +VgaConvertToGraphicsOutputColor ( + UINT8 *MemoryBuffer, + UINTN X, + UINTN Y, + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer + ) +{ + UINTN Mask; + UINTN Bit; + UINTN Color; + + MemoryBuffer += ((Y << 6) + (Y << 4) + (X >> 3)); + Mask = mVgaBitMaskTable[X & 0x07]; + for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) { + if ((*MemoryBuffer & Mask) != 0) { + Color |= Bit; + } + } + + *BltBuffer = mVgaColorToGraphicsOutputColor[Color]; +} + +/** + + Internal routine to convert Graphics Output color to VGA color + + + @param BltBuffer - buffer containing Graphics Output color + + @return Converted VGA color + +**/ +UINT8 +VgaConvertColor ( + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer + ) +{ + UINT8 Color; + + Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04)); + if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) { + Color |= 0x08; + } + + return Color; +} + +/** + Grahpics Output protocol instance to block transfer for VGA device + + @param This Pointer to Grahpics Output protocol instance + @param BltBuffer The data to transfer to screen + @param BltOperation The operation to perform + @param SourceX The X coordinate of the source for BltOperation + @param SourceY The Y coordinate of the source for BltOperation + @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 rectangle in pixels + @param Height The height of a rectangle in the blt rectangle in pixels + @param Delta Not used for EfiBltVideoFill and EfiBltVideoToVideo operation. + If a Delta of 0 is used, the entire BltBuffer will be operated 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 BytesPerBitPlane; + 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 X; + UINTN Y; + UINTN CurrentMode; + + if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) { + return EFI_INVALID_PARAMETER; + } + + if (Width == 0 || Height == 0) { + return EFI_INVALID_PARAMETER; + } + + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This); + + CurrentMode = This->Mode->Mode; + PciIo = BiosVideoPrivate->PciIo; + MemAddress = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer; + BytesPerScanLine = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3; + //BytesPerBitPlane = BytesPerScanLine * BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution; + VgaFrameBuffer = BiosVideoPrivate->VgaFrameBuffer; + + // + // 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 == EfiBltVideoToBltBuffer) { + // + // Video to BltBuffer: Source is Video, destination is BltBuffer + // + if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + } else { + // + // BltBuffer to Video: Source is BltBuffer, destination is Video + // + if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].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 == 0) { + Delta = 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 = gBS->RaiseTPL (TPL_NOTIFY); + + // + // Compute some values we need for VGA + // + switch (BltOperation) { + case EfiBltVideoToBltBuffer: + + SourceOffset = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3); + SourceWidth = ((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 + ); + + // + // Convert VGA Bit Planes to a Graphics Output 32-bit color value + // + BltBuffer += (DestinationY * (Delta >> 2) + DestinationX); + for (Rows = 0, Y = SourceY; Rows < Height; Rows++, Y++, BltBuffer += (Delta >> 2)) { + for (Columns = 0, X = SourceX; Columns < Width; Columns++, X++, BltBuffer++) { + VgaConvertToGraphicsOutputColor (VgaFrameBuffer, X, Y, BltBuffer); + } + + BltBuffer -= Width; + } + + break; + + case EfiBltVideoToVideo: + // + // Check for an aligned Video to Video operation + // + if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 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_WRITE_MODE_1 + ); + + SourceAddress = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3)); + DestinationAddress = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3)); + Bytes = Width >> 3; + for (Index = 0, Offset = 0; Index < Height; Index++, Offset += 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 = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3); + SourceWidth = ((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 = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3)); + Bytes = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3); + LeftMask = mVgaLeftMaskTable[DestinationX & 0x07]; + RightMask = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07]; + if (Bytes == 0) { + LeftMask = (UINT8) (LeftMask & RightMask); + RightMask = 0; + } + + if (LeftMask == 0xff) { + StartAddress--; + Bytes++; + LeftMask = 0; + } + + if (RightMask == 0xff) { + Bytes++; + RightMask = 0; + } + + PixelColor = 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 != 0) { + // + // Program the BitMask register with the Left column mask + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + LeftMask + ); + + for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += 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 pixels 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 = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) { + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthFillUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address, + Bytes - 1, + &PixelColor + ); + } + } + + if (RightMask != 0) { + // + // Program the BitMask register with the Right column mask + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + RightMask + ); + + for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += 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 pixels enabled by BitMask + // + PciIo->Mem.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) (UINTN) Address, + 1, + &PixelColor + ); + } + } + break; + + case EfiBltBufferToVideo: + StartAddress = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3)); + LeftMask = 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 = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) { + for (Index1 = 0; Index1 < Width; Index1++) { + BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]); + } + AddressFix = Address; + + for (Bit = 0; Bit < 8; Bit++) { + // + // Program the BitMask register with the Left column mask + // + WriteGraphicsController ( + PciIo, + VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER, + LeftMask + ); + + for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 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 = (UINT8) (LeftMask >> 1); + if (LeftMask == 0) { + LeftMask = 0x80; + AddressFix++; + } + } + } + + break; + default: + break; + } + + 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; + IA32_REGISTER_SET Regs; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Make sure the ModeNumber is a valid value + // + if (ModeNumber >= This->MaxMode) { + return EFI_UNSUPPORTED; + } + // + // Get the device structure for this device + // + BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This); + + ZeroMem (&Regs, sizeof (Regs)); + + switch (ModeNumber) { + case 0: + // + // Set the 80x25 Text VGA Mode + // + Regs.H.AH = 0x00; + Regs.H.AL = 0x83; + LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + + Regs.H.AH = 0x11; + Regs.H.AL = 0x14; + Regs.H.BL = 0; + LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + + break; + + case 1: + // + // Set the 80x50 Text VGA Mode + // + Regs.H.AH = 0x00; + Regs.H.AL = 0x83; + LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + + Regs.H.AH = 0x11; + Regs.H.AL = 0x12; + Regs.H.BL = 0; + LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + break; + + default: + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} diff --git a/Legacy/BootPlatform/BiosVideo/BiosVideo.h b/Legacy/BootPlatform/BiosVideo/BiosVideo.h new file mode 100644 index 0000000000000000000000000000000000000000..f2fa0153ea8d04e6b891c1c2db6566a4fd87f3ab --- /dev/null +++ b/Legacy/BootPlatform/BiosVideo/BiosVideo.h @@ -0,0 +1,522 @@ +/** @file + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _BIOS_GRAPHICS_OUTPUT_H +#define _BIOS_GRAPHICS_OUTPUT_H + +#include + +// +// Driver Consumed Protocol Prototypes +// +#include + +#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" + +// +// ** CHANGE ** +// Legacy region base is now 0x0C0000 instead of 0x100000. +// +#define LEGACY_REGION_BASE 0x0C0000 + + +// +// Packed format support: The number of bits reserved for each of the colors and the actual +// position of RGB in the frame buffer is specified in the VBE Mode information +// +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 inherited from parent controller. + // + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_LEGACY_8259_PROTOCOL *Legacy8259; + THUNK_CONTEXT *ThunkContext; + + // + // 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 *DevicePath; + 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 + +#define EFI_SEGMENT(_Adr) (UINT16) ((UINT16) (((UINTN) (_Adr)) >> 4) & 0xf000) +#define EFI_OFFSET(_Adr) (UINT16) (((UINT16) ((UINTN) (_Adr))) & 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 +// +/** + Test to see if Bios Video could be supported on the Controller. + + @param This Pointer to driver binding protocol + @param Controller Controller handle to connect + @param RemainingDevicePath A pointer to the remaining portion of a device path + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +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 device 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 this driver on Controller + + @param This Protocol instance pointer. + @param Controller Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed Controller. + @retval other This driver was not removed from this device. + +**/ +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 +EFIAPI +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 +EFIAPI +BiosVideoCheckForVga ( + IN OUT BIOS_VIDEO_DEV *BiosVideoPrivate + ); + + + + +/** + Collect the resource from destroyed bios video device. + + @param BiosVideoPrivate Video child device private data structure + +**/ +VOID +BiosVideoDeviceReleaseResource ( + BIOS_VIDEO_DEV *BiosVideoChildPrivate + ) +; + +// +// 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 Info buffer. + @param Info - Caller allocated buffer that returns information about ModeNumber. + + @return EFI_SUCCESS - Mode information returned. + EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode. + EFI_NOT_STARTED - Video display is not initialized. Call SetMode () + 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. + + @return EFI_SUCCESS - Graphics mode was changed. + EFI_DEVICE_ERROR - The device had an error and could not complete the request. + EFI_UNSUPPORTED - ModeNumber is not supported by this device. + +**/ +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 instance + @param BltBuffer - The data to transfer to screen + @param BltOperation - The operation to perform + @param SourceX - The X coordinate of the source for BltOperation + @param SourceY - The Y coordinate of the source for BltOperation + @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 rectangle in pixels + @param Height - The height of a rectangle in the blt rectangle in pixels + @param Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation. + If a Delta of 0 is used, the entire BltBuffer will be operated on. + If a subrectangle of the BltBuffer is used, then Delta represents + the number of bytes in a row of the BltBuffer. + + @return EFI_INVALID_PARAMETER - Invalid parameter passed in + 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 instance + @param BltBuffer The data to transfer to screen + @param BltOperation The operation to perform + @param SourceX The X coordinate of the source for BltOperation + @param SourceY The Y coordinate of the source for BltOperation + @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 rectangle in pixels + @param Height The height of a rectangle in the blt rectangle in pixels + @param Delta Not used for EfiBltVideoFill and EfiBltVideoToVideo operation. + If a Delta of 0 is used, the entire BltBuffer will be operated 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 + ); + +/** + Judge whether this device is VGA device. + + @param PciIo Parent PciIo protocol instance pointer + + @retval TRUE Is vga device + @retval FALSE Is no vga device +**/ + +BOOLEAN +BiosVideoIsVga ( + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +; + +// +// 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_RESOLUTION * 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 + +/** + Initialize legacy environment for BIOS INI caller. + + @param ThunkContext the instance pointer of THUNK_CONTEXT +**/ +VOID +InitializeBiosIntCaller ( + THUNK_CONTEXT *ThunkContext + ); + +/** + Initialize interrupt redirection code and entries, because + IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f. + Or the interrupt will lost when we do thunk. + NOTE: We do not reset 8259 vector base, because it will cause pending + interrupt lost. + + @param Legacy8259 Instance pointer for EFI_LEGACY_8259_PROTOCOL. + +**/ +VOID +InitializeInterruptRedirection ( + IN EFI_LEGACY_8259_PROTOCOL *Legacy8259 + ); + +/** + 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 Reg Register contexted passed into (and returned) from thunk to 16-bit mode + + @retval TRUE Thunk completed, and there were no BIOS errors in the target code. + See Regs for status. + @retval FALSE There was a BIOS erro in the target code. +**/ +BOOLEAN +EFIAPI +LegacyBiosInt86 ( + IN BIOS_VIDEO_DEV *BiosDev, + IN UINT8 BiosInt, + IN IA32_REGISTER_SET *Regs + ); + +#endif diff --git a/Legacy/BootPlatform/BiosVideo/BiosVideo.inf b/Legacy/BootPlatform/BiosVideo/BiosVideo.inf new file mode 100644 index 0000000000000000000000000000000000000000..403eb3e865fac3e94dd7289dff27e951e4a101bf --- /dev/null +++ b/Legacy/BootPlatform/BiosVideo/BiosVideo.inf @@ -0,0 +1,56 @@ +## @file +# This module provides EFI_GRAPHIC_OUT_PROTOCOL based on functions of video +# on legacy BIOS. +# +# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BiosVideo + FILE_GUID = 29CF55F8-B675-4f5d-8F2F-B87A3ECFD063 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = BiosVideoDriverEntryPoint + +[Packages] + MdePkg/MdePkg.dec + OpenCorePkg/OpenDuetPkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + UefiLib + DebugLib + PrintLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseMemoryLib + MemoryAllocationLib + UefiDriverEntryPoint + DevicePathLib + +[Sources] + BiosVideo.h + BiosVideo.c + ComponentName.c + VesaBiosExtensions.h + LegacyBiosThunk.c + +[Protocols] + gEfiPciIoProtocolGuid + gEfiVgaMiniPortProtocolGuid + gEfiLegacy8259ProtocolGuid + gEfiEdidDiscoveredProtocolGuid + gEfiEdidActiveProtocolGuid + + [Guids] + gEfiGlobalVariableGuid + diff --git a/Legacy/BootPlatform/BiosVideo/ComponentName.c b/Legacy/BootPlatform/BiosVideo/ComponentName.c new file mode 100644 index 0000000000000000000000000000000000000000..6d673d2d2a0b5fe21e2b66e893d4d27a29654070 --- /dev/null +++ b/Legacy/BootPlatform/BiosVideo/ComponentName.c @@ -0,0 +1,166 @@ +/*++ + +Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "BiosVideo.h" + +EFI_STATUS +EFIAPI +BiosVideoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +BiosVideoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gBiosVideoComponentName = { + BiosVideoComponentNameGetDriverName, + BiosVideoComponentNameGetControllerName, + "eng" +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosVideoComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosVideoComponentNameGetControllerName, + "en" +}; + + +static EFI_UNICODE_STRING_TABLE mBiosVideoDriverNameTable[] = { + { + "eng;en", + L"BIOS[INT10] Video Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +BiosVideoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + 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. + DriverName - 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. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mBiosVideoDriverNameTable, + DriverName, + (BOOLEAN)(This == &gBiosVideoComponentName) + ); +} + +EFI_STATUS +EFIAPI +BiosVideoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers 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. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller 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. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/Legacy/BootPlatform/BiosVideo/LegacyBiosThunk.c b/Legacy/BootPlatform/BiosVideo/LegacyBiosThunk.c new file mode 100644 index 0000000000000000000000000000000000000000..fa134f88472735174ae28530773f37a77a456dd3 --- /dev/null +++ b/Legacy/BootPlatform/BiosVideo/LegacyBiosThunk.c @@ -0,0 +1,222 @@ +/** @file + Provide legacy thunk interface for accessing Bios Video Rom. + +Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "BiosVideo.h" + +#define EFI_CPU_EFLAGS_IF 0x200 + +/** + Initialize legacy environment for BIOS INI caller. + + @param ThunkContext the instance pointer of THUNK_CONTEXT +**/ +VOID +InitializeBiosIntCaller ( + THUNK_CONTEXT *ThunkContext + ) +{ + EFI_STATUS Status; + UINT32 RealModeBufferSize; + UINT32 ExtraStackSize; + EFI_PHYSICAL_ADDRESS LegacyRegionBase; + UINT32 LegacyRegionSize; + // + // Get LegacyRegion + // + AsmGetThunk16Properties (&RealModeBufferSize, &ExtraStackSize); + LegacyRegionSize = (((RealModeBufferSize + ExtraStackSize) / EFI_PAGE_SIZE) + 1) * EFI_PAGE_SIZE; + LegacyRegionBase = LEGACY_REGION_BASE; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + EFI_SIZE_TO_PAGES(LegacyRegionSize), + &LegacyRegionBase + ); + ASSERT_EFI_ERROR (Status); + + ThunkContext->RealModeBuffer = (VOID*)(UINTN)LegacyRegionBase; + ThunkContext->RealModeBufferSize = LegacyRegionSize; + ThunkContext->ThunkAttributes = THUNK_ATTRIBUTE_BIG_REAL_MODE|THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15; + AsmPrepareThunk16(ThunkContext); +} + +/** + Initialize interrupt redirection code and entries, because + IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f. + Or the interrupt will lost when we do thunk. + NOTE: We do not reset 8259 vector base, because it will cause pending + interrupt lost. + + @param Legacy8259 Instance pointer for EFI_LEGACY_8259_PROTOCOL. + +**/ +VOID +InitializeInterruptRedirection ( + IN EFI_LEGACY_8259_PROTOCOL *Legacy8259 + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS LegacyRegionBase; + UINTN LegacyRegionLength; + volatile UINT32 *IdtArray; + UINTN Index; + UINT8 ProtectedModeBaseVector; + + STATIC CONST UINT32 InterruptRedirectionCode[] = { + 0x90CF08CD, // INT8; IRET; NOP + 0x90CF09CD, // INT9; IRET; NOP + 0x90CF0ACD, // INTA; IRET; NOP + 0x90CF0BCD, // INTB; IRET; NOP + 0x90CF0CCD, // INTC; IRET; NOP + 0x90CF0DCD, // INTD; IRET; NOP + 0x90CF0ECD, // INTE; IRET; NOP + 0x90CF0FCD // INTF; IRET; NOP + }; + + + // + // Get LegacyRegion + // + LegacyRegionLength = sizeof(InterruptRedirectionCode); + LegacyRegionBase = LEGACY_REGION_BASE; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + EFI_SIZE_TO_PAGES(LegacyRegionLength), + &LegacyRegionBase + ); + ASSERT_EFI_ERROR (Status); + + // + // Copy code to legacy region + // + CopyMem ((VOID *)(UINTN)LegacyRegionBase, InterruptRedirectionCode, sizeof (InterruptRedirectionCode)); + + // + // Get VectorBase, it should be 0x68 + // + Status = Legacy8259->GetVector (Legacy8259, Efi8259Irq0, &ProtectedModeBaseVector); + ASSERT_EFI_ERROR (Status); + + // + // Patch IVT 0x68 ~ 0x6f + // + IdtArray = (UINT32 *) 0; + for (Index = 0; Index < 8; Index++) { + IdtArray[ProtectedModeBaseVector + Index] = ((EFI_SEGMENT (LegacyRegionBase + Index * 4)) << 16) | (EFI_OFFSET (LegacyRegionBase + Index * 4)); + } + + return ; +} + +/** + 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 Reg Register contexted passed into (and returned) from thunk to 16-bit mode + + @retval TRUE Thunk completed, and there were no BIOS errors in the target code. + See Regs for status. + @retval FALSE There was a BIOS erro in the target code. +**/ +BOOLEAN +EFIAPI +LegacyBiosInt86 ( + IN BIOS_VIDEO_DEV *BiosDev, + IN UINT8 BiosInt, + IN IA32_REGISTER_SET *Regs + ) +{ + UINTN Status; + IA32_REGISTER_SET ThunkRegSet; + BOOLEAN Ret; + UINT16 *Stack16; + BOOLEAN Enabled; + + ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet)); + ThunkRegSet.E.EFLAGS.Bits.Reserved_0 = 1; + ThunkRegSet.E.EFLAGS.Bits.Reserved_1 = 0; + ThunkRegSet.E.EFLAGS.Bits.Reserved_2 = 0; + ThunkRegSet.E.EFLAGS.Bits.Reserved_3 = 0; + ThunkRegSet.E.EFLAGS.Bits.IOPL = 3; + ThunkRegSet.E.EFLAGS.Bits.NT = 0; + ThunkRegSet.E.EFLAGS.Bits.IF = 1; + ThunkRegSet.E.EFLAGS.Bits.TF = 0; + ThunkRegSet.E.EFLAGS.Bits.CF = 0; + + ThunkRegSet.E.EDI = Regs->E.EDI; + ThunkRegSet.E.ESI = Regs->E.ESI; + ThunkRegSet.E.EBP = Regs->E.EBP; + ThunkRegSet.E.EBX = Regs->E.EBX; + ThunkRegSet.E.EDX = Regs->E.EDX; + ThunkRegSet.E.ECX = Regs->E.ECX; + ThunkRegSet.E.EAX = Regs->E.EAX; + ThunkRegSet.E.DS = Regs->E.DS; + ThunkRegSet.E.ES = Regs->E.ES; + + // + // The call to Legacy16 is a critical section to EFI + // + Enabled = SaveAndDisableInterrupts(); + + // + // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. + // + Status = BiosDev->Legacy8259->SetMode (BiosDev->Legacy8259, Efi8259LegacyMode, NULL, NULL); + ASSERT_EFI_ERROR (Status); + + Stack16 = (UINT16 *)((UINT8 *) BiosDev->ThunkContext->RealModeBuffer + BiosDev->ThunkContext->RealModeBufferSize - sizeof (UINT16)); + + ThunkRegSet.E.SS = (UINT16) (((UINTN) Stack16 >> 16) << 12); + ThunkRegSet.E.ESP = (UINT16) (UINTN) Stack16; + + ThunkRegSet.E.Eip = (UINT16)((volatile UINT32 *)NULL)[BiosInt]; + ThunkRegSet.E.CS = (UINT16)(((volatile UINT32 *)NULL)[BiosInt] >> 16); + BiosDev->ThunkContext->RealModeState = &ThunkRegSet; + AsmThunk16 (BiosDev->ThunkContext); + + // + // Restore protected mode interrupt state + // + Status = BiosDev->Legacy8259->SetMode (BiosDev->Legacy8259, Efi8259ProtectedMode, NULL, NULL); + ASSERT_EFI_ERROR (Status); + + // + // End critical section + // + SetInterruptState (Enabled); + + Regs->E.EDI = ThunkRegSet.E.EDI; + Regs->E.ESI = ThunkRegSet.E.ESI; + Regs->E.EBP = ThunkRegSet.E.EBP; + Regs->E.EBX = ThunkRegSet.E.EBX; + Regs->E.EDX = ThunkRegSet.E.EDX; + Regs->E.ECX = ThunkRegSet.E.ECX; + Regs->E.EAX = ThunkRegSet.E.EAX; + Regs->E.SS = ThunkRegSet.E.SS; + Regs->E.CS = ThunkRegSet.E.CS; + Regs->E.DS = ThunkRegSet.E.DS; + Regs->E.ES = ThunkRegSet.E.ES; + + CopyMem (&(Regs->E.EFLAGS), &(ThunkRegSet.E.EFLAGS), sizeof (UINT32)); + + Ret = (BOOLEAN) (Regs->E.EFLAGS.Bits.CF == 1); + + return Ret; +} + + diff --git a/Legacy/BootPlatform/BiosVideo/VesaBiosExtensions.h b/Legacy/BootPlatform/BiosVideo/VesaBiosExtensions.h new file mode 100644 index 0000000000000000000000000000000000000000..9e5597f1b8a7189255411c9ca39de11085f16415 --- /dev/null +++ b/Legacy/BootPlatform/BiosVideo/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 = 0x4f00 + ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK structure + Outputs: + AX = Return Status + +--*/ +#define VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION 0x4f01 + +/*++ + + Routine Description: + Function 01 : Return Mode Information + + Arguments: + Inputs: + AX = 0x4f01 + CX = Mode Number + ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK structure + Outputs: + AX = Return Status + +--*/ +#define VESA_BIOS_EXTENSIONS_SET_MODE 0x4f02 + +/*++ + + Routine Description: + Function 02 : Set Mode + + Arguments: + Inputs: + AX = 0x4f02 + BX = Desired mode to set + D0-D8 = Mode Number + D9-D10 = Reserved (must be 0) + D11 = 0 - Use current default refresh rate + = 1 - Use user specfieid CRTC values for refresh rate + D12-D13 = Reserved (must be 0) + D14 = 0 - Use windowed frame buffer model + = 1 - Use linear/flat frame buffer model + D15 = 0 - Clear display memory + = 1 - Don't clear display memory + ES:DI = Pointer to buffer to the VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK structure + Outputs: + AX = Return Status + +--*/ +#define VESA_BIOS_EXTENSIONS_RETURN_CURRENT_MODE 0x4f03 + +/*++ + + Routine Description: + Function 03 : Return Current Mode + + Arguments: + Inputs: + AX = 0x4f03 + Outputs: + AX = Return Status + BX = Current mode + D0-D13 = Mode Number + D14 = 0 - Windowed frame buffer model + = 1 - Linear/flat frame buffer model + D15 = 0 - Memory cleared at last mode set + = 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 = 0x4f03 + DL = 0x00 - Return Save/Restore State buffer size + = 0x01 - Save State + = 0x02 - Restore State + CX = Requested Status + D0 = Save/Restore controller hardware state + D1 = Save/Restore BIOS data state + D2 = Save/Restore DAC state + D3 = Save/Restore Regsiter state + ES:BX = Pointer to buffer if DL=1 or DL=2 + Outputs: + AX = Return Status + BX = Number of 64 byte blocks to hold the state buffer if DL=0 + +--*/ +#define VESA_BIOS_EXTENSIONS_EDID 0x4f15 + +/*++ + + Routine Description: + Function 15 : implement VBE/DDC service + + Arguments: + Inputs: + AX = 0x4f15 + BL = 0x00 - Report VBE/DDC Capabilities + CX = 0x00 - Controller unit number (00 = primary controller) + ES:DI = Null pointer, must be 0:0 in version 1.0 + Outputs: + AX = Return Status + BH = Approx. time in seconds, rounded up, to transfer one EDID block(128 bytes) + BL = DDC level supported + D0 = 0 DDC1 not supported + = 1 DDC1 supported + D1 = 0 DDC2 not supported + = 1 DDC2 supported + D2 = 0 Screen not blanked during data transfer + = 1 Screen blanked during data transfer + + Inputs: + AX = 0x4f15 + BL = 0x01 - Read EDID + CX = 0x00 - Controller unit number (00 = primary controller) + DX = 0x00 - EDID block number + ES:DI = Pointer to buffer in which the EDID block is returned + Outputs: + AX = 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 Gy1Gy0 + 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_TIMING_SIZE]; + UINT8 DetailedTimingDescriptions[VESA_BIOS_EXTENSIONS_DETAILED_TIMING_DESCRIPTOR_MAX_SIZE]; + UINT8 ExtensionFlag; //Number of (optional) 128-byte 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 modes 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 area + UINT8 OemData[256]; // Data area for OEM strings. Pad to 512 byte 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 definitions +// +#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: Normal RAMDAC operation +// 1: Use blank bit in function 9 to program RAMDAC +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_STEREOSCOPIC 0x08 // 0: No hardware stereoscopic signal support +// 1: Hardware stereoscopic signal support +// +#define VESA_BIOS_EXTENSIONS_CAPABILITY_VESA_EVC 0x10 // 0: Stero signaling 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 defined 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: Clear 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 attributes + UINT8 WinAAttributes; // Window A attributes + UINT8 WinBAttributes; // Window B attributes + UINT16 WinGranularity; // Window granularity in k + UINT16 WinSize; // Window size in k + UINT16 WinASegment; // Window A segment + UINT16 WinBSegment; // Window B segment + UINT32 WindowFunction; // Pointer to window function + UINT16 BytesPerScanLine; // Bytes per scanline + // + // Manadory fields for VESA Bios Extensions 1.2 and above + // + UINT16 XResolution; // Horizontal 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 model type + UINT8 BankSize; // Size of CGA style banks + UINT8 NumberOfImagePages; // Number of images pages + UINT8 Reserved1; // Reserved + UINT8 RedMaskSize; // Size of direct color red mask + UINT8 RedFieldPosition; // Bit posn of lsb of red mask + UINT8 GreenMaskSize; // Size of direct color green mask + UINT8 GreenFieldPosition; // Bit posn of lsb of green mask + UINT8 BlueMaskSize; // Size of direct color blue mask + UINT8 BlueFieldPosition; // Bit posn of lsb of blue mask + UINT8 RsvdMaskSize; // Size of direct color res mask + UINT8 RsvdFieldPosition; // Bit posn of lsb of res mask + UINT8 DirectColorModeInfo; // Direct color 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/scan 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 posiiton of lsb of red mask (linear modes) + UINT8 LinGreenMaskSize; // Size of direct color green mask (linear mode) + UINT8 LinGreenFieldPosition; // Bit posiiton of lsb of green mask (linear modes) + UINT8 LinBlueMaskSize; // Size of direct color blue mask (linear mode) + UINT8 LinBlueFieldPosition; // Bit posiiton of lsb of blue mask (linear modes) + UINT8 LinRsvdMaskSize; // Size of direct color reserved mask (linear mode) + UINT8 LinRsvdFieldPosition; // Bit posiiton 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 definitions +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_HARDWARE 0x0001 // 0: Mode not supported in handware +// 1: Mode supported in handware +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_TTY 0x0004 // 0: TTY Output functions 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 mode +// 1: Graphics mode +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_VGA 0x0020 // 0: VGA compatible mode +// 1: Not a VGA compatible mode +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_WINDOWED 0x0040 // 0: VGA 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 double scan mode available +// 1: Double scan mode available +// +#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_INTERLACED 0x0200 // 0: No interlaced 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 definitions +// +#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 is not readable +// 1: Window is readable +// +#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_WRITABLE 0x04 // 0: Window is not writable +// 1: Window is writable +// +// Super VGA Mode Information Block DirectColorMode field bit definitions +// +#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: Bits in Rsvd field are reserved +// 1: Bits in Rsdv field are usable +// +// Super VGA Memory Models +// +typedef enum { + MemPL = 3, // Planar memory model + MemPK = 4, // Packed pixel memory model + MemRGB= 6, // Direct color RGB memory model + MemYUV= 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 mode is not souble scanned +// 1: Graphics mode is double scanned +// +#define VESA_BIOS_EXTENSIONS_CRTC_FLAGSINTERLACED 0x02 // 0: Graphics mode is not interlaced +// 1: Graphics mode is interlaced +// +#define VESA_BIOS_EXTENSIONS_CRTC_HORIZONTAL_SYNC_NEGATIVE 0x04 // 0: Horizontal sync polarity is positive(+) +// 0: Horizontal sync polarity is negative(-) +// +#define VESA_BIOS_EXTENSIONS_CRTC_VERITICAL_SYNC_NEGATIVE 0x08 // 0: Verical sync polarity is positive(+) +// 0: Verical sync polarity is negative(-) +// +// Turn off byte packing of data structures +// +#pragma pack() + +#endif diff --git a/Legacy/BootPlatform/CpuDxe/CpuDxe.c b/Legacy/BootPlatform/CpuDxe/CpuDxe.c new file mode 100644 index 0000000000000000000000000000000000000000..7aec4f9732b3d4d38e75cf81387ebcc02f75520b --- /dev/null +++ b/Legacy/BootPlatform/CpuDxe/CpuDxe.c @@ -0,0 +1,1262 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + CpuDxe.c + +Abstract: + +--*/ + +#include "CpuDxe.h" + +// +// Global Variables +// + +UINT32 CONST mExceptionCodeSize = 9; +BOOLEAN mInterruptState = FALSE; +UINTN mTimerVector = 0; +volatile EFI_CPU_INTERRUPT_HANDLER mTimerHandler = NULL; +EFI_LEGACY_8259_PROTOCOL *gLegacy8259 = NULL; +THUNK_CONTEXT mThunkContext; + +VOID +InitializeBiosIntCaller ( + VOID + ); + +// +// The Cpu Architectural Protocol that this Driver produces +// +EFI_HANDLE mHandle = NULL; +EFI_CPU_ARCH_PROTOCOL mCpu = { + CpuFlushCpuDataCache, ///< Used in LightMemoryTest + CpuEnableInterrupt, ///< Not-used in LegacyBoot + CpuDisableInterrupt, + CpuGetInterruptState, + CpuInit, + CpuRegisterInterruptHandler, ///< Used in 8254Timer, HPETTimer, + CpuGetTimerValue, + CpuSetMemoryAttributes, + 1, ///< NumberOfTimers + 4, ///< DmaBufferAlignment +}; + +EFI_STATUS +EFIAPI +CpuFlushCpuDataCache ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType + ) +/*++ + +Routine Description: + Flush CPU data cache. If the instruction cache is fully coherent + with all DMA operations then function can just return EFI_SUCCESS. + +Arguments: + This - Protocol instance structure + Start - Physical address to start flushing from. + Length - Number of bytes to flush. Round up to chipset + granularity. + FlushType - Specifies the type of flush operation to perform. + +Returns: + + EFI_SUCCESS - If cache was flushed + EFI_UNSUPPORTED - If flush type is not supported. + EFI_DEVICE_ERROR - If requested range could not be flushed. + +--*/ +{ + if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) { + AsmWbinvd (); + return EFI_SUCCESS; + } else if (FlushType == EfiCpuFlushTypeInvalidate) { + AsmInvd (); + return EFI_SUCCESS; + } else { + return EFI_UNSUPPORTED; + } +} + + +EFI_STATUS +EFIAPI +CpuEnableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ) +/*++ + +Routine Description: + Enables CPU interrupts. + +Arguments: + This - Protocol instance structure + +Returns: + EFI_SUCCESS - If interrupts were enabled in the CPU + EFI_DEVICE_ERROR - If interrupts could not be enabled on the CPU. + +--*/ +{ + EnableInterrupts (); + + mInterruptState = TRUE; + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +CpuDisableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ) +/*++ + +Routine Description: + Disables CPU interrupts. + +Arguments: + This - Protocol instance structure + +Returns: + EFI_SUCCESS - If interrupts were disabled in the CPU. + EFI_DEVICE_ERROR - If interrupts could not be disabled on the CPU. + +--*/ +{ + DisableInterrupts (); + + mInterruptState = FALSE; + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +CpuGetInterruptState ( + IN EFI_CPU_ARCH_PROTOCOL *This, + OUT BOOLEAN *State + ) +/*++ + +Routine Description: + Return the state of interrupts. + +Arguments: + This - Protocol instance structure + State - Pointer to the CPU's current interrupt state + +Returns: + EFI_SUCCESS - If interrupts were disabled in the CPU. + EFI_INVALID_PARAMETER - State is NULL. + +--*/ +{ + if (State == NULL) { + return EFI_INVALID_PARAMETER; + } + + *State = mInterruptState; + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +CpuInit ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_CPU_INIT_TYPE InitType + ) + +/*++ + +Routine Description: + Generates an INIT to the CPU + +Arguments: + This - Protocol instance structure + InitType - Type of CPU INIT to perform + +Returns: + EFI_SUCCESS - If CPU INIT occurred. This value should never be + seen. + EFI_DEVICE_ERROR - If CPU INIT failed. + EFI_NOT_SUPPORTED - Requested type of CPU INIT not supported. + +--*/ +{ + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +CpuRegisterInterruptHandler ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +/*++ + +Routine Description: + Registers a function to be called from the CPU interrupt handler. + +Arguments: + This - Protocol instance structure + InterruptType - Defines which interrupt to hook. IA-32 valid range + is 0x00 through 0xFF + InterruptHandler - A pointer to a function of type + EFI_CPU_INTERRUPT_HANDLER that is called when a + processor interrupt occurs. A null pointer + is an error condition. + +Returns: + EFI_SUCCESS - If handler installed or uninstalled. + EFI_ALREADY_STARTED - InterruptHandler is not NULL, and a handler for + InterruptType was previously installed + EFI_INVALID_PARAMETER - InterruptHandler is NULL, and a handler for + InterruptType was not previously installed. + EFI_UNSUPPORTED - The interrupt specified by InterruptType is not + supported. + +--*/ +{ + if ((InterruptType < 0) || (InterruptType >= INTERRUPT_VECTOR_NUMBER)) { + return EFI_UNSUPPORTED; + } + if ((UINTN)(UINT32)InterruptType != mTimerVector) { + return EFI_UNSUPPORTED; + } + if ((mTimerHandler == NULL) && (InterruptHandler == NULL)) { + return EFI_INVALID_PARAMETER; + } else if ((mTimerHandler != NULL) && (InterruptHandler != NULL)) { + return EFI_ALREADY_STARTED; + } + mTimerHandler = InterruptHandler; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CpuGetTimerValue ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN UINT32 TimerIndex, + OUT UINT64 *TimerValue, + OUT UINT64 *TimerPeriod OPTIONAL + ) +/*++ + +Routine Description: + Returns a timer value from one of the CPU's internal timers. There is no + inherent time interval between ticks but is a function of the CPU + frequency. + +Arguments: + This - Protocol instance structure + TimerIndex - Specifies which CPU timer ie requested + TimerValue - Pointer to the returned timer value + TimerPeriod - + +Returns: + EFI_SUCCESS - If the CPU timer count was returned. + EFI_UNSUPPORTED - If the CPU does not have any readable timers + EFI_DEVICE_ERROR - If an error occurred reading the timer. + EFI_INVALID_PARAMETER - TimerIndex is not valid + +--*/ +{ + if (TimerValue == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (TimerIndex == 0) { + *TimerValue = AsmReadTsc (); + if (TimerPeriod != NULL) { + // + // BugBug: Hard coded. Don't know how to do this generically + // + *TimerPeriod = 1000000000; + } + return EFI_SUCCESS; + } + return EFI_INVALID_PARAMETER; +} + +EFI_STATUS +EFIAPI +CpuSetMemoryAttributes ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + Set memory cacheability attributes for given range of memory + +Arguments: + This - Protocol instance structure + BaseAddress - Specifies the start address of the memory range + Length - Specifies the length of the memory range + Attributes - The memory cacheability for the memory range + +Returns: + EFI_SUCCESS - If the cacheability of that memory range is set successfully + EFI_UNSUPPORTED - If the desired operation cannot be done + EFI_INVALID_PARAMETER - The input parameter is not correct, such as Length = 0 + +--*/ +{ + return EFI_UNSUPPORTED; +} + +#if CPU_EXCEPTION_DEBUG_OUTPUT +VOID +DumpExceptionDataDebugOut ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + UINT32 ErrorCodeFlag; + + ErrorCodeFlag = 0x00027d00; + +#ifdef MDE_CPU_IA32 + DEBUG (( + EFI_D_ERROR, + "!!!! IA32 Exception Type - %08x !!!!\n", + InterruptType + )); + DEBUG (( + EFI_D_ERROR, + "EIP - %08x, CS - %08x, EFLAGS - %08x\n", + SystemContext.SystemContextIa32->Eip, + SystemContext.SystemContextIa32->Cs, + SystemContext.SystemContextIa32->Eflags + )); + if (ErrorCodeFlag & (1 << InterruptType)) { + DEBUG (( + EFI_D_ERROR, + "ExceptionData - %08x\n", + SystemContext.SystemContextIa32->ExceptionData + )); + } + DEBUG (( + EFI_D_ERROR, + "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n", + SystemContext.SystemContextIa32->Eax, + SystemContext.SystemContextIa32->Ecx, + SystemContext.SystemContextIa32->Edx, + SystemContext.SystemContextIa32->Ebx + )); + DEBUG (( + EFI_D_ERROR, + "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n", + SystemContext.SystemContextIa32->Esp, + SystemContext.SystemContextIa32->Ebp, + SystemContext.SystemContextIa32->Esi, + SystemContext.SystemContextIa32->Edi + )); + DEBUG (( + EFI_D_ERROR, + "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n", + SystemContext.SystemContextIa32->Ds, + SystemContext.SystemContextIa32->Es, + SystemContext.SystemContextIa32->Fs, + SystemContext.SystemContextIa32->Gs, + SystemContext.SystemContextIa32->Ss + )); + DEBUG (( + EFI_D_ERROR, + "GDTR - %08x %08x, IDTR - %08x %08x\n", + SystemContext.SystemContextIa32->Gdtr[0], + SystemContext.SystemContextIa32->Gdtr[1], + SystemContext.SystemContextIa32->Idtr[0], + SystemContext.SystemContextIa32->Idtr[1] + )); + DEBUG (( + EFI_D_ERROR, + "LDTR - %08x, TR - %08x\n", + SystemContext.SystemContextIa32->Ldtr, + SystemContext.SystemContextIa32->Tr + )); + DEBUG (( + EFI_D_ERROR, + "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n", + SystemContext.SystemContextIa32->Cr0, + SystemContext.SystemContextIa32->Cr2, + SystemContext.SystemContextIa32->Cr3, + SystemContext.SystemContextIa32->Cr4 + )); + DEBUG (( + EFI_D_ERROR, + "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n", + SystemContext.SystemContextIa32->Dr0, + SystemContext.SystemContextIa32->Dr1, + SystemContext.SystemContextIa32->Dr2, + SystemContext.SystemContextIa32->Dr3 + )); + DEBUG (( + EFI_D_ERROR, + "DR6 - %08x, DR7 - %08x\n", + SystemContext.SystemContextIa32->Dr6, + SystemContext.SystemContextIa32->Dr7 + )); +#else + DEBUG (( + EFI_D_ERROR, + "!!!! X64 Exception Type - %016lx !!!!\n", + (UINT64)InterruptType + )); + DEBUG (( + EFI_D_ERROR, + "RIP - %016lx, CS - %016lx, RFLAGS - %016lx\n", + SystemContext.SystemContextX64->Rip, + SystemContext.SystemContextX64->Cs, + SystemContext.SystemContextX64->Rflags + )); + if (ErrorCodeFlag & (1 << InterruptType)) { + DEBUG (( + EFI_D_ERROR, + "ExceptionData - %016lx\n", + SystemContext.SystemContextX64->ExceptionData + )); + } + DEBUG (( + EFI_D_ERROR, + "RAX - %016lx, RCX - %016lx, RDX - %016lx\n", + SystemContext.SystemContextX64->Rax, + SystemContext.SystemContextX64->Rcx, + SystemContext.SystemContextX64->Rdx + )); + DEBUG (( + EFI_D_ERROR, + "RBX - %016lx, RSP - %016lx, RBP - %016lx\n", + SystemContext.SystemContextX64->Rbx, + SystemContext.SystemContextX64->Rsp, + SystemContext.SystemContextX64->Rbp + )); + DEBUG (( + EFI_D_ERROR, + "RSI - %016lx, RDI - %016lx\n", + SystemContext.SystemContextX64->Rsi, + SystemContext.SystemContextX64->Rdi + )); + DEBUG (( + EFI_D_ERROR, + "R8 - %016lx, R9 - %016lx, R10 - %016lx\n", + SystemContext.SystemContextX64->R8, + SystemContext.SystemContextX64->R9, + SystemContext.SystemContextX64->R10 + )); + DEBUG (( + EFI_D_ERROR, + "R11 - %016lx, R12 - %016lx, R13 - %016lx\n", + SystemContext.SystemContextX64->R11, + SystemContext.SystemContextX64->R12, + SystemContext.SystemContextX64->R13 + )); + DEBUG (( + EFI_D_ERROR, + "R14 - %016lx, R15 - %016lx\n", + SystemContext.SystemContextX64->R14, + SystemContext.SystemContextX64->R15 + )); + DEBUG (( + EFI_D_ERROR, + "DS - %016lx, ES - %016lx, FS - %016lx\n", + SystemContext.SystemContextX64->Ds, + SystemContext.SystemContextX64->Es, + SystemContext.SystemContextX64->Fs + )); + DEBUG (( + EFI_D_ERROR, + "GS - %016lx, SS - %016lx\n", + SystemContext.SystemContextX64->Gs, + SystemContext.SystemContextX64->Ss + )); + DEBUG (( + EFI_D_ERROR, + "GDTR - %016lx %016lx, LDTR - %016lx\n", + SystemContext.SystemContextX64->Gdtr[0], + SystemContext.SystemContextX64->Gdtr[1], + SystemContext.SystemContextX64->Ldtr + )); + DEBUG (( + EFI_D_ERROR, + "IDTR - %016lx %016lx, TR - %016lx\n", + SystemContext.SystemContextX64->Idtr[0], + SystemContext.SystemContextX64->Idtr[1], + SystemContext.SystemContextX64->Tr + )); + DEBUG (( + EFI_D_ERROR, + "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n", + SystemContext.SystemContextX64->Cr0, + SystemContext.SystemContextX64->Cr2, + SystemContext.SystemContextX64->Cr3 + )); + DEBUG (( + EFI_D_ERROR, + "CR4 - %016lx, CR8 - %016lx\n", + SystemContext.SystemContextX64->Cr4, + SystemContext.SystemContextX64->Cr8 + )); + DEBUG (( + EFI_D_ERROR, + "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n", + SystemContext.SystemContextX64->Dr0, + SystemContext.SystemContextX64->Dr1, + SystemContext.SystemContextX64->Dr2 + )); + DEBUG (( + EFI_D_ERROR, + "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n", + SystemContext.SystemContextX64->Dr3, + SystemContext.SystemContextX64->Dr6, + SystemContext.SystemContextX64->Dr7 + )); +#endif + return ; +} +#endif + +STATIC +CHAR16* +DumpMemoryVgaOut ( + IN CHAR16* VideoBuffer, + IN UINTN ColumnMax, + IN UINTN MemoryAddress, + IN UINTN Count + ) +{ + UINT32 Space; + UINT32 InLine; + CHAR16 *Line; + UINT8 CONST *Data; + + Space = 8U; + InLine = 4U; + Line = VideoBuffer; + Data = (UINT8 CONST*) MemoryAddress; + + while (Count) { + UnicodeSPrintAsciiFormat ( + VideoBuffer, + 3U * sizeof (CHAR16), + "%02x", + (UINTN) *Data + ); + VideoBuffer += 2; + --Space; + if (!Space) { + *(CHAR8*) VideoBuffer = ' '; + ++VideoBuffer; + Space = 8U; + --InLine; + if (!InLine) { + Line += ColumnMax; + VideoBuffer = Line; + InLine = 4U; + } + } + ++Data; + --Count; + } + if (VideoBuffer != Line) { + Line += ColumnMax; + VideoBuffer = Line; + } + return VideoBuffer; +} + +VOID +DumpExceptionDataVgaOut ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + UINTN COLUMN_MAX; + UINTN ROW_MAX; + UINT32 ErrorCodeFlag; + CHAR16 *VideoBufferBase; + CHAR16 *VideoBuffer; + UINTN Index; + + COLUMN_MAX = 80; + ROW_MAX = 25; + ErrorCodeFlag = 0x00027d00; + VideoBufferBase = (CHAR16 *) (UINTN) 0xb8000; + VideoBuffer = (CHAR16 *) (UINTN) 0xb8000; + +#ifdef MDE_CPU_IA32 + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "!!!! IA32 Exception Type - %08x !!!!", + InterruptType + ); + VideoBuffer += COLUMN_MAX; + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "EIP - %08x, CS - %08x, EFLAGS - %08x", + SystemContext.SystemContextIa32->Eip, + SystemContext.SystemContextIa32->Cs, + SystemContext.SystemContextIa32->Eflags + ); + VideoBuffer += COLUMN_MAX; + if (ErrorCodeFlag & (1 << InterruptType)) { + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "ExceptionData - %08x", + SystemContext.SystemContextIa32->ExceptionData + ); + VideoBuffer += COLUMN_MAX; + } + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x", + SystemContext.SystemContextIa32->Eax, + SystemContext.SystemContextIa32->Ecx, + SystemContext.SystemContextIa32->Edx, + SystemContext.SystemContextIa32->Ebx + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x", + SystemContext.SystemContextIa32->Esp, + SystemContext.SystemContextIa32->Ebp, + SystemContext.SystemContextIa32->Esi, + SystemContext.SystemContextIa32->Edi + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x", + SystemContext.SystemContextIa32->Ds, + SystemContext.SystemContextIa32->Es, + SystemContext.SystemContextIa32->Fs, + SystemContext.SystemContextIa32->Gs, + SystemContext.SystemContextIa32->Ss + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "GDTR - %08x %08x, IDTR - %08x %08x", + SystemContext.SystemContextIa32->Gdtr[0], + SystemContext.SystemContextIa32->Gdtr[1], + SystemContext.SystemContextIa32->Idtr[0], + SystemContext.SystemContextIa32->Idtr[1] + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "LDTR - %08x, TR - %08x", + SystemContext.SystemContextIa32->Ldtr, + SystemContext.SystemContextIa32->Tr + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x", + SystemContext.SystemContextIa32->Cr0, + SystemContext.SystemContextIa32->Cr2, + SystemContext.SystemContextIa32->Cr3, + SystemContext.SystemContextIa32->Cr4 + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x", + SystemContext.SystemContextIa32->Dr0, + SystemContext.SystemContextIa32->Dr1, + SystemContext.SystemContextIa32->Dr2, + SystemContext.SystemContextIa32->Dr3 + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "DR6 - %08x, DR7 - %08x", + SystemContext.SystemContextIa32->Dr6, + SystemContext.SystemContextIa32->Dr7 + ); + VideoBuffer += COLUMN_MAX; + VideoBuffer = DumpMemoryVgaOut ( + VideoBuffer, + COLUMN_MAX, + (UINTN) SystemContext.SystemContextIa32->Esp, + 128U + ); + VideoBuffer = DumpMemoryVgaOut ( + VideoBuffer, + COLUMN_MAX, + (UINTN) SystemContext.SystemContextIa32->Eip - 64U, + 128U + ); +#else + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "!!!! X64 Exception Type - %016lx !!!!", + (UINT64)InterruptType + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "RIP - %016lx, CS - %016lx, RFLAGS - %016lx", + SystemContext.SystemContextX64->Rip, + SystemContext.SystemContextX64->Cs, + SystemContext.SystemContextX64->Rflags + ); + VideoBuffer += COLUMN_MAX; + + if (ErrorCodeFlag & (1 << InterruptType)) { + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "ExceptionData - %016lx", + SystemContext.SystemContextX64->ExceptionData + ); + VideoBuffer += COLUMN_MAX; + } + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "RAX - %016lx, RCX - %016lx, RDX - %016lx", + SystemContext.SystemContextX64->Rax, + SystemContext.SystemContextX64->Rcx, + SystemContext.SystemContextX64->Rdx + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "RBX - %016lx, RSP - %016lx, RBP - %016lx", + SystemContext.SystemContextX64->Rbx, + SystemContext.SystemContextX64->Rsp, + SystemContext.SystemContextX64->Rbp + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "RSI - %016lx, RDI - %016lx", + SystemContext.SystemContextX64->Rsi, + SystemContext.SystemContextX64->Rdi + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "R8 - %016lx, R9 - %016lx, R10 - %016lx", + SystemContext.SystemContextX64->R8, + SystemContext.SystemContextX64->R9, + SystemContext.SystemContextX64->R10 + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "R11 - %016lx, R12 - %016lx, R13 - %016lx", + SystemContext.SystemContextX64->R11, + SystemContext.SystemContextX64->R12, + SystemContext.SystemContextX64->R13 + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "R14 - %016lx, R15 - %016lx", + SystemContext.SystemContextX64->R14, + SystemContext.SystemContextX64->R15 + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "DS - %016lx, ES - %016lx, FS - %016lx", + SystemContext.SystemContextX64->Ds, + SystemContext.SystemContextX64->Es, + SystemContext.SystemContextX64->Fs + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "GS - %016lx, SS - %016lx", + SystemContext.SystemContextX64->Gs, + SystemContext.SystemContextX64->Ss + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "GDTR - %016lx %016lx, LDTR - %016lx", + SystemContext.SystemContextX64->Gdtr[0], + SystemContext.SystemContextX64->Gdtr[1], + SystemContext.SystemContextX64->Ldtr + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "IDTR - %016lx %016lx, TR - %016lx", + SystemContext.SystemContextX64->Idtr[0], + SystemContext.SystemContextX64->Idtr[1], + SystemContext.SystemContextX64->Tr + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx", + SystemContext.SystemContextX64->Cr0, + SystemContext.SystemContextX64->Cr2, + SystemContext.SystemContextX64->Cr3 + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "CR4 - %016lx, CR8 - %016lx", + SystemContext.SystemContextX64->Cr4, + SystemContext.SystemContextX64->Cr8 + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx", + SystemContext.SystemContextX64->Dr0, + SystemContext.SystemContextX64->Dr1, + SystemContext.SystemContextX64->Dr2 + ); + VideoBuffer += COLUMN_MAX; + + UnicodeSPrintAsciiFormat ( + VideoBuffer, + COLUMN_MAX * sizeof (CHAR16), + "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx", + SystemContext.SystemContextX64->Dr3, + SystemContext.SystemContextX64->Dr6, + SystemContext.SystemContextX64->Dr7 + ); + VideoBuffer += COLUMN_MAX; + VideoBuffer = DumpMemoryVgaOut ( + VideoBuffer, + COLUMN_MAX, + (UINTN) SystemContext.SystemContextX64->Rsp, + 128U + ); + VideoBuffer = DumpMemoryVgaOut ( + VideoBuffer, + COLUMN_MAX, + (UINTN) SystemContext.SystemContextX64->Rip - 64U, + 128U + ); +#endif + + for (Index = 0; Index < COLUMN_MAX * ROW_MAX; Index ++) { + if (Index > (UINTN)(VideoBuffer - VideoBufferBase)) { + VideoBufferBase[Index] = 0x0c20; + } else { + VideoBufferBase[Index] |= 0x0c00; + } + } + + return ; +} + +#if CPU_EXCEPTION_VGA_SWITCH +UINT16 +SwitchVideoMode ( + UINT16 NewVideoMode + ) +/*++ +Description + Switch Video Mode from current mode to new mode, and return the old mode. + Use Thuink + +Arguments + NewVideoMode - new video mode want to set + +Return + UINT16 - (UINT16) -1 indicates failure + Other value indicates the old mode, which can be used for restore later + +--*/ +{ + EFI_IA32_REGISTER_SET Regs; + UINT16 OriginalVideoMode = (UINT16) -1; + + + // + // Set new video mode + // + if (NewVideoMode < 0x100) { + // + // Set the 80x25 Text VGA Mode: Assume successful always + // + // VIDEO - SET VIDEO MODE + // AH = 00h + // AL = desired video mode (see #0009) + // Return:AL = video mode flag (Phoenix, AMI BIOS) + // 20h mode > 7 + // 30h modes 0-5 and 7 + // 3Fh mode 6 + // AL = CRT controller mode byte (Phoenix 386 BIOS v1.10) + // + gBS->SetMem (&Regs, sizeof (Regs), 0); + Regs.H.AH = 0x00; + Regs.H.AL = (UINT8) NewVideoMode; + LegacyBiosInt86 (0x10, &Regs); + + // + // VIDEO - TEXT-MODE CHARGEN - LOAD ROM 8x16 CHARACTER SET (VGA) + // AX = 1114h + // BL = block to load + // Return:Nothing + // + gBS->SetMem (&Regs, sizeof (Regs), 0); + Regs.H.AH = 0x11; + Regs.H.AL = 0x14; + Regs.H.BL = 0; + LegacyBiosInt86 (0x10, &Regs); + } else { + // + // VESA SuperVGA BIOS - SET SuperVGA VIDEO MODE + // AX = 4F02h + // BX = mode (see #0082,#0083) + // bit 15 set means don't clear video memory + // bit 14 set means enable linear framebuffer mode (VBE v2.0+) + // Return:AL = 4Fh if function supported + // AH = status + // 00h successful + // 01h failed + // + gBS->SetMem (&Regs, sizeof (Regs), 0); + Regs.X.AX = 0x4F02; + Regs.X.BX = NewVideoMode; + LegacyBiosInt86 (0x10, &Regs); + if (Regs.X.AX != 0x004F) { + // + // SORRY: Cannot set to video mode! + // + return (UINT16) -1; + } + } + + return OriginalVideoMode; +} +#endif + +VOID +EFIAPI +ExceptionHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ +#if CPU_EXCEPTION_VGA_SWITCH + UINT16 VideoMode; +#endif + +#if CPU_EXCEPTION_DEBUG_OUTPUT + DumpExceptionDataDebugOut (InterruptType, SystemContext); +#endif + +#if CPU_EXCEPTION_VGA_SWITCH + // + // Switch to text mode for RED-SCREEN output + // + VideoMode = SwitchVideoMode (0x83); +#endif + + DumpExceptionDataVgaOut (InterruptType, SystemContext); + + // + // Use this macro to hang so that the compiler does not optimize out + // the following RET instructions. This allows us to return if we + // have a debugger attached. + // + CpuDeadLoop (); + +#if CPU_EXCEPTION_VGA_SWITCH + // + // Switch back to the old video mode + // + if (VideoMode != (UINT16)-1) { + SwitchVideoMode (VideoMode); + } +#endif + + return ; +} + +VOID +EFIAPI +TimerHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + if (mTimerHandler != NULL) { + mTimerHandler (InterruptType, SystemContext); + } +} + +EFI_STATUS +EFIAPI +InitializeCpu ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Initialize the state information for the CPU Architectural Protocol + +Arguments: + ImageHandle of the loaded driver + Pointer to the System Table + +Returns: + EFI_SUCCESS - thread can be successfully created + EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure + EFI_DEVICE_ERROR - cannot create the thread + +--*/ +{ + EFI_STATUS Status; + EFI_8259_IRQ Irq; + UINT32 InterruptVector; + + // + // Find the Legacy8259 protocol. + // + Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &gLegacy8259); + ASSERT_EFI_ERROR (Status); + + // + // Get the interrupt vector number corresponding to IRQ0 from the 8259 driver + // + Status = gLegacy8259->GetVector (gLegacy8259, Efi8259Irq0, (UINT8 *) &mTimerVector); + ASSERT_EFI_ERROR (Status); + + // + // Reload GDT, IDT + // + InitDescriptor (); + + // + // Install Exception Handler (0x00 ~ 0x1F) + // + for (InterruptVector = 0; InterruptVector < 0x20; InterruptVector++) { + InstallInterruptHandler ( + InterruptVector, + (VOID (EFIAPI *)(VOID)) (UINTN) ((UINTN) SystemExceptionHandler + mExceptionCodeSize * InterruptVector) + ); + } + + // + // Install Timer Handler + // + InstallInterruptHandler (mTimerVector, SystemTimerHandler); + ((volatile UINT8 *)(UINTN)&SystemTimerHandler)[3] = (UINT8)mTimerVector; + + // + // BUGBUG: We add all other interrupt vector + // + for (Irq = Efi8259Irq1; Irq <= Efi8259Irq15; Irq++) { + InterruptVector = 0; + Status = gLegacy8259->GetVector (gLegacy8259, Irq, (UINT8 *) &InterruptVector); + ASSERT_EFI_ERROR (Status); + InstallInterruptHandler (InterruptVector, SystemTimerHandler); + } + + InitializeBiosIntCaller(); + + // + // Install CPU Architectural Protocol and the thunk protocol + // + mHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &mHandle, + &gEfiCpuArchProtocolGuid, + &mCpu, + NULL + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + +VOID +InitializeBiosIntCaller ( + VOID + ) +{ + EFI_STATUS Status; + UINT32 RealModeBufferSize; + UINT32 ExtraStackSize; + EFI_PHYSICAL_ADDRESS LegacyRegionBase; + UINT32 LegacyRegionSize; + + // + // Get LegacyRegion + // + AsmGetThunk16Properties (&RealModeBufferSize, &ExtraStackSize); + LegacyRegionSize = (((RealModeBufferSize + ExtraStackSize) / EFI_PAGE_SIZE) + 1) * EFI_PAGE_SIZE; + LegacyRegionBase = 0x0C0000; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + EFI_SIZE_TO_PAGES(LegacyRegionSize), + &LegacyRegionBase + ); + ASSERT_EFI_ERROR (Status); + + mThunkContext.RealModeBuffer = (VOID*)(UINTN)LegacyRegionBase; + mThunkContext.RealModeBufferSize = LegacyRegionSize; + mThunkContext.ThunkAttributes = 3; + AsmPrepareThunk16(&mThunkContext); + +} + +BOOLEAN +EFIAPI +LegacyBiosInt86 ( + IN UINT8 BiosInt, + IN EFI_IA32_REGISTER_SET *Regs + ) +{ + UINTN Status; + BOOLEAN InterruptsEnabled; + IA32_REGISTER_SET ThunkRegSet; + BOOLEAN Ret; + UINT16 *Stack16; + + if (!gLegacy8259 || !mThunkContext.RealModeBuffer) { + return FALSE; + } + Regs->X.Flags.Reserved1 = 1; + Regs->X.Flags.Reserved2 = 0; + Regs->X.Flags.Reserved3 = 0; + Regs->X.Flags.Reserved4 = 0; + Regs->X.Flags.IOPL = 3; + Regs->X.Flags.NT = 0; + Regs->X.Flags.IF = 1; + Regs->X.Flags.TF = 0; + Regs->X.Flags.CF = 0; + + ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet)); + ThunkRegSet.E.EDI = Regs->E.EDI; + ThunkRegSet.E.ESI = Regs->E.ESI; + ThunkRegSet.E.EBP = Regs->E.EBP; + ThunkRegSet.E.EBX = Regs->E.EBX; + ThunkRegSet.E.EDX = Regs->E.EDX; + ThunkRegSet.E.ECX = Regs->E.ECX; + ThunkRegSet.E.EAX = Regs->E.EAX; + ThunkRegSet.E.DS = Regs->E.DS; + ThunkRegSet.E.ES = Regs->E.ES; + + CopyMem (&(ThunkRegSet.E.EFLAGS), &(Regs->E.EFlags), sizeof (UINT32)); + + // + // The call to Legacy16 is a critical section to EFI + // + InterruptsEnabled = SaveAndDisableInterrupts (); + + // + // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. + // + Status = gLegacy8259->SetMode (gLegacy8259, Efi8259LegacyMode, NULL, NULL); + ASSERT_EFI_ERROR (Status); + + Stack16 = (UINT16 *)((UINT8 *) mThunkContext.RealModeBuffer + mThunkContext.RealModeBufferSize - sizeof (UINT16)); + Stack16 -= sizeof (ThunkRegSet.E.EFLAGS) / sizeof (UINT16); + CopyMem (Stack16, &ThunkRegSet.E.EFLAGS, sizeof (ThunkRegSet.E.EFLAGS)); + + ThunkRegSet.E.SS = (UINT16) (((UINTN) Stack16 >> 16) << 12); + ThunkRegSet.E.ESP = (UINT16) (UINTN) Stack16; + ThunkRegSet.E.Eip = (UINT16)((volatile UINT32 *)NULL)[BiosInt]; + ThunkRegSet.E.CS = (UINT16)(((volatile UINT32 *)NULL)[BiosInt] >> 16); + + mThunkContext.RealModeState = &ThunkRegSet; + AsmThunk16 (&mThunkContext); + + // + // Restore protected mode interrupt state + // + Status = gLegacy8259->SetMode (gLegacy8259, Efi8259ProtectedMode, NULL, NULL); + ASSERT_EFI_ERROR (Status); + + // + // End critical section + // + SetInterruptState (InterruptsEnabled); + + Regs->E.EDI = ThunkRegSet.E.EDI; + Regs->E.ESI = ThunkRegSet.E.ESI; + Regs->E.EBP = ThunkRegSet.E.EBP; + Regs->E.EBX = ThunkRegSet.E.EBX; + Regs->E.EDX = ThunkRegSet.E.EDX; + Regs->E.ECX = ThunkRegSet.E.ECX; + Regs->E.EAX = ThunkRegSet.E.EAX; + Regs->E.SS = ThunkRegSet.E.SS; + Regs->E.CS = ThunkRegSet.E.CS; + Regs->E.DS = ThunkRegSet.E.DS; + Regs->E.ES = ThunkRegSet.E.ES; + + CopyMem (&(Regs->E.EFlags), &(ThunkRegSet.E.EFLAGS), sizeof (UINT32)); + + Ret = (BOOLEAN) (Regs->E.EFlags.CF == 1); + + return Ret; +} diff --git a/Legacy/BootPlatform/CpuDxe/CpuDxe.h b/Legacy/BootPlatform/CpuDxe/CpuDxe.h new file mode 100644 index 0000000000000000000000000000000000000000..8d30c7d4a5e3fd3312341f947831050180be70ea --- /dev/null +++ b/Legacy/BootPlatform/CpuDxe/CpuDxe.h @@ -0,0 +1,139 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + CpuDxe.h + +Abstract: + +--*/ +#ifndef _CPU_DXE_H +#define _CPU_DXE_H + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define CPU_EXCEPTION_DEBUG_OUTPUT 0 +#define CPU_EXCEPTION_VGA_SWITCH 1 + +#define INTERRUPT_VECTOR_NUMBER 0x100 + +// +// Function declarations +// +EFI_STATUS +EFIAPI +InitializeCpu ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STATUS +EFIAPI +CpuFlushCpuDataCache ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType + ); + +EFI_STATUS +EFIAPI +CpuEnableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +CpuDisableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +CpuGetInterruptState ( + IN EFI_CPU_ARCH_PROTOCOL *This, + OUT BOOLEAN *State + ); + +EFI_STATUS +EFIAPI +CpuInit ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_CPU_INIT_TYPE InitType + ); + +EFI_STATUS +EFIAPI +CpuRegisterInterruptHandler ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ); + +EFI_STATUS +EFIAPI +CpuGetTimerValue ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN UINT32 TimerIndex, + OUT UINT64 *TimerValue, + OUT UINT64 *TimerPeriod OPTIONAL + ); + +EFI_STATUS +EFIAPI +CpuSetMemoryAttributes( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + +VOID +EFIAPI +InstallInterruptHandler ( + UINTN Vector, + VOID (EFIAPI *Handler)(VOID) + ); + +VOID +EFIAPI +SystemExceptionHandler ( + VOID + ); + +VOID +EFIAPI +SystemTimerHandler ( + VOID + ); + +VOID +EFIAPI +InitDescriptor ( + VOID + ); + +BOOLEAN +EFIAPI +LegacyBiosInt86 ( + IN UINT8 BiosInt, + IN EFI_IA32_REGISTER_SET *Regs + ); + +#endif diff --git a/Legacy/BootPlatform/CpuDxe/CpuDxe.inf b/Legacy/BootPlatform/CpuDxe/CpuDxe.inf new file mode 100644 index 0000000000000000000000000000000000000000..6facb4d6aa9c68fc42781b8989fca245587a4913 --- /dev/null +++ b/Legacy/BootPlatform/CpuDxe/CpuDxe.inf @@ -0,0 +1,54 @@ +## @file +# +# Copyright (c) 2006 - 2010, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# CpuDxe.inf +# +# Abstract: +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CpuDxe + FILE_GUID = 10527025-78B2-4D3E-A9DF-41E75C220F5A + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = InitializeCpu + +[Packages] + OpenCorePkg/OpenDuetPkg.dec + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + PrintLib + UefiBootServicesTableLib + BaseMemoryLib + +[Sources.IA32] + Ia32/CpuInterrupt.nasm + +[Sources.X64] + X64/CpuInterrupt.nasm + +[Sources] + CpuDxe.c + CpuDxe.h + +[Protocols] + gEfiCpuArchProtocolGuid + gEfiLegacy8259ProtocolGuid + +[Depex] + gEfiLegacy8259ProtocolGuid diff --git a/Legacy/BootPlatform/CpuDxe/Ia32/CpuInterrupt.nasm b/Legacy/BootPlatform/CpuDxe/Ia32/CpuInterrupt.nasm new file mode 100644 index 0000000000000000000000000000000000000000..43534687351a2abdb1cb484e7b8e5f991b3e5725 --- /dev/null +++ b/Legacy/BootPlatform/CpuDxe/Ia32/CpuInterrupt.nasm @@ -0,0 +1,845 @@ +; TITLE CpuInterrupt.nasm: +;------------------------------------------------------------------------------ +;* +;* Copyright 2006 - 2010, Intel Corporation +;* All rights reserved. This program and the accompanying materials +;* are licensed and made available under the terms and conditions of the BSD License +;* which accompanies this distribution. The full text of the license may be found at +;* http://opensource.org/licenses/bsd-license.php +;* +;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +;* +;* CpuInterrupt.asm +;* +;* Abstract: +;* +;------------------------------------------------------------------------------ +global ASM_PFX(InstallInterruptHandler) +global ASM_PFX(InitDescriptor) +global ASM_PFX(SystemExceptionHandler) +global ASM_PFX(SystemTimerHandler) + +; +; Workaround for NASM bug emitting incorrect +; pc-relative relocations to mach-o i386 +; object files. +; +%ifidn __OUTPUT_FORMAT__, macho +%macro MakeCall 2 + mov %1, %2 + call %1 +%endmacro +%elifidn __OUTPUT_FORMAT__, macho32 +%macro MakeCall 2 + mov %1, %2 + call %1 +%endmacro +%else +%macro MakeCall 2 + call %2 +%endmacro +%endif + +SECTION .text + +EXTERN ASM_PFX(TimerHandler) +EXTERN ASM_PFX(ExceptionHandler) + + +ASM_PFX(InitDescriptor): + mov eax, GDT_BASE ; EAX=PHYSICAL address of gdt + mov [gdtr + 2], eax ; Put address of gdt into the gdtr + lgdt [gdtr] + + mov eax, IDT_BASE ; EAX=PHYSICAL address of idt + mov [idtr + 2], eax ; Put address of idt into the idtr + lidt [idtr] + ret + + +; VOID +; EFIAPI +; InstallInterruptHandler ( +; UINTN Vector, //6(SP) +; void (*Handler)(void) //10(SP) +; ) +ASM_PFX(InstallInterruptHandler): + push edi + pushfd ; save eflags + cli ; turn off interrupts + sub esp, 6 ; open some space on the stack + mov edi, esp + sidt [edi] ; get fword address of IDT + mov edi, [edi+2] ; move offset of IDT into EDI + add esp, 6 ; correct stack + mov eax, [esp+12] ; Get vector number + shl eax, 3 ; multiply by 8 to get offset + add edi, eax ; add to IDT base to get entry + mov eax, [esp+16] ; load new address into IDT entry + mov word [edi], ax ; write bits 15..0 of offset + shr eax, 16 ; use ax to copy 31..16 to descriptors + mov word [edi+6], ax ; write bits 31..16 of offset + popfd ; restore flags (possible enabling interrupts) + pop edi + ret + +%macro JmpCommonIdtEntry 0 + ; jmp commonIdtEntry - this must be hand coded to keep the assembler from + ; using a 8 bit reletive jump when the entries are + ; within 255 bytes of the common entry. This must + ; be done to maintain the consistency of the size + ; of entry points... + db 0e9h ; jmp 16 bit reletive + dd commonIdtEntry - $ - 4 ; offset to jump to +%endmacro + + ALIGN 02h +ASM_PFX(SystemExceptionHandler): +INT0: + push 0h ; push error code place holder on the stack + push 0h + JmpCommonIdtEntry +; db 0e9h ; jmp 16 bit reletive +; dd commonIdtEntry - $ - 4 ; offset to jump to + +INT1: + push 0h ; push error code place holder on the stack + push 1h + JmpCommonIdtEntry + +INT2: + push 0h ; push error code place holder on the stack + push 2h + JmpCommonIdtEntry + +INT3: + push 0h ; push error code place holder on the stack + push 3h + JmpCommonIdtEntry + +INT4: + push 0h ; push error code place holder on the stack + push 4h + JmpCommonIdtEntry + +INT5: + push 0h ; push error code place holder on the stack + push 5h + JmpCommonIdtEntry + +INT6: + push 0h ; push error code place holder on the stack + push 6h + JmpCommonIdtEntry + +INT7: + push 0h ; push error code place holder on the stack + push 7h + JmpCommonIdtEntry + +INT8: +; Double fault causes an error code to be pushed so no phony push necessary + nop + nop + push 8h + JmpCommonIdtEntry + +INT9: + push 0h ; push error code place holder on the stack + push 9h + JmpCommonIdtEntry + +INT10: +; Invalid TSS causes an error code to be pushed so no phony push necessary + nop + nop + push 10 + JmpCommonIdtEntry + +INT11: +; Segment Not Present causes an error code to be pushed so no phony push necessary + nop + nop + push 11 + JmpCommonIdtEntry + +INT12: +; Stack fault causes an error code to be pushed so no phony push necessary + nop + nop + push 12 + JmpCommonIdtEntry + +INT13: +; GP fault causes an error code to be pushed so no phony push necessary + nop + nop + push 13 + JmpCommonIdtEntry + +INT14: +; Page fault causes an error code to be pushed so no phony push necessary + nop + nop + push 14 + JmpCommonIdtEntry + +INT15: + push 0h ; push error code place holder on the stack + push 15 + JmpCommonIdtEntry + +INT16: + push 0h ; push error code place holder on the stack + push 16 + JmpCommonIdtEntry + +INT17: +; Alignment check causes an error code to be pushed so no phony push necessary + nop + nop + push 17 + JmpCommonIdtEntry + +INT18: + push 0h ; push error code place holder on the stack + push 18 + JmpCommonIdtEntry + +INT19: + push 0h ; push error code place holder on the stack + push 19 + JmpCommonIdtEntry + +INTUnknown: +%rep (32 - 20) + push 0h ; push error code place holder on the stack +; push xxh ; push vector number + db 06ah + db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number + JmpCommonIdtEntry +%endrep +;ENDM + +ASM_PFX(SystemTimerHandler): + push 0 + push 0 ;mTimerVector ;to be patched in Cpu.c + JmpCommonIdtEntry + +commonIdtEntry: +; +---------------------+ +; + EFlags + +; +---------------------+ +; + CS + +; +---------------------+ +; + EIP + +; +---------------------+ +; + Error Code + +; +---------------------+ +; + Vector Number + +; +---------------------+ +; + EBP + +; +---------------------+ <-- EBP + + cli + push ebp + mov ebp, esp + +; +; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32 +; is 16-byte aligned +; + and esp, 0fffffff0h + sub esp, 12 + +;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; + push eax + push ecx + push edx + push ebx + lea ecx, [ebp + 6 * 4] + push ecx ; ESP + push dword [ebp] ; EBP + push esi + push edi + +;; UINT32 Gs, Fs, Es, Ds, Cs, Ss; + mov ax, ss + push eax + movzx eax, word [ebp + 4 * 4] + push eax + mov ax, ds + push eax + mov ax, es + push eax + mov ax, fs + push eax + mov ax, gs + push eax + +;; UINT32 Eip; + push dword [ebp + 3 * 4] + +;; UINT32 Gdtr[2], Idtr[2]; + sub esp, 8 + sidt [esp] + sub esp, 8 + sgdt [esp] + +;; UINT32 Ldtr, Tr; + xor eax, eax + str ax + push eax + sldt eax + push eax + +;; UINT32 EFlags; + push dword [ebp + 5 * 4] + +;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; + mov eax, cr4 + or eax, 208h + mov cr4, eax + push eax + mov eax, cr3 + push eax + mov eax, cr2 + push eax + xor eax, eax + push eax + mov eax, cr0 + push eax + +;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; + mov eax, dr7 + push eax + +;; clear Dr7 while executing debugger itself + xor eax, eax + mov dr7, eax + mov eax, dr6 + push eax + +;; insure all status bits in dr6 are clear... + xor eax, eax + mov dr6, eax + mov eax, dr3 + push eax + mov eax, dr2 + push eax + mov eax, dr1 + push eax + mov eax, dr0 + push eax + +;; FX_SAVE_STATE_IA32 FxSaveState; + sub esp, 512 + mov edi, esp + db 0fh, 0aeh, 00000111y ;fxsave [edi] + +;; UINT32 ExceptionData; + push dword [ebp + 2 * 4] + +;; Prepare parameter and call + mov edx, esp + push edx + mov eax, dword [ebp + 1 * 4] + push eax + cmp eax, 32 + jb CallException + MakeCall eax, ASM_PFX(TimerHandler) + jmp ExceptionDone +CallException: + MakeCall eax, ASM_PFX(ExceptionHandler) +ExceptionDone: + add esp, 8 + + cli +;; UINT32 ExceptionData; + add esp, 4 + +;; FX_SAVE_STATE_IA32 FxSaveState; + mov esi, esp + db 0fh, 0aeh, 00001110y ; fxrstor [esi] + add esp, 512 + +;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; + pop eax + mov dr0, eax + pop eax + mov dr1, eax + pop eax + mov dr2, eax + pop eax + mov dr3, eax +;; skip restore of dr6. We cleared dr6 during the context save. + add esp, 4 + pop eax + mov dr7, eax + +;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; + pop eax + mov cr0, eax + add esp, 4 ; not for Cr1 + pop eax + mov cr2, eax + pop eax + mov cr3, eax + pop eax + mov cr4, eax + +;; UINT32 EFlags; + pop dword [ebp + 5 * 4] + +;; UINT32 Ldtr, Tr; +;; UINT32 Gdtr[2], Idtr[2]; +;; Best not let anyone mess with these particular registers... + add esp, 24 + +;; UINT32 Eip; + pop dword [ebp + 3 * 4] + +;; UINT32 Gs, Fs, Es, Ds, Cs, Ss; +;; NOTE - modified segment registers could hang the debugger... We +;; could attempt to insulate ourselves against this possibility, +;; but that poses risks as well. +;; + pop gs + pop fs + pop es + pop ds + pop dword [ebp + 4 * 4] + pop ss + +;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; + pop edi + pop esi + add esp, 4 ; not for ebp + add esp, 4 ; not for esp + pop ebx + pop edx + pop ecx + pop eax + + mov esp, ebp + pop ebp + add esp, 8 + iretd + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; data +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SECTION .data + +ALIGN 04h + +gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit + dd 0 ;GDT_BASE ; (GDT base gets set above) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; global descriptor table (GDT) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +ALIGN 04h ; make GDT 4-byte align + +GDT_BASE: +; null descriptor +NULL_SEL equ $-GDT_BASE ; Selector [0x0] + dw 0 ; limit 15:0 + dw 0 ; base 15:0 + db 0 ; base 23:16 + db 0 ; type + db 0 ; limit 19:16, flags + db 0 ; base 31:24 + +; linear data segment descriptor +LINEAR_SEL equ $-GDT_BASE ; Selector [0x8] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 092h ; present, ring 0, data, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; linear code segment descriptor +LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 09Ah ; present, ring 0, code, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; system data segment descriptor +SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 092h ; present, ring 0, data, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; system code segment descriptor +SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 09Ah ; present, ring 0, code, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; spare segment descriptor +SPARE3_SEL equ $-GDT_BASE ; Selector [0x28] + dw 0 + dw 0 + db 0 + db 0 + db 0 + db 0 + +; spare segment descriptor +SPARE4_SEL equ $-GDT_BASE ; Selector [0x30] + dw 0 + dw 0 + db 0 + db 0 + db 0 + db 0 + +; spare segment descriptor +SPARE5_SEL equ $-GDT_BASE ; Selector [0x38] + dw 0 + dw 0 + db 0 + db 0 + db 0 + db 0 + + +GDT_END: + ALIGN 04h + +idtr dw IDT_END - IDT_BASE - 1 ; IDT limit + dd 0 ;IDT_BASE ; (IDT base gets set above) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; interrupt descriptor table (IDT) +; +; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ +; mappings. This implementation only uses the system timer and all other +; IRQs will remain masked. The descriptors for vectors 33+ are provided +; for convenience. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ALIGN 04h ; make IDT 4-byte align + +;global IDT_BASE +IDT_BASE: +; divide by zero (INT 0) +DIV_ZERO_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; debug exception (INT 1) +DEBUG_EXCEPT_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; NMI (INT 2) +NMI_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; soft breakpoint (INT 3) +BREAKPOINT_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; overflow (INT 4) +OVERFLOW_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; bounds check (INT 5) +BOUNDS_CHECK_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; invalid opcode (INT 6) +INVALID_OPCODE_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; device not available (INT 7) +DEV_NOT_AVAIL_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; double fault (INT 8) +DOUBLE_FAULT_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; Coprocessor segment overrun - reserved (INT 9) +RSVD_INTR_SEL1 equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; invalid TSS (INT 0ah) +INVALID_TSS_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; segment not present (INT 0bh) +SEG_NOT_PRESENT_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; stack fault (INT 0ch) +STACK_FAULT_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; general protection (INT 0dh) +GP_FAULT_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; page fault (INT 0eh) +PAGE_FAULT_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; Intel reserved - do not use (INT 0fh) +RSVD_INTR_SEL2 equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; floating point error (INT 10h) +FLT_POINT_ERR_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; alignment check (INT 11h) +ALIGNMENT_CHECK_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; machine check (INT 12h) +MACHINE_CHECK_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; SIMD floating-point exception (INT 13h) +SIMD_EXCEPTION_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +%rep (32 - 20) + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 +%endrep + +; 72 unspecified descriptors +; db (72 * 8) dup(0) +TIMES (72 * 8) db 0 + +; IRQ 0 (System timer) - (INT 68h) +IRQ0_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; IRQ 1 (8042 Keyboard controller) - (INT 69h) +IRQ1_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah) +IRQ2_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; IRQ 3 (COM 2) - (INT 6bh) +IRQ3_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; IRQ 4 (COM 1) - (INT 6ch) +IRQ4_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; IRQ 5 (LPT 2) - (INT 6dh) +IRQ5_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; IRQ 6 (Floppy controller) - (INT 6eh) +IRQ6_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; IRQ 7 (LPT 1) - (INT 6fh) +IRQ7_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; IRQ 8 (RTC Alarm) - (INT 70h) +IRQ8_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; IRQ 9 - (INT 71h) +IRQ9_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; IRQ 10 - (INT 72h) +IRQ10_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; IRQ 11 - (INT 73h) +IRQ11_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; IRQ 12 (PS/2 mouse) - (INT 74h) +IRQ12_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; IRQ 13 (Floating point error) - (INT 75h) +IRQ13_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; IRQ 14 (Secondary IDE) - (INT 76h) +IRQ14_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; IRQ 15 (Primary IDE) - (INT 77h) +IRQ15_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + +; db (1 * 8) dup(0) +TIMES (1 * 8) db 0 + +IDT_END: + + +;END diff --git a/Legacy/BootPlatform/CpuDxe/X64/CpuInterrupt.nasm b/Legacy/BootPlatform/CpuDxe/X64/CpuInterrupt.nasm new file mode 100644 index 0000000000000000000000000000000000000000..86532854f694108eb0e908eac2c9d3f106accb38 --- /dev/null +++ b/Legacy/BootPlatform/CpuDxe/X64/CpuInterrupt.nasm @@ -0,0 +1,938 @@ +; TITLE CpuInterrupt.nasm: +;------------------------------------------------------------------------------ +;* +;* Copyright 2006 - 2010, Intel Corporation +;* All rights reserved. This program and the accompanying materials +;* are licensed and made available under the terms and conditions of the BSD License +;* which accompanies this distribution. The full text of the license may be found at +;* http://opensource.org/licenses/bsd-license.php +;* +;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +;* +;* CpuInterrupt.asm +;* +;* Abstract: +;* +;------------------------------------------------------------------------------ +global ASM_PFX(InstallInterruptHandler) +global ASM_PFX(InitDescriptor) +global ASM_PFX(SystemExceptionHandler) +global ASM_PFX(SystemTimerHandler) + +SECTION .text + +EXTERN ASM_PFX(TimerHandler) +EXTERN ASM_PFX(ExceptionHandler) + + +ASM_PFX(InitDescriptor): + lea rax, [REL GDT_BASE] ; RAX=PHYSICAL address of gdt + mov [REL gdtr + 2], rax ; Put address of gdt into the gdtr + lgdt [REL gdtr] + mov eax, 18h + mov gs, eax + mov fs, eax + lea rax, [REL IDT_BASE] ; RAX=PHYSICAL address of idt + mov qword [REL idtr + 2], rax ; Put address of idt into the idtr + lidt [REL idtr] + ret + + +; VOID +; EFIAPI +; InstallInterruptHandler ( +; UINTN Vector, // rcx +; void (*Handler)(void) // rdx +; ) +ASM_PFX(InstallInterruptHandler): + push rbx + pushfq ; save eflags + cli ; turn off interrupts + sub rsp, 10h ; open some space on the stack + mov rbx, rsp + sidt [rbx] ; get tword address of IDT + mov rbx, [rbx+2] ; move offset of IDT into RBX + add rsp, 10h ; correct stack + mov rax, rcx ; Get vector number + shl rax, 4 ; multiply by 16 to get offset + add rbx, rax ; add to IDT base to get entry + mov rax, rdx ; load new address into IDT entry + mov word [rbx], ax ; write bits 15..0 of offset + shr rax, 16 ; use ax to copy 31..16 to descriptors + mov word [rbx+6], ax ; write bits 31..16 of offset + shr rax, 16 ; use eax to copy 63..32 to descriptors + mov dword [rbx+8], eax ; write bits 63..32 of offset + popfq ; restore flags (possible enabling interrupts) + pop rbx + ret + +%macro JmpCommonIdtEntry 0 + ; jmp commonIdtEntry - this must be hand coded to keep the assembler from + ; using a 8 bit reletive jump when the entries are + ; within 255 bytes of the common entry. This must + ; be done to maintain the consistency of the size + ; of entry points... + db 0e9h ; jmp 16 bit reletive + dd commonIdtEntry - $ - 4 ; offset to jump to +%endmacro + + ALIGN 02h,db 0 +ASM_PFX(SystemExceptionHandler): +INT0: + push 0h ; push error code place holder on the stack + push 0h + JmpCommonIdtEntry +; db 0e9h ; jmp 16 bit reletive +; dd commonIdtEntry - $ - 4 ; offset to jump to + +INT1: + push 0h ; push error code place holder on the stack + push 1h + JmpCommonIdtEntry + +INT2: + push 0h ; push error code place holder on the stack + push 2h + JmpCommonIdtEntry + +INT3: + push 0h ; push error code place holder on the stack + push 3h + JmpCommonIdtEntry + +INT4: + push 0h ; push error code place holder on the stack + push 4h + JmpCommonIdtEntry + +INT5: + push 0h ; push error code place holder on the stack + push 5h + JmpCommonIdtEntry + +INT6: + push 0h ; push error code place holder on the stack + push 6h + JmpCommonIdtEntry + +INT7: + push 0h ; push error code place holder on the stack + push 7h + JmpCommonIdtEntry + +INT8: +; Double fault causes an error code to be pushed so no phony push necessary + nop + nop + push 8h + JmpCommonIdtEntry + +INT9: + push 0h ; push error code place holder on the stack + push 9h + JmpCommonIdtEntry + +INT10: +; Invalid TSS causes an error code to be pushed so no phony push necessary + nop + nop + push 10 + JmpCommonIdtEntry + +INT11: +; Segment Not Present causes an error code to be pushed so no phony push necessary + nop + nop + push 11 + JmpCommonIdtEntry + +INT12: +; Stack fault causes an error code to be pushed so no phony push necessary + nop + nop + push 12 + JmpCommonIdtEntry + +INT13: +; GP fault causes an error code to be pushed so no phony push necessary + nop + nop + push 13 + JmpCommonIdtEntry + +INT14: +; Page fault causes an error code to be pushed so no phony push necessary + nop + nop + push 14 + JmpCommonIdtEntry + +INT15: + push 0h ; push error code place holder on the stack + push 15 + JmpCommonIdtEntry + +INT16: + push 0h ; push error code place holder on the stack + push 16 + JmpCommonIdtEntry + +INT17: +; Alignment check causes an error code to be pushed so no phony push necessary + nop + nop + push 17 + JmpCommonIdtEntry + +INT18: + push 0h ; push error code place holder on the stack + push 18 + JmpCommonIdtEntry + +INT19: + push 0h ; push error code place holder on the stack + push 19 + JmpCommonIdtEntry + +INTUnknown: +%rep (32 - 20) + push 0h ; push error code place holder on the stack +; push xxh ; push vector number + db 06ah + db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number + JmpCommonIdtEntry +%endrep +;ENDM + +ASM_PFX(SystemTimerHandler): + push 0 + push 0 ;mTimerVector ;to be patched in Cpu.c + JmpCommonIdtEntry + +commonIdtEntry: +; +---------------------+ <-- 16-byte aligned ensured by processor +; + Old SS + +; +---------------------+ +; + Old RSP + +; +---------------------+ +; + RFlags + +; +---------------------+ +; + CS + +; +---------------------+ +; + RIP + +; +---------------------+ +; + Error Code + +; +---------------------+ +; + Vector Number + +; +---------------------+ +; + RBP + +; +---------------------+ <-- RBP, 16-byte aligned + + cli + push rbp + mov rbp, rsp + + ; + ; Since here the stack pointer is 16-byte aligned, so + ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64 + ; is 16-byte aligned + ; + +;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; +;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15; + push r15 + push r14 + push r13 + push r12 + push r11 + push r10 + push r9 + push r8 + push rax + push rcx + push rdx + push rbx + push qword [rbp + 6 * 8] ; RSP + push qword [rbp] ; RBP + push rsi + push rdi + +;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero + movzx rax, word [rbp + 7 * 8] + push rax ; for ss + movzx rax, word [rbp + 4 * 8] + push rax ; for cs + mov rax, ds + push rax + mov rax, es + push rax + mov rax, fs + push rax + mov rax, gs + push rax + +;; UINT64 Rip; + push qword [rbp + 3 * 8] + +;; UINT64 Gdtr[2], Idtr[2]; + sub rsp, 16 + sidt [rsp] + sub rsp, 16 + sgdt [rsp] + +;; UINT64 Ldtr, Tr; + xor rax, rax + str ax + push rax + sldt ax + push rax + +;; UINT64 RFlags; + push qword [rbp + 5 * 8] + +;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; + mov rax, cr8 + push rax + mov rax, cr4 + or rax, 208h + mov cr4, rax + push rax + mov rax, cr3 + push rax + mov rax, cr2 + push rax + xor rax, rax + push rax + mov rax, cr0 + push rax + +;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; + mov rax, dr7 + push rax +;; clear Dr7 while executing debugger itself + xor rax, rax + mov dr7, rax + + mov rax, dr6 + push rax +;; insure all status bits in dr6 are clear... + xor rax, rax + mov dr6, rax + + mov rax, dr3 + push rax + mov rax, dr2 + push rax + mov rax, dr1 + push rax + mov rax, dr0 + push rax + +;; FX_SAVE_STATE_X64 FxSaveState; + + sub rsp, 512 + mov rdi, rsp + db 0fh, 0aeh, 00000111y ;fxsave [rdi] + +;; UINT32 ExceptionData; + push qword [rbp + 2 * 8] + +;; call into exception handler +;; Prepare parameter and call + mov rcx, qword [rbp + 1 * 8] + mov rdx, rsp + ; + ; Per X64 calling convention, allocate maximum parameter stack space + ; and make sure RSP is 16-byte aligned + ; + sub rsp, 4 * 8 + 8 + cmp rcx, 32 + jb CallException + call ASM_PFX(TimerHandler) + jmp ExceptionDone +CallException: + call NEAR ASM_PFX(ExceptionHandler) +ExceptionDone: + add rsp, 4 * 8 + 8 + + cli +;; UINT64 ExceptionData; + add rsp, 8 + +;; FX_SAVE_STATE_X64 FxSaveState; + + mov rsi, rsp + db 0fh, 0aeh, 00001110y ; fxrstor [rsi] + add rsp, 512 + +;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; + pop rax + mov dr0, rax + pop rax + mov dr1, rax + pop rax + mov dr2, rax + pop rax + mov dr3, rax +;; skip restore of dr6. We cleared dr6 during the context save. + add rsp, 8 + pop rax + mov dr7, rax + +;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; + pop rax + mov cr0, rax + add rsp, 8 ; not for Cr1 + pop rax + mov cr2, rax + pop rax + mov cr3, rax + pop rax + mov cr4, rax + pop rax + mov cr8, rax + +;; UINT64 RFlags; + pop qword [rbp + 5 * 8] + +;; UINT64 Ldtr, Tr; +;; UINT64 Gdtr[2], Idtr[2]; +;; Best not let anyone mess with these particular registers... + add rsp, 48 + +;; UINT64 Rip; + pop qword [rbp + 3 * 8] + +;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; + pop rax + ; mov gs, rax ; not for gs + pop rax + ; mov fs, rax ; not for fs + ; (X64 will not use fs and gs, so we do not restore it) + pop rax + mov es, rax + pop rax + mov ds, rax + pop qword [rbp + 4 * 8] ; for cs + pop qword [rbp + 7 * 8] ; for ss + +;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; +;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15; + pop rdi + pop rsi + add rsp, 8 ; not for rbp + pop qword [rbp + 6 * 8] ; for rsp + pop rbx + pop rdx + pop rcx + pop rax + pop r8 + pop r9 + pop r10 + pop r11 + pop r12 + pop r13 + pop r14 + pop r15 + + mov rsp, rbp + pop rbp + add rsp, 16 + iretq + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; data +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +SECTION .data + +gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit + dq 0 ;GDT_BASE ; (GDT base gets set above) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; global descriptor table (GDT) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ALIGN 010h,db 0 ; make GDT 16-byte align + +;global GDT_BASE +GDT_BASE: +; null descriptor +NULL_SEL equ $-GDT_BASE ; Selector [0x0] + dw 0 ; limit 15:0 + dw 0 ; base 15:0 + db 0 ; base 23:16 + db 0 ; type + db 0 ; limit 19:16, flags + db 0 ; base 31:24 + +; linear data segment descriptor +LINEAR_SEL equ $-GDT_BASE ; Selector [0x8] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 092h ; present, ring 0, data, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; linear code segment descriptor +LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 09Ah ; present, ring 0, code, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; system data segment descriptor +SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 092h ; present, ring 0, data, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; system code segment descriptor +SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 09Ah ; present, ring 0, code, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; spare segment descriptor +SPARE3_SEL equ $-GDT_BASE ; Selector [0x28] + dw 0 + dw 0 + db 0 + db 0 + db 0 + db 0 + +; system data segment descriptor +SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 092h ; present, ring 0, data, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; system code segment descriptor +SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 09Ah ; present, ring 0, code, expand-up, writable + db 0AFh ; page-granular, 64-bit + db 0 + +; spare segment descriptor +SPARE4_SEL equ $-GDT_BASE ; Selector [0x40] + dw 0 + dw 0 + db 0 + db 0 + db 0 + db 0 + +GDT_END: + +idtr dw IDT_END - IDT_BASE - 1 ; IDT limit + dq 0 ;IDT_BASE ; (IDT base gets set above) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; interrupt descriptor table (IDT) +; +; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ +; mappings. This implementation only uses the system timer and all other +; IRQs will remain masked. The descriptors for vectors 33+ are provided +; for convenience. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ALIGN 08h, db 0 ; make IDT 8-byte align + +;global IDT_BASE +IDT_BASE: +; divide by zero (INT 0) +DIV_ZERO_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; debug exception (INT 1) +DEBUG_EXCEPT_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; NMI (INT 2) +NMI_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; soft breakpoint (INT 3) +BREAKPOINT_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; overflow (INT 4) +OVERFLOW_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; bounds check (INT 5) +BOUNDS_CHECK_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; invalid opcode (INT 6) +INVALID_OPCODE_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; device not available (INT 7) +DEV_NOT_AVAIL_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; double fault (INT 8) +DOUBLE_FAULT_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; Coprocessor segment overrun - reserved (INT 9) +RSVD_INTR_SEL1 equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; invalid TSS (INT 0ah) +INVALID_TSS_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; segment not present (INT 0bh) +SEG_NOT_PRESENT_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; stack fault (INT 0ch) +STACK_FAULT_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; general protection (INT 0dh) +GP_FAULT_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; page fault (INT 0eh) +PAGE_FAULT_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; Intel reserved - do not use (INT 0fh) +RSVD_INTR_SEL2 equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; floating point error (INT 10h) +FLT_POINT_ERR_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; alignment check (INT 11h) +ALIGNMENT_CHECK_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; machine check (INT 12h) +MACHINE_CHECK_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; SIMD floating-point exception (INT 13h) +SIMD_EXCEPTION_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +%rep (32 - 20) + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved +%endrep + +; 72 unspecified descriptors +; db (72 * 16) dup(0) +TIMES (72 * 16) db 0 + +; IRQ 0 (System timer) - (INT 68h) +IRQ0_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; IRQ 1 (8042 Keyboard controller) - (INT 69h) +IRQ1_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah) +IRQ2_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; IRQ 3 (COM 2) - (INT 6bh) +IRQ3_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; IRQ 4 (COM 1) - (INT 6ch) +IRQ4_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; IRQ 5 (LPT 2) - (INT 6dh) +IRQ5_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; IRQ 6 (Floppy controller) - (INT 6eh) +IRQ6_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; IRQ 7 (LPT 1) - (INT 6fh) +IRQ7_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; IRQ 8 (RTC Alarm) - (INT 70h) +IRQ8_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; IRQ 9 - (INT 71h) +IRQ9_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; IRQ 10 - (INT 72h) +IRQ10_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; IRQ 11 - (INT 73h) +IRQ11_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; IRQ 12 (PS/2 mouse) - (INT 74h) +IRQ12_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; IRQ 13 (Floating point error) - (INT 75h) +IRQ13_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; IRQ 14 (Secondary IDE) - (INT 76h) +IRQ14_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; IRQ 15 (Primary IDE) - (INT 77h) +IRQ15_SEL equ $-IDT_BASE + dw 0 ; offset 15:0 + dw SYS_CODE64_SEL ; selector 15:0 + db 0 ; 0 for interrupt gate + db 8eh ; (10001110)type = 386 interrupt gate, present + dw 0 ; offset 31:16 + dd 0 ; offset 63:32 + dd 0 ; 0 for reserved + +; db (1 * 16) dup(0) +TIMES 16 db 0 + +IDT_END: + + +;END diff --git a/Legacy/BootPlatform/DxeIpl/DxeInit.c b/Legacy/BootPlatform/DxeIpl/DxeInit.c new file mode 100644 index 0000000000000000000000000000000000000000..d6e160785ab64ca6511b3b5a99bf9d6476a51235 --- /dev/null +++ b/Legacy/BootPlatform/DxeIpl/DxeInit.c @@ -0,0 +1,205 @@ +/** @file + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + DxeInit.c + +Abstract: + +Revision History: + +**/ + +#include "DxeIpl.h" + +#include "LegacyTable.h" +#include "HobGeneration.h" + +/* +-------------------------------------------------------- + Memory Map: (XX=32,64) +-------------------------------------------------------- +0x0 + IVT +0x400 + BDA +0x500 + +0x7C00 + BootSector +0x10000 + EfiLdr (relocate by efiXX.COM) +0x15000 + Efivar.bin (Load by StartXX.COM) +0x20000 + StartXX.COM (E820 table, Temporary GDT, Temporary IDT) +0x21000 + EfiXX.COM (Temporary Interrupt Handler) +0x22000 + EfiLdr.efi + DxeIpl.Z + DxeMain.Z + BFV.Z +0x86000 + MemoryFreeUnder1M (For legacy driver DMA) +0x90000 + Temporary 4G PageTable for X64 (6 page) +0x9F800 + EBDA +0xA0000 + VGA +0xC0000 + OPROM +0xE0000 + FIRMEWARE +0x100000 (1M) + Temporary Stack (1M) +0x200000 + +MemoryAbove1MB.PhysicalStart <-----------------------------------------------------+ + ... | + ... | + <- Phit.EfiMemoryBottom -------------------+ | + HOB | | + <- Phit.EfiFreeMemoryBottom | | + | MemoryFreeAbove1MB.ResourceLength + <- Phit.EfiFreeMemoryTop ------+ | | + MemoryDescriptor (For ACPINVS, ACPIReclaim) | 4M = CONSUMED_MEMORY | + | | | + Permament 4G PageTable for IA32 or MemoryAllocation | | + Permament 64G PageTable for X64 | | | + <------------------------------+ | | + Permament Stack (0x20 Pages = 128K) | | + <- Phit.EfiMemoryTop ----------+-----------+---------------+ + NvFV (64K) | + MMIO + FtwFV (128K) | + <----------------------------------------------------------+<---------+ + DxeCore | | + DxeCore | + DxeIpl | Allocated in EfiLdr + <----------------------------------------------------------+ | + BFV MMIO | + <- Top of Free Memory reported by E820 --------------------+<---------+ + ACPINVS or + ACPIReclaim or + Reserved + <- Memory Top on RealMemory + +0x100000000 (4G) + +MemoryFreeAbove4G.Physicalstart <--------------------------------------------------+ + | + | + MemoryFreeAbove4GB.ResourceLength + | + | + <--------------------------------------------------+ +*/ + +VOID +EnterDxeMain ( + IN VOID *StackTop, + IN VOID *DxeCoreEntryPoint, + IN VOID *Hob, + IN VOID *PageTable + ); + +VOID +DxeInit ( + IN EFILDRHANDOFF *Handoff + ) +/*++ + + Routine Description: + + This is the entry point after this code has been loaded into memory. + +Arguments: + + +Returns: + + Calls into EFI Firmware + +--*/ +{ + VOID *StackTop; + VOID *StackBottom; + VOID *PageTableBase; + VOID *MemoryTopOnDescriptor; + VOID *MemoryDescriptor; + VOID *NvStorageBase; + EFILDRHANDOFF HandoffCopy; + + CopyMem ((VOID*) &HandoffCopy, (VOID*) Handoff, sizeof (EFILDRHANDOFF)); + Handoff = &HandoffCopy; + + // + // Hob Generation Guild line: + // * Don't report FV as physical memory + // * MemoryAllocation Hob should only cover physical memory + // * Use ResourceDescriptor Hob to report physical memory or Firmware Device and they shouldn't be overlapped + PrepareHobCpu (); + + // + // 1. BFV + // + PrepareHobBfv (Handoff->BfvBase, Handoff->BfvSize); + + // + // 2. Updates Memory information, and get the top free address under 4GB + // + MemoryTopOnDescriptor = PrepareHobMemory (Handoff->MemDescCount, Handoff->MemDesc); + + // + // 3. Put [NV], [Stack], [PageTable], [MemDesc], [HOB] just below the [top free address under 4GB] + // + + // 3.1 NV data + NvStorageBase = PrepareHobNvStorage (MemoryTopOnDescriptor); + // 3.2 Stack + StackTop = NvStorageBase; + StackBottom = PrepareHobStack (StackTop); + // 3.3 Page Table + PageTableBase = PreparePageTable (StackBottom, gHob->Cpu.SizeOfMemorySpace); + // 3.4 MemDesc (will be used in PlatformBds) + MemoryDescriptor = PrepareHobMemoryDescriptor (PageTableBase, Handoff->MemDescCount, Handoff->MemDesc); + // 3.5 Copy the Hob itself to EfiMemoryBottom, and update the PHIT Hob + PrepareHobPhit (StackTop, MemoryDescriptor); + + // + // 4. Register the memory occupied by DxeCore and DxeIpl together as DxeCore + // + PrepareHobDxeCore ( + Handoff->DxeCoreEntryPoint, + (EFI_PHYSICAL_ADDRESS)(UINTN)Handoff->DxeCoreImageBase, + (UINTN)Handoff->DxeIplImageBase + (UINTN)Handoff->DxeIplImageSize - (UINTN)Handoff->DxeCoreImageBase + ); + + PrepareHobLegacyTable (gHob); + + CompleteHobGeneration (); + + EnterDxeMain (StackTop, Handoff->DxeCoreEntryPoint, gHob, PageTableBase); + + // + // Should never get here + // + CpuDeadLoop (); +} + +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN EFILDRHANDOFF *Handoff + ) +{ + DxeInit(Handoff); + return EFI_SUCCESS; +} diff --git a/Legacy/BootPlatform/DxeIpl/DxeIpl.h b/Legacy/BootPlatform/DxeIpl/DxeIpl.h new file mode 100644 index 0000000000000000000000000000000000000000..23697b34139254bfecec90b514f04f522ae13338 --- /dev/null +++ b/Legacy/BootPlatform/DxeIpl/DxeIpl.h @@ -0,0 +1,59 @@ +/** @file + Internal header file for DxeIpl module. + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _DUET_DXEIPL_H_ +#define _DUET_DXEIPL_H_ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#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_STICKY_WRITE 0x00000200 +#define EFI_FVB_MEMORY_MAPPED 0x00000400 +#define EFI_FVB_ERASE_POLARITY 0x00000800 + +#endif // _DUET_DXEIPL_H_ + diff --git a/Legacy/BootPlatform/DxeIpl/DxeIpl.inf b/Legacy/BootPlatform/DxeIpl/DxeIpl.inf new file mode 100644 index 0000000000000000000000000000000000000000..c9d5e1601f5d6f8262eeebe1cfc58376a3753903 --- /dev/null +++ b/Legacy/BootPlatform/DxeIpl/DxeIpl.inf @@ -0,0 +1,62 @@ +## @file +# +# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# DxeIpl.inf +# +# Abstract: +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeIpl + FILE_GUID = 2119BBD7-9432-4f47-B5E2-5C4EA31B6BDC + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + +[Packages] + MdePkg/MdePkg.dec + OpenCorePkg/OpenDuetPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + PrintLib + ReportStatusCodeLib + IoLib + +[Guids] + gEfiVariableGuid + gDxeCoreFileNameGuid + gLdrMemoryDescriptorGuid + +[Sources] + DxeIpl.h + DxeInit.c + LegacyTable.c + LegacyTable.h + HobGeneration.c + HobGeneration.h + +[Sources.x64] + X64/EnterDxeCore.c + X64/Paging.c + X64/VirtualMemory.h + +[Sources.Ia32] + Ia32/EnterDxeCore.c + Ia32/Paging.c + Ia32/VirtualMemory.h + +[Depex] + TRUE diff --git a/Legacy/BootPlatform/DxeIpl/HobGeneration.c b/Legacy/BootPlatform/DxeIpl/HobGeneration.c new file mode 100644 index 0000000000000000000000000000000000000000..d47c951574b74fd2decd6e06ec1476a0b2cc7434 --- /dev/null +++ b/Legacy/BootPlatform/DxeIpl/HobGeneration.c @@ -0,0 +1,1002 @@ +/** @file + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + HobGeneration.c + +Abstract: + +Revision History: + +**/ +#include "DxeIpl.h" +#include "HobGeneration.h" +#include "FlashLayout.h" + +#define EFI_CPUID_EXTENDED_FUNCTION 0x80000000 +#define CPUID_EXTENDED_ADD_SIZE 0x80000008 +#define EBDA_VALUE_ADDRESS 0x40E + +HOB_TEMPLATE gHobTemplate = { + { // Phit + { // Header + EFI_HOB_TYPE_HANDOFF, // HobType + sizeof (EFI_HOB_HANDOFF_INFO_TABLE), // HobLength + 0 // Reserved + }, + EFI_HOB_HANDOFF_TABLE_VERSION, // Version + BOOT_WITH_FULL_CONFIGURATION, // BootMode + 0, // EfiMemoryTop + 0, // EfiMemoryBottom + 0, // EfiFreeMemoryTop + 0, // EfiFreeMemoryBottom + 0 // EfiEndOfHobList + }, + { // Bfv + { + EFI_HOB_TYPE_FV, // HobType + sizeof (EFI_HOB_FIRMWARE_VOLUME), // HobLength + 0 // Reserved + }, + 0, // BaseAddress + 0 // Length + }, + { // BfvResource + { + EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, // HobType + sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength + 0 // Reserved + }, + { + 0 // Owner Guid + }, + EFI_RESOURCE_FIRMWARE_DEVICE, // ResourceType + (EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE), // ResourceAttribute + 0, // PhysicalStart + 0 // ResourceLength + }, + { // Cpu + { // Header + EFI_HOB_TYPE_CPU, // HobType + sizeof (EFI_HOB_CPU), // HobLength + 0 // Reserved + }, + 52, // SizeOfMemorySpace - Architecture Max + 16, // SizeOfIoSpace, + { + 0, 0, 0, 0, 0, 0 // Reserved[6] + } + }, + { // Stack HOB + { // header + EFI_HOB_TYPE_MEMORY_ALLOCATION, // Hob type + sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK), // Hob size + 0 // reserved + }, + { + EFI_HOB_MEMORY_ALLOC_STACK_GUID, + 0x0, // EFI_PHYSICAL_ADDRESS MemoryBaseAddress; + 0x0, // UINT64 MemoryLength; + EfiBootServicesData, // EFI_MEMORY_TYPE MemoryType; + {0, 0, 0, 0} // Reserved Reserved[4]; + } + }, + { // MemoryAllocation for HOB's & Images + { + EFI_HOB_TYPE_MEMORY_ALLOCATION, // HobType + sizeof (EFI_HOB_MEMORY_ALLOCATION), // HobLength + 0 // Reserved + }, + { + { + 0, //EFI_HOB_MEMORY_ALLOC_MODULE_GUID // Name + }, + 0x0, // EFI_PHYSICAL_ADDRESS MemoryBaseAddress; + 0x0, // UINT64 MemoryLength; + EfiBootServicesData, // EFI_MEMORY_TYPE MemoryType; + { + 0, 0, 0, 0 // Reserved Reserved[4]; + } + } + }, + { // MemoryFreeUnder1MB for unused memory that DXE core will claim + { + EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, // HobType + sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength + 0 // Reserved + }, + { + 0 // Owner Guid + }, + EFI_RESOURCE_SYSTEM_MEMORY, // ResourceType + (EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE), + 0x0, // PhysicalStart + 0 // ResourceLength + }, + { // MemoryFreeAbove1MB for unused memory that DXE core will claim + { + EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, // HobType + sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength + 0 // Reserved + }, + { + 0 // Owner Guid + }, + EFI_RESOURCE_SYSTEM_MEMORY, // ResourceType + (EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE), + 0x0, // PhysicalStart + 0 // ResourceLength + }, + { // MemoryFreeAbove4GB for unused memory that DXE core will claim + { + EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, // HobType + sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength + 0 // Reserved + }, + { + 0 // Owner Guid + }, + EFI_RESOURCE_SYSTEM_MEMORY, // ResourceType + (EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE), + 0x0, // PhysicalStart + 0 // ResourceLength + }, + { // Memory Allocation Module for DxeCore + { // header + EFI_HOB_TYPE_MEMORY_ALLOCATION, // Hob type + sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE), // Hob size + 0 // reserved + }, + { + EFI_HOB_MEMORY_ALLOC_MODULE_GUID, + 0x0, // EFI_PHYSICAL_ADDRESS MemoryBaseAddress; + 0x0, // UINT64 MemoryLength; + EfiBootServicesCode, // EFI_MEMORY_TYPE MemoryType; + { + 0, 0, 0, 0 // UINT8 Reserved[4]; + }, + }, + DXE_CORE_FILE_NAME_GUID, + 0x0 // EFI_PHYSICAL_ADDRESS of EntryPoint; + }, + { // MemoryDxeCore + { + EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, // HobType + sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength + 0 // Reserved + }, + { + 0 // Owner Guid + }, + EFI_RESOURCE_SYSTEM_MEMORY, // ResourceType + (EFI_RESOURCE_ATTRIBUTE_PRESENT | +// EFI_RESOURCE_ATTRIBUTE_TESTED | // Do not mark as TESTED, or DxeCore will find it and use it before check Allocation + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE), + 0x0, // PhysicalStart + 0 // ResourceLength + }, + { // Memory Map Hints to reduce fragmentation in the memory map + { + { + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (MEMORY_TYPE_INFORMATION_HOB), // Hob size + 0, // reserved + }, + EFI_MEMORY_TYPE_INFORMATION_GUID + }, + { + { + EfiACPIReclaimMemory, + 0x80 + }, // 0x80 pages = 512k for ASL + { + EfiACPIMemoryNVS, + 0x100 + }, // 0x100 pages = 1024k for S3, SMM, etc + { + EfiReservedMemoryType, + 0x04 + }, // 16k for BIOS Reserved + { + EfiRuntimeServicesData, + 0x100 + }, + { + EfiRuntimeServicesCode, + 0x100 + }, + { + EfiBootServicesCode, + 0x200 + }, + { + EfiBootServicesData, + 0x200 + }, + { + EfiLoaderCode, + 0x100 + }, + { + EfiLoaderData, + 0x100 + }, + { + EfiMaxMemoryType, + 0 + } + } + }, + { // Pointer to ACPI Table + { + { + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (TABLE_HOB), // Hob size + 0 // reserved + }, + EFI_ACPI_TABLE_GUID + }, + 0 + }, + { // Pointer to ACPI20 Table + { + { + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (TABLE_HOB), // Hob size + 0 // reserved + }, + EFI_ACPI_20_TABLE_GUID + }, + 0 + }, + { // Pointer to SMBIOS Table + { + { + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (TABLE_HOB), // Hob size + 0 // reserved + }, + SMBIOS_TABLE_GUID + }, + 0 + }, + { // Pointer to MPS Table + { + { + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (TABLE_HOB), // Hob size + 0, // reserved + }, + EFI_MPS_TABLE_GUID + }, + 0 + }, + /** + { // Pointer to FlushInstructionCache + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (PROTOCOL_HOB), // Hob size + 0, // reserved + EFI_PEI_FLUSH_INSTRUCTION_CACHE_GUID, + NULL + }, + { // Pointer to TransferControl + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (PROTOCOL_HOB), // Hob size + 0, // reserved + EFI_PEI_TRANSFER_CONTROL_GUID, + NULL + }, + { // Pointer to PeCoffLoader + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (PROTOCOL_HOB), // Hob size + 0, // reserved + EFI_PEI_PE_COFF_LOADER_GUID, + NULL + }, + { // Pointer to EfiDecompress + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (PROTOCOL_HOB), // Hob size + 0, // reserved + EFI_DECOMPRESS_PROTOCOL_GUID, + NULL + }, + { // Pointer to TianoDecompress + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (PROTOCOL_HOB), // Hob size + 0, // reserved + EFI_TIANO_DECOMPRESS_PROTOCOL_GUID, + NULL + }, + **/ + { // Pointer to ReportStatusCode + { + { + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (PROTOCOL_HOB), // Hob size + 0 // reserved + }, + EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID + }, + 0 + }, + { // EFILDR Memory Descriptor + { + { + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (MEMORY_DESC_HOB), // Hob size + 0 // reserved + }, + LDR_MEMORY_DESCRIPTOR_GUID + }, + 0, + NULL + }, + { // Pci Express Base Address Hob + { + { + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (PCI_EXPRESS_BASE_HOB), // Hob size + 0 // reserved + }, + EFI_PCI_EXPRESS_BASE_ADDRESS_GUID + }, + { + 0, + 0, + 0, + } + }, + { // Acpi Description Hob + { + { + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (ACPI_DESCRIPTION_HOB), // Hob size + 0 // reserved + }, + EFI_ACPI_DESCRIPTION_GUID + }, + { + { + 0, + }, + } + }, + { // NV Storage FV Resource + { + EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, // HobType + sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength + 0 // Reserved + }, + { + 0 // Owner Guid + }, + EFI_RESOURCE_FIRMWARE_DEVICE, // ResourceType + (EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE), // ResourceAttribute + 0, // PhysicalStart (Fixed later) + NV_STORAGE_FVB_SIZE // ResourceLength + }, + { // FVB holding NV Storage + { + { + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (FVB_HOB), + 0 + }, + EFI_FLASH_MAP_HOB_GUID + }, + { + {0, 0, 0}, // Reserved[3] + EFI_FLASH_AREA_GUID_DEFINED, // AreaType + EFI_SYSTEM_NV_DATA_FV_GUID , // AreaTypeGuid + 1, + { + { + EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes + 0, // SubAreaData.Reserved + 0, // SubAreaData.Base (Fixed later) + NV_STORAGE_FVB_SIZE, // SubAreaData.Length + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID // SubAreaData.FileSystem + } + }, + 0, // VolumeSignature (Fixed later) + NV_STORAGE_FILE_PATH, // Mapped file without padding + // TotalFVBSize = FileSize + PaddingSize = multiple of BLOCK_SIZE + NV_STORAGE_SIZE + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH, + // ActuralSize + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH + } + }, + { // NV Storage Hob + { + { + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (FVB_HOB), // Hob size + 0 // reserved + }, + EFI_FLASH_MAP_HOB_GUID + }, + { + {0, 0, 0}, // Reserved[3] + EFI_FLASH_AREA_EFI_VARIABLES, // AreaType + { 0 }, // AreaTypeGuid + 1, + { + { + EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes + 0, // SubAreaData.Reserved + 0, // SubAreaData.Base (Fixed later) + NV_STORAGE_SIZE, // SubAreaData.Length + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID // SubAreaData.FileSystem + } + }, + 0, + NV_STORAGE_FILE_PATH, + NV_STORAGE_SIZE, + 0 + } + }, + { // NV Ftw FV Resource + { + EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, // HobType + sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength + 0 // Reserved + }, + { + 0 // Owner Guid + }, + EFI_RESOURCE_FIRMWARE_DEVICE, // ResourceType + (EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE), // ResourceAttribute + 0, // PhysicalStart (Fixed later) + NV_FTW_FVB_SIZE // ResourceLength + }, + { // FVB holding FTW spaces including Working & Spare space + { + { + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (FVB_HOB), + 0 + }, + EFI_FLASH_MAP_HOB_GUID + }, + { + {0, 0, 0}, // Reserved[3] + EFI_FLASH_AREA_GUID_DEFINED, // AreaType + EFI_SYSTEM_NV_DATA_FV_GUID, // AreaTypeGuid + 1, + { + { + EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes + 0, // SubAreaData.Reserved + 0, // SubAreaData.Base (Fixed later) + NV_FTW_FVB_SIZE, // SubAreaData.Length + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID // SubAreaData.FileSystem + } + }, + 0, + L"", // Empty String indicates using memory + 0, + 0 + } + }, + { // NV Ftw working Hob + { + { + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (FVB_HOB), // Hob size + 0 // reserved + }, + EFI_FLASH_MAP_HOB_GUID + }, + { + {0, 0, 0}, // Reserved[3] + EFI_FLASH_AREA_FTW_STATE, // AreaType + { 0 }, // AreaTypeGuid + 1, + { + { + EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes + 0, // SubAreaData.Reserved + 0, // SubAreaData.Base (Fixed later) + NV_FTW_WORKING_SIZE, // SubAreaData.Length + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID // SubAreaData.FileSystem + } + }, + 0, // VolumeSignature + L"", + 0, + 0 + } + }, + { // NV Ftw spare Hob + { + { + EFI_HOB_TYPE_GUID_EXTENSION, // Hob type + sizeof (FVB_HOB), // Hob size + 0 // reserved + }, + EFI_FLASH_MAP_HOB_GUID + }, + { + {0, 0, 0}, // Reserved[3] + EFI_FLASH_AREA_FTW_BACKUP, // AreaType + { 0 }, // AreaTypeGuid + 1, + { + { + EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes + 0, // SubAreaData.Reserved + 0, // SubAreaData.Base (Fixed later) + NV_FTW_SPARE_SIZE, // SubAreaData.Length + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID // SubAreaData.FileSystem + } + }, + 0, + L"", + 0, + 0 + } + }, + { // EndOfHobList + EFI_HOB_TYPE_END_OF_HOB_LIST, // HobType + sizeof (EFI_HOB_GENERIC_HEADER), // HobLength + 0 // Reserved + } +}; + +HOB_TEMPLATE *gHob = &gHobTemplate; + +VOID * +PrepareHobMemory ( + IN UINTN NumberOfMemoryMapEntries, + IN EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor + ) +/*++ +Description: + Update the Hob filling MemoryFreeUnder1MB, MemoryAbove1MB, MemoryAbove4GB + +Arguments: + NumberOfMemoryMapEntries - Count of Memory Descriptors + EfiMemoryDescriptor - Point to the buffer containing NumberOfMemoryMapEntries Memory Descriptors + +Return: + VOID * : The end address of MemoryAbove1MB (or the top free memory under 4GB) +--*/ +{ + UINTN Index; + UINT64 EbdaAddress; + + // + // Prepare Low Memory + // 0x18 pages is 72 KB. + // + EbdaAddress = LShiftU64 (*(UINT16 *)(UINTN)(EBDA_VALUE_ADDRESS), 4); + if (EbdaAddress < 0x90000 || EbdaAddress > EFI_MEMORY_BELOW_1MB_END) { + // + // ** CHANGE ** + // Allocate memory only up to EBDA (EBDA boundry speicifed at EFI_MEMORY_BELOW_1MB_END is not universal!) + // Bottom of EBDA is usually available by examining 0x40E, which should contain EBDA base address >> 4 + // If value is not sane, we use default value at EFI_MEMORY_BELOW_1MB_END (0x9F800) + // + EbdaAddress = 0x9A000; + } + + gHob->MemoryFreeUnder1MB.ResourceLength = EbdaAddress - EFI_MEMORY_BELOW_1MB_START; + gHob->MemoryFreeUnder1MB.PhysicalStart = EFI_MEMORY_BELOW_1MB_START; + + // + // Prepare High Memory + // Assume Memory Map is ordered from low to high + // + gHob->MemoryAbove1MB.PhysicalStart = 0; + gHob->MemoryAbove1MB.ResourceLength = 0; + gHob->MemoryAbove4GB.PhysicalStart = 0; + gHob->MemoryAbove4GB.ResourceLength = 0; + + for (Index = 0; Index < NumberOfMemoryMapEntries; Index++) { + // + // Skip regions below 1MB + // + if (EfiMemoryDescriptor[Index].PhysicalStart < 0x100000) { + continue; + } + // + // Process regions above 1MB + // + if (EfiMemoryDescriptor[Index].PhysicalStart >= 0x100000) { + if (EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) { + if (gHob->MemoryAbove1MB.PhysicalStart == 0) { + gHob->MemoryAbove1MB.PhysicalStart = EfiMemoryDescriptor[Index].PhysicalStart; + gHob->MemoryAbove1MB.ResourceLength = LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT); + } else if (gHob->MemoryAbove1MB.PhysicalStart + gHob->MemoryAbove1MB.ResourceLength == EfiMemoryDescriptor[Index].PhysicalStart) { + gHob->MemoryAbove1MB.ResourceLength += LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT); + } + } + if ((EfiMemoryDescriptor[Index].Type == EfiReservedMemoryType) || + (EfiMemoryDescriptor[Index].Type >= EfiACPIReclaimMemory) ) { + continue; + } + if ((EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesCode) || + (EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesData)) { + break; + } + } + // + // Process region above 4GB + // + if (EfiMemoryDescriptor[Index].PhysicalStart >= 0x100000000LL) { + if (EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) { + if (gHob->MemoryAbove4GB.PhysicalStart == 0) { + gHob->MemoryAbove4GB.PhysicalStart = EfiMemoryDescriptor[Index].PhysicalStart; + gHob->MemoryAbove4GB.ResourceLength = LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT); + } + if (gHob->MemoryAbove4GB.PhysicalStart + gHob->MemoryAbove4GB.ResourceLength == + EfiMemoryDescriptor[Index].PhysicalStart) { + gHob->MemoryAbove4GB.ResourceLength += LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT); + } + } + } + } + + if (gHob->MemoryAbove4GB.ResourceLength == 0) { + // + // If there is no memory above 4GB then change the resource descriptor HOB + // into another type. I'm doing this as it's unclear if a resource + // descriptor HOB of length zero is valid. Spec does not say it's illegal, + // but code in EDK does not seem to handle this case. + // + gHob->MemoryAbove4GB.Header.HobType = EFI_HOB_TYPE_UNUSED; + } + + return (VOID *)(UINTN)(gHob->MemoryAbove1MB.PhysicalStart + gHob->MemoryAbove1MB.ResourceLength); +} + +VOID * +PrepareHobStack ( + IN VOID *StackTop + ) +{ + gHob->Stack.AllocDescriptor.MemoryLength = EFI_MEMORY_STACK_PAGE_NUM * EFI_PAGE_SIZE; + gHob->Stack.AllocDescriptor.MemoryBaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)StackTop - gHob->Stack.AllocDescriptor.MemoryLength; + + return (VOID *)(UINTN)gHob->Stack.AllocDescriptor.MemoryBaseAddress; +} + +VOID * +PrepareHobMemoryDescriptor ( + VOID *MemoryDescriptorTop, + UINTN MemDescCount, + EFI_MEMORY_DESCRIPTOR *MemDesc + ) +{ + gHob->MemoryDescriptor.MemDescCount = MemDescCount; + gHob->MemoryDescriptor.MemDesc = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryDescriptorTop - MemDescCount * sizeof(EFI_MEMORY_DESCRIPTOR)); + // + // Make MemoryDescriptor.MemDesc page aligned + // + gHob->MemoryDescriptor.MemDesc = (EFI_MEMORY_DESCRIPTOR *)((UINTN) gHob->MemoryDescriptor.MemDesc & ~EFI_PAGE_MASK); + + CopyMem (gHob->MemoryDescriptor.MemDesc, MemDesc, MemDescCount * sizeof(EFI_MEMORY_DESCRIPTOR)); + + return gHob->MemoryDescriptor.MemDesc; +} + +VOID +PrepareHobBfv ( + VOID *Bfv, + UINTN BfvLength + ) +{ + //UINTN BfvLengthPageSize; + + // + // Calculate BFV location at top of the memory region. + // This is like a RAM Disk. Align to page boundary. + // + //BfvLengthPageSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (BfvLength)); + + gHob->Bfv.BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Bfv; + gHob->Bfv.Length = BfvLength; + + // + // Resource descriptor for the FV + // + gHob->BfvResource.PhysicalStart = gHob->Bfv.BaseAddress; + gHob->BfvResource.ResourceLength = gHob->Bfv.Length; +} + +VOID +PrepareHobDxeCore ( + VOID *DxeCoreEntryPoint, + EFI_PHYSICAL_ADDRESS DxeCoreImageBase, + UINT64 DxeCoreLength + ) +{ + gHob->DxeCore.MemoryAllocationHeader.MemoryBaseAddress = DxeCoreImageBase; + gHob->DxeCore.MemoryAllocationHeader.MemoryLength = DxeCoreLength; + gHob->DxeCore.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)DxeCoreEntryPoint; + + + gHob->MemoryDxeCore.PhysicalStart = DxeCoreImageBase; + gHob->MemoryDxeCore.ResourceLength = DxeCoreLength; +} + +VOID * +PrepareHobNvStorage ( + VOID *NvStorageTop + ) +/* + Initialize Block-Aligned Firmware Block. + + Variable: + +-------------------+ + | FV_Header | + +-------------------+ + | | + |VAR_STORAGE(0x4000)| + | | + +-------------------+ + FTW: + +-------------------+ + | FV_Header | + +-------------------+ + | | + | Working(0x2000) | + | | + +-------------------+ + | | + | Spare(0x10000) | + | | + +-------------------+ +*/ +{ + STATIC VARIABLE_STORE_HEADER VarStoreHeader = { + VARIABLE_STORE_SIGNATURE, + 0xffffffff, // will be fixed in Variable driver + VARIABLE_STORE_FORMATTED, + VARIABLE_STORE_HEALTHY, + 0, + 0 + }; + + STATIC EFI_FIRMWARE_VOLUME_HEADER NvStorageFvbHeader = { + { + 0, + }, // ZeroVector[16] + EFI_SYSTEM_NV_DATA_FV_GUID, + NV_STORAGE_FVB_SIZE, + EFI_FVH_SIGNATURE, + EFI_FVB_READ_ENABLED_CAP | + EFI_FVB_READ_STATUS | + EFI_FVB_WRITE_ENABLED_CAP | + EFI_FVB_WRITE_STATUS | + EFI_FVB_ERASE_POLARITY, + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH, + 0, // CheckSum + 0, // ExtHeaderOffset + { + 0, + }, // Reserved[1] + 1, // Revision + { + { + NV_STORAGE_FVB_BLOCK_NUM, + FV_BLOCK_SIZE, + } + } + }; + + STATIC EFI_FV_BLOCK_MAP_ENTRY BlockMapEntryEnd = {0, 0}; + + EFI_PHYSICAL_ADDRESS StorageFvbBase; + EFI_PHYSICAL_ADDRESS FtwFvbBase; + + UINT16 *Ptr; + UINT16 Checksum; + + + // + // Use first 16-byte Reset Vector of FVB to store extra information + // UINT32 Offset 0 stores the volume signature + // UINT8 Offset 4 : should init the Variable Store Header if non-zero + // + gHob->NvStorageFvb.FvbInfo.VolumeId = *(UINT32 *) (UINTN) (NV_STORAGE_STATE); + gHob->NvStorage. FvbInfo.VolumeId = *(UINT32 *) (UINTN) (NV_STORAGE_STATE); + + // + // *(NV_STORAGE_STATE + 4): + // 2 - Size error + // 1 - File not exist + // 0 - File exist with correct size + // + if (*(UINT8 *) (UINTN) (NV_STORAGE_STATE + 4) == 2) { + // + // Error: Size of Efivar.bin should be 16k! + // + CpuDeadLoop(); + } + + if (*(UINT8 *) (UINTN) (NV_STORAGE_STATE + 4) != 0) { + // + // Efivar.bin doesn't exist + // 1. Init variable storage header to valid header + // + CopyMem ( + (VOID *) (UINTN) NV_STORAGE_START, + &VarStoreHeader, + sizeof (VARIABLE_STORE_HEADER) + ); + // + // 2. set all bits in variable storage body to 1 + // + SetMem ( + (VOID *) (UINTN) (NV_STORAGE_START + sizeof (VARIABLE_STORE_HEADER)), + NV_STORAGE_SIZE - sizeof (VARIABLE_STORE_HEADER), + 0xff + ); + } + + // + // Relocate variable storage + // + // 1. Init FVB Header to valid header: First 0x48 bytes + // In real platform, these fields are fixed by tools + // + // + Checksum = 0; + for ( + Ptr = (UINT16 *) &NvStorageFvbHeader; + Ptr < (UINT16 *) ((UINTN) (UINT8 *) &NvStorageFvbHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER)); + ++Ptr + ) { + Checksum = (UINT16) (Checksum + (*Ptr)); + } + NvStorageFvbHeader.Checksum = (UINT16) (0x10000 - Checksum); + StorageFvbBase = (EFI_PHYSICAL_ADDRESS)(((UINTN)NvStorageTop - NV_STORAGE_FVB_SIZE - NV_FTW_FVB_SIZE) & ~EFI_PAGE_MASK); + CopyMem ((VOID *) (UINTN) StorageFvbBase, &NvStorageFvbHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER)); + CopyMem ( + (VOID *) (UINTN) (StorageFvbBase + sizeof (EFI_FIRMWARE_VOLUME_HEADER)), + &BlockMapEntryEnd, + sizeof (EFI_FV_BLOCK_MAP_ENTRY) + ); + + // + // 2. Relocate variable data + // + CopyMem ( + (VOID *) (UINTN) (StorageFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH), + (VOID *) (UINTN) NV_STORAGE_START, + NV_STORAGE_SIZE + ); + + // + // 3. Set the remaining memory to 0xff + // + SetMem ( + (VOID *) (UINTN) (StorageFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH + NV_STORAGE_SIZE), + NV_STORAGE_FVB_SIZE - NV_STORAGE_SIZE - EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH, + 0xff + ); + + // + // Create the FVB holding NV Storage in memory + // + gHob->NvStorageFvResource.PhysicalStart = + gHob->NvStorageFvb.FvbInfo.Entries[0].Base = StorageFvbBase; + // + // Create the NV Storage Hob + // + gHob->NvStorage.FvbInfo.Entries[0].Base = StorageFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH; + + // + // Create the FVB holding FTW spaces + // + FtwFvbBase = (EFI_PHYSICAL_ADDRESS)((UINTN) StorageFvbBase + NV_STORAGE_FVB_SIZE); + gHob->NvFtwFvResource.PhysicalStart = + gHob->NvFtwFvb.FvbInfo.Entries[0].Base = FtwFvbBase; + // + // Put FTW Working in front + // + gHob->NvFtwWorking.FvbInfo.Entries[0].Base = FtwFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH; + + // + // Put FTW Spare area after FTW Working area + // + gHob->NvFtwSpare.FvbInfo.Entries[0].Base = + (EFI_PHYSICAL_ADDRESS)((UINTN) FtwFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH + NV_FTW_WORKING_SIZE); + + return (VOID *)(UINTN)StorageFvbBase; +} + +VOID +PrepareHobPhit ( + VOID *MemoryTop, + VOID *FreeMemoryTop + ) +{ + gHob->Phit.EfiMemoryTop = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryTop; + gHob->Phit.EfiMemoryBottom = gHob->Phit.EfiMemoryTop - CONSUMED_MEMORY; + gHob->Phit.EfiFreeMemoryTop = (EFI_PHYSICAL_ADDRESS)(UINTN)FreeMemoryTop; + gHob->Phit.EfiFreeMemoryBottom = gHob->Phit.EfiMemoryBottom + sizeof(HOB_TEMPLATE); + + CopyMem ((VOID *)(UINTN)gHob->Phit.EfiMemoryBottom, gHob, sizeof(HOB_TEMPLATE)); + gHob = (HOB_TEMPLATE *)(UINTN)gHob->Phit.EfiMemoryBottom; + + gHob->Phit.EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)&gHob->EndOfHobList; +} + +VOID +PrepareHobCpu ( + VOID + ) +{ + UINT32 CpuidEax; + + // + // Create a CPU hand-off information + // + gHob->Cpu.SizeOfMemorySpace = 36; + + AsmCpuid (EFI_CPUID_EXTENDED_FUNCTION, &CpuidEax, NULL, NULL, NULL); + if (CpuidEax >= CPUID_EXTENDED_ADD_SIZE) { + AsmCpuid (CPUID_EXTENDED_ADD_SIZE, &CpuidEax, NULL, NULL, NULL); + gHob->Cpu.SizeOfMemorySpace = (UINT8)(CpuidEax & 0xFF); + } +} + +VOID +CompleteHobGeneration ( + VOID + ) +{ + gHob->MemoryAllocation.AllocDescriptor.MemoryBaseAddress = gHob->Phit.EfiFreeMemoryTop; + // + // Reserve all the memory under Stack above FreeMemoryTop as allocated + // + gHob->MemoryAllocation.AllocDescriptor.MemoryLength = gHob->Stack.AllocDescriptor.MemoryBaseAddress - gHob->Phit.EfiFreeMemoryTop; + + // + // adjust Above1MB ResourceLength + // + if (gHob->MemoryAbove1MB.PhysicalStart + gHob->MemoryAbove1MB.ResourceLength > gHob->Phit.EfiMemoryTop) { + gHob->MemoryAbove1MB.ResourceLength = gHob->Phit.EfiMemoryTop - gHob->MemoryAbove1MB.PhysicalStart; + } +} + diff --git a/Legacy/BootPlatform/DxeIpl/HobGeneration.h b/Legacy/BootPlatform/DxeIpl/HobGeneration.h new file mode 100644 index 0000000000000000000000000000000000000000..75b555609b53f96935e240240240980d5983c61c --- /dev/null +++ b/Legacy/BootPlatform/DxeIpl/HobGeneration.h @@ -0,0 +1,174 @@ +/** @file + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + HobGeneration.h + +Abstract: + +Revision History: + +**/ + +#ifndef _DXELDR_HOB_GENERATION_H_ +#define _DXELDR_HOB_GENERATION_H_ + +#include "DxeIpl.h" + +// +// ** CHANGE ** +// +#define EFI_MEMORY_BELOW_1MB_START 0x18000 +#define EFI_MEMORY_BELOW_1MB_END 0x9F800 +#define EFI_MEMORY_STACK_PAGE_NUM 0x20 +#define CONSUMED_MEMORY 0x100000 * 80 + +#define NV_STORAGE_START 0x15000 +#define NV_STORAGE_STATE 0x19000 + +#pragma pack(1) + +typedef struct { + EFI_HOB_GUID_TYPE Hob; + EFI_MEMORY_TYPE_INFORMATION Info[10]; +} MEMORY_TYPE_INFORMATION_HOB; + +typedef struct { + EFI_HOB_GUID_TYPE Hob; + EFI_PHYSICAL_ADDRESS Table; +} TABLE_HOB; + +typedef struct { + EFI_HOB_GUID_TYPE Hob; + EFI_PHYSICAL_ADDRESS Interface; +} PROTOCOL_HOB; + +typedef struct { + EFI_HOB_GUID_TYPE Hob; + // Note: we get only one PCI Segment now. + EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION PciExpressBaseAddressInfo; +} PCI_EXPRESS_BASE_HOB; + +typedef struct { + EFI_HOB_GUID_TYPE Hob; + EFI_ACPI_DESCRIPTION AcpiDescription; +} ACPI_DESCRIPTION_HOB; + +typedef struct { + EFI_HOB_GUID_TYPE Hob; + EFI_FLASH_MAP_FS_ENTRY_DATA FvbInfo; +} FVB_HOB; + +typedef struct { + EFI_HOB_HANDOFF_INFO_TABLE Phit; + EFI_HOB_FIRMWARE_VOLUME Bfv; + EFI_HOB_RESOURCE_DESCRIPTOR BfvResource; + EFI_HOB_CPU Cpu; + EFI_HOB_MEMORY_ALLOCATION_STACK Stack; + EFI_HOB_MEMORY_ALLOCATION MemoryAllocation; + EFI_HOB_RESOURCE_DESCRIPTOR MemoryFreeUnder1MB; + EFI_HOB_RESOURCE_DESCRIPTOR MemoryAbove1MB; + EFI_HOB_RESOURCE_DESCRIPTOR MemoryAbove4GB; + EFI_HOB_MEMORY_ALLOCATION_MODULE DxeCore; + EFI_HOB_RESOURCE_DESCRIPTOR MemoryDxeCore; + MEMORY_TYPE_INFORMATION_HOB MemoryTypeInfo; + TABLE_HOB Acpi; + TABLE_HOB Acpi20; + TABLE_HOB Smbios; + TABLE_HOB Mps; + /** + PROTOCOL_HOB FlushInstructionCache; + PROTOCOL_HOB TransferControl; + PROTOCOL_HOB PeCoffLoader; + PROTOCOL_HOB EfiDecompress; + PROTOCOL_HOB TianoDecompress; + **/ + PROTOCOL_HOB SerialStatusCode; + MEMORY_DESC_HOB MemoryDescriptor; + PCI_EXPRESS_BASE_HOB PciExpress; + ACPI_DESCRIPTION_HOB AcpiInfo; + + EFI_HOB_RESOURCE_DESCRIPTOR NvStorageFvResource; + + FVB_HOB NvStorageFvb; + FVB_HOB NvStorage; + + EFI_HOB_RESOURCE_DESCRIPTOR NvFtwFvResource; + FVB_HOB NvFtwFvb; + FVB_HOB NvFtwWorking; + FVB_HOB NvFtwSpare; + + EFI_HOB_GENERIC_HEADER EndOfHobList; +} HOB_TEMPLATE; + +#pragma pack() + +extern HOB_TEMPLATE *gHob; + +VOID * +PrepareHobStack ( + IN VOID *StackTop + ); + +VOID +PrepareHobBfv ( + VOID *Bfv, + UINTN BfvLength + ); + +VOID * +PrepareHobMemory ( + IN UINTN NumberOfMemoryMapEntries, + IN EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor + ); + +VOID +PrepareHobDxeCore ( + VOID *DxeCoreEntryPoint, + EFI_PHYSICAL_ADDRESS DxeCoreImageBase, + UINT64 DxeCoreLength + ); + +VOID * +PreparePageTable ( + VOID *PageNumberTop, + UINT8 SizeOfMemorySpace + ); + +VOID * +PrepareHobMemoryDescriptor ( + VOID *MemoryDescriptorTop, + UINTN MemDescCount, + EFI_MEMORY_DESCRIPTOR *MemDesc + ); + +VOID +PrepareHobPhit ( + VOID *MemoryTop, + VOID *FreeMemoryTop + ); + +VOID * +PrepareHobNvStorage ( + VOID *NvStorageTop + ); + +VOID +PrepareHobCpu ( + VOID + ); + +VOID +CompleteHobGeneration ( + VOID + ); + +#endif diff --git a/Legacy/BootPlatform/DxeIpl/Ia32/EnterDxeCore.c b/Legacy/BootPlatform/DxeIpl/Ia32/EnterDxeCore.c new file mode 100644 index 0000000000000000000000000000000000000000..449738dadbc65ad1bc424725ce18dff75c670687 --- /dev/null +++ b/Legacy/BootPlatform/DxeIpl/Ia32/EnterDxeCore.c @@ -0,0 +1,31 @@ +/** @file + IA32 specific code to enter DxeCore + +Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "DxeIpl.h" + +VOID +EnterDxeMain ( + IN VOID *StackTop, + IN VOID *DxeCoreEntryPoint, + IN VOID *Hob, + IN VOID *PageTable + ) +{ + SwitchStack ( + (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint, + Hob, + NULL, + StackTop + ); +} diff --git a/Legacy/BootPlatform/DxeIpl/Ia32/Paging.c b/Legacy/BootPlatform/DxeIpl/Ia32/Paging.c new file mode 100644 index 0000000000000000000000000000000000000000..a5026f8840220c1b318a18ebb569b96329d3eb4c --- /dev/null +++ b/Legacy/BootPlatform/DxeIpl/Ia32/Paging.c @@ -0,0 +1,171 @@ +/** @file + +Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + Paging.c + +Abstract: + +Revision History: + +**/ + +#include "DxeIpl.h" +#include "HobGeneration.h" +#include "VirtualMemory.h" + +#define EFI_PAGE_SIZE_4K 0x1000 +#define EFI_PAGE_SIZE_4M 0x400000 + +// +// Create 4G 4M-page table +// PDE (31:22) : 1024 entries +// +#define EFI_MAX_ENTRY_NUM 1024 + +#define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM + +#define EFI_PDE_PAGE_NUM 1 + +#define EFI_PAGE_NUMBER_4M (EFI_PDE_PAGE_NUM) + +// +// Create 4M 4K-page table +// PTE (21:12) : 1024 entries +// +#define EFI_PTE_ENTRY_NUM EFI_MAX_ENTRY_NUM +#define EFI_PTE_PAGE_NUM 1 + +#define EFI_PAGE_NUMBER_4K (EFI_PTE_PAGE_NUM) + +#define EFI_PAGE_NUMBER (EFI_PAGE_NUMBER_4M + EFI_PAGE_NUMBER_4K) + +VOID +EnableNullPointerProtection ( + UINT8 *PageTable + ) +{ + IA32_PAGE_TABLE_ENTRY_4K *PageTableEntry4KB; + + PageTableEntry4KB = (IA32_PAGE_TABLE_ENTRY_4K *)((UINTN)PageTable + EFI_PAGE_NUMBER_4M * EFI_PAGE_SIZE_4K); + + // + // Fill in the Page Table entries + // Mark 0~4K as not present + // + PageTableEntry4KB->Bits.Present = 0; + + return ; +} + +VOID +Ia32Create4KPageTables ( + UINT8 *PageTable + ) +{ + UINT64 PageAddress; + UINTN PTEIndex; + IA32_PAGE_DIRECTORY_ENTRY_4K *PageDirectoryEntry4KB; + IA32_PAGE_TABLE_ENTRY_4K *PageTableEntry4KB; + + PageAddress = 0; + + // + // Page Table structure 2 level 4K. + // + // Page Table 4K : PageDirectoryEntry4K : bits 31-22 + // PageTableEntry : bits 21-12 + // + + PageTableEntry4KB = (IA32_PAGE_TABLE_ENTRY_4K *)((UINTN)PageTable + EFI_PAGE_NUMBER_4M * EFI_PAGE_SIZE_4K); + PageDirectoryEntry4KB = (IA32_PAGE_DIRECTORY_ENTRY_4K *)((UINTN)PageTable); + + PageDirectoryEntry4KB->Uint32 = (UINT32)(UINTN)PageTableEntry4KB; + PageDirectoryEntry4KB->Bits.ReadWrite = 0; + PageDirectoryEntry4KB->Bits.Present = 1; + PageDirectoryEntry4KB->Bits.MustBeZero = 1; + + for (PTEIndex = 0; PTEIndex < EFI_PTE_ENTRY_NUM; PTEIndex++, PageTableEntry4KB++) { + // + // Fill in the Page Table entries + // + PageTableEntry4KB->Uint32 = (UINT32)PageAddress; + PageTableEntry4KB->Bits.ReadWrite = 1; + PageTableEntry4KB->Bits.Present = 1; + + PageAddress += EFI_PAGE_SIZE_4K; + } + + return ; +} + +VOID +Ia32Create4MPageTables ( + UINT8 *PageTable + ) +{ + UINT32 PageAddress; + UINT8 *TempPageTable; + UINTN PDEIndex; + IA32_PAGE_TABLE_ENTRY_4M *PageDirectoryEntry4MB; + + TempPageTable = PageTable; + + PageAddress = 0; + + // + // Page Table structure 1 level 4MB. + // + // Page Table 4MB : PageDirectoryEntry4M : bits 31-22 + // + + PageDirectoryEntry4MB = (IA32_PAGE_TABLE_ENTRY_4M *)TempPageTable; + + for (PDEIndex = 0; PDEIndex < EFI_PDE_ENTRY_NUM; PDEIndex++, PageDirectoryEntry4MB++) { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry4MB->Uint32 = (UINT32)PageAddress; + PageDirectoryEntry4MB->Bits.ReadWrite = 1; + PageDirectoryEntry4MB->Bits.Present = 1; + PageDirectoryEntry4MB->Bits.MustBe1 = 1; + + PageAddress += EFI_PAGE_SIZE_4M; + } + + return ; +} + +VOID * +PreparePageTable ( + VOID *PageNumberTop, + UINT8 SizeOfMemorySpace + ) +/*++ +Description: + Generate pagetable below PageNumberTop, + and return the bottom address of pagetable for putting other things later. +--*/ +{ + VOID *PageNumberBase; + + PageNumberBase = (VOID *)((UINTN)PageNumberTop - EFI_PAGE_NUMBER * EFI_PAGE_SIZE_4K); + ZeroMem (PageNumberBase, EFI_PAGE_NUMBER * EFI_PAGE_SIZE_4K); + + Ia32Create4MPageTables (PageNumberBase); + Ia32Create4KPageTables (PageNumberBase); + // + // Not enable NULL Pointer Protection if using INTX call + // +// EnableNullPointerProtection (PageNumberBase); + + return PageNumberBase; +} diff --git a/Legacy/BootPlatform/DxeIpl/Ia32/VirtualMemory.h b/Legacy/BootPlatform/DxeIpl/Ia32/VirtualMemory.h new file mode 100644 index 0000000000000000000000000000000000000000..285953e2278272e4c61faf500f1aa4be8387569a --- /dev/null +++ b/Legacy/BootPlatform/DxeIpl/Ia32/VirtualMemory.h @@ -0,0 +1,88 @@ +/** @file + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + VirtualMemory.h + +Abstract: + +Revision History: + +**/ + +#ifndef _VIRTUAL_MEMORY_H_ +#define _VIRTUAL_MEMORY_H_ + +#pragma pack(1) + +// +// Page Directory Entry 4K +// +typedef union { + struct { + UINT32 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT32 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT32 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT32 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT32 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT32 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT32 MustBeZero:3; // Must Be Zero + UINT32 Available:3; // Available for use by system software + UINT32 PageTableBaseAddress:20; // Page Table Base Address + } Bits; + UINT32 Uint32; +} IA32_PAGE_DIRECTORY_ENTRY_4K; + +// +// Page Table Entry 4K +// +typedef union { + struct { + UINT32 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT32 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT32 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT32 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT32 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT32 Accessed:1; // 0 = Not accessed (cleared by software), 1 = Accessed (set by CPU) + UINT32 Dirty:1; // 0 = Not written to (cleared by software), 1 = Written to (set by CPU) + UINT32 PAT:1; // 0 = Disable PAT, 1 = Enable PAT + UINT32 Global:1; // Ignored + UINT32 Available:3; // Available for use by system software + UINT32 PageTableBaseAddress:20; // Page Table Base Address + } Bits; + UINT32 Uint32; +} IA32_PAGE_TABLE_ENTRY_4K; + +// +// Page Table Entry 4M +// +typedef union { + struct { + UINT32 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT32 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT32 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT32 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT32 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT32 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT32 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT32 MustBe1:1; // Must be 1 + UINT32 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT32 Available:3; // Available for use by system software + UINT32 PAT:1; // + UINT32 MustBeZero:9; // Must be zero; + UINT32 PageTableBaseAddress:10; // Page Table Base Address + } Bits; + UINT32 Uint32; +} IA32_PAGE_TABLE_ENTRY_4M; + +#pragma pack() + +#endif diff --git a/Legacy/BootPlatform/DxeIpl/LegacyTable.c b/Legacy/BootPlatform/DxeIpl/LegacyTable.c new file mode 100644 index 0000000000000000000000000000000000000000..b6a06563892d431b5e3cf9f0e4695a9fe7f55014 --- /dev/null +++ b/Legacy/BootPlatform/DxeIpl/LegacyTable.c @@ -0,0 +1,428 @@ +/** @file + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + LegacyTable.c + +Abstract: + +Revision History: + +**/ + +#include "DxeIpl.h" +#include "HobGeneration.h" + +#define MPS_PTR SIGNATURE_32('_','M','P','_') +#define SMBIOS_PTR SIGNATURE_32('_','S','M','_') + +#define EBDA_BASE_ADDRESS 0x40E + +VOID * +FindAcpiRsdPtr ( + VOID + ) +{ + UINTN Address; + UINTN Index; + + // + // First Seach 0x0e0000 - 0x0fffff for RSD Ptr + // + for (Address = 0xe0000; Address < 0xfffff; Address += 0x10) { + if (*(UINT64 *)(Address) == EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) { + return (VOID *)Address; + } + } + + // + // Search EBDA + // + + Address = (*(UINT16 *)(UINTN)(EBDA_BASE_ADDRESS)) << 4; + for (Index = 0; Index < 0x400 ; Index += 16) { + if (*(UINT64 *)(Address + Index) == EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) { + return (VOID *)Address; + } + } + return NULL; +} + +VOID * +FindSMBIOSPtr ( + VOID + ) +{ + UINTN Address; + + // + // First Seach 0x0f0000 - 0x0fffff for SMBIOS Ptr + // + for (Address = 0xf0000; Address < 0xfffff; Address += 0x10) { + if (*(UINT32 *)(Address) == SMBIOS_PTR) { + return (VOID *)Address; + } + } + return NULL; +} + +VOID * +FindMPSPtr ( + VOID + ) +{ + UINTN Address; + UINTN Index; + + // + // First Seach 0x0e0000 - 0x0fffff for MPS Ptr + // + for (Address = 0xe0000; Address < 0xfffff; Address += 0x10) { + if (*(UINT32 *)(Address) == MPS_PTR) { + return (VOID *)Address; + } + } + + // + // Search EBDA + // + + Address = (*(UINT16 *)(UINTN)(EBDA_BASE_ADDRESS)) << 4; + for (Index = 0; Index < 0x400 ; Index += 16) { + if (*(UINT32 *)(Address + Index) == MPS_PTR) { + return (VOID *)Address; + } + } + return NULL; +} + +#pragma pack(1) + +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Entry; +} RSDT_TABLE; + +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 Entry; +} XSDT_TABLE; + +#pragma pack() + +VOID +ScanTableInRSDT ( + RSDT_TABLE *Rsdt, + UINT32 Signature, + EFI_ACPI_DESCRIPTION_HEADER **FoundTable + ) +{ + UINTN Index; + UINT32 EntryCount; + UINT32 *EntryPtr; + EFI_ACPI_DESCRIPTION_HEADER *Table; + + *FoundTable = NULL; + + EntryCount = (Rsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32); + + EntryPtr = &Rsdt->Entry; + for (Index = 0; Index < EntryCount; Index ++, EntryPtr ++) { + Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(*EntryPtr)); + if (Table->Signature == Signature) { + *FoundTable = Table; + break; + } + } + + return; +} + +VOID +ScanTableInXSDT ( + XSDT_TABLE *Xsdt, + UINT32 Signature, + EFI_ACPI_DESCRIPTION_HEADER **FoundTable + ) +{ + UINTN Index; + UINT32 EntryCount; + UINT64 EntryPtr; + UINTN BasePtr; + EFI_ACPI_DESCRIPTION_HEADER *Table; + + *FoundTable = NULL; + + EntryCount = (Xsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64); + + BasePtr = (UINTN)(&(Xsdt->Entry)); + for (Index = 0; Index < EntryCount; Index ++) { + CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * sizeof(UINT64)), sizeof(UINT64)); + Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(EntryPtr)); + if (Table->Signature == Signature) { + *FoundTable = Table; + break; + } + } + + return; +} + +VOID * +FindAcpiPtr ( + IN HOB_TEMPLATE *Hob, + UINT32 Signature + ) +{ + EFI_ACPI_DESCRIPTION_HEADER *AcpiTable; + EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; + RSDT_TABLE *Rsdt; + XSDT_TABLE *Xsdt; + + AcpiTable = NULL; + + // + // Check ACPI2.0 table + // + if ((int)Hob->Acpi20.Table != -1) { + Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)Hob->Acpi20.Table; + Rsdt = (RSDT_TABLE *)(UINTN)Rsdp->RsdtAddress; + Xsdt = NULL; + if ((Rsdp->Revision >= 2) && (Rsdp->XsdtAddress < (UINT64)(UINTN)-1)) { + Xsdt = (XSDT_TABLE *)(UINTN)Rsdp->XsdtAddress; + } + // + // Check Xsdt + // + if (Xsdt != NULL) { + ScanTableInXSDT (Xsdt, Signature, &AcpiTable); + } + // + // Check Rsdt + // + if ((AcpiTable == NULL) && (Rsdt != NULL)) { + ScanTableInRSDT (Rsdt, Signature, &AcpiTable); + } + } + + // + // Check ACPI1.0 table + // + if ((AcpiTable == NULL) && ((int)Hob->Acpi.Table != -1)) { + Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)Hob->Acpi.Table; + Rsdt = (RSDT_TABLE *)(UINTN)Rsdp->RsdtAddress; + // + // Check Rsdt + // + if (Rsdt != NULL) { + ScanTableInRSDT (Rsdt, Signature, &AcpiTable); + } + } + + return AcpiTable; +} + +#pragma pack(1) +typedef struct { + UINT64 BaseAddress; + UINT16 PciSegmentGroupNumber; + UINT8 StartBusNumber; + UINT8 EndBusNumber; + UINT32 Reserved; +} MCFG_STRUCTURE; +#pragma pack() + +VOID +PrepareMcfgTable ( + IN HOB_TEMPLATE *Hob + ) +{ + EFI_ACPI_DESCRIPTION_HEADER *McfgTable; + MCFG_STRUCTURE *Mcfg; + UINTN McfgCount; + UINTN Index; + + McfgTable = FindAcpiPtr (Hob, EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE); + if (McfgTable == NULL) { + return ; + } + + Mcfg = (MCFG_STRUCTURE *)((UINTN)McfgTable + sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)); + McfgCount = (McfgTable->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER) - sizeof(UINT64)) / sizeof(MCFG_STRUCTURE); + + // + // Fill PciExpress info on Hob + // Note: Only for 1st segment + // + for (Index = 0; Index < McfgCount; Index++) { + if (Mcfg[Index].PciSegmentGroupNumber == 0) { + Hob->PciExpress.PciExpressBaseAddressInfo.PciExpressBaseAddress = Mcfg[Index].BaseAddress; + break; + } + } + + return ; +} + +VOID +PrepareFadtTable ( + IN HOB_TEMPLATE *Hob + ) +{ + EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt; + EFI_ACPI_DESCRIPTION *AcpiDescription; + + Fadt = FindAcpiPtr (Hob, EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE); + if (Fadt == NULL) { + return ; + } + + AcpiDescription = &Hob->AcpiInfo.AcpiDescription; + // + // Fill AcpiDescription according to FADT + // Currently, only for PM_TMR + // + AcpiDescription->PM_TMR_LEN = Fadt->PmTmrLen; + AcpiDescription->TMR_VAL_EXT = (UINT8)((Fadt->Flags & 0x100) != 0); + // + // ** CHANGE ** + // + AcpiDescription->Flags = Fadt->Flags; + // + // For fields not included in ACPI 1.0 spec, we get the value based on table length + // + if (Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE, XPmTmrBlk) + sizeof (Fadt->XPmTmrBlk)) { + CopyMem ( + &AcpiDescription->PM_TMR_BLK, + &Fadt->XPmTmrBlk, + sizeof(EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE) + ); + } + if (Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE, ResetValue) + sizeof (Fadt->ResetValue)) { + CopyMem ( + &AcpiDescription->RESET_REG, + &Fadt->ResetReg, + sizeof(EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE) + ); + AcpiDescription->RESET_VALUE = Fadt->ResetValue; + } else { + // + // ** CHANGE START ** + // Otherwise fill with defaults. + // + AcpiDescription->RESET_REG.Address = 0x64; + AcpiDescription->RESET_REG.AddressSpaceId = EFI_ACPI_3_0_SYSTEM_IO; + AcpiDescription->RESET_REG.RegisterBitWidth = 8; + AcpiDescription->RESET_REG.RegisterBitOffset = 0; + AcpiDescription->RESET_REG.AccessSize = 1; + AcpiDescription->RESET_VALUE = 0xFE; + // + // ** CHANGE END ** + // + } + + // + // ** CHANGE START ** + // Fill more values. + // + if (Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE, XPm1aEvtBlk) + sizeof (Fadt->XPm1aEvtBlk)) { + CopyMem ( + &AcpiDescription->PM1a_EVT_BLK, + &Fadt->XPm1aEvtBlk, + sizeof(EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE) + ); + } else { + AcpiDescription->PM1a_EVT_BLK.Address = (UINT64) Fadt->Pm1aEvtBlk; + AcpiDescription->PM1a_EVT_BLK.AddressSpaceId = EFI_ACPI_3_0_SYSTEM_IO; + AcpiDescription->PM1a_EVT_BLK.RegisterBitWidth = 20; + AcpiDescription->PM1a_EVT_BLK.RegisterBitOffset = 0; + AcpiDescription->PM1a_EVT_BLK.AccessSize = 3; + } + + AcpiDescription->PM1_EVT_LEN = Fadt->Pm1EvtLen; + + if (Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE, XPm1aCntBlk) + sizeof (Fadt->XPm1aCntBlk)) { + CopyMem ( + &AcpiDescription->PM1a_CNT_BLK, + &Fadt->XPm1aCntBlk, + sizeof(EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE) + ); + } else { + AcpiDescription->PM1a_CNT_BLK.Address = (UINT64) Fadt->Pm1aCntBlk; + AcpiDescription->PM1a_CNT_BLK.AddressSpaceId = EFI_ACPI_3_0_SYSTEM_IO; + AcpiDescription->PM1a_CNT_BLK.RegisterBitWidth = 10; + AcpiDescription->PM1a_CNT_BLK.RegisterBitOffset = 0; + AcpiDescription->PM1a_CNT_BLK.AccessSize = 2; + } + + AcpiDescription->PM1_CNT_LEN = Fadt->Pm1CntLen; + + if (Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE, XPm2CntBlk) + sizeof (Fadt->XPm2CntBlk)) { + CopyMem ( + &AcpiDescription->PM2_CNT_BLK, + &Fadt->XPm2CntBlk, + sizeof(EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE) + ); + } else { + AcpiDescription->PM2_CNT_BLK.Address = (UINT64) Fadt->Pm2CntBlk; + AcpiDescription->PM2_CNT_BLK.AddressSpaceId = EFI_ACPI_3_0_SYSTEM_IO; + AcpiDescription->PM2_CNT_BLK.RegisterBitWidth = 8; + AcpiDescription->PM2_CNT_BLK.RegisterBitOffset = 0; + AcpiDescription->PM2_CNT_BLK.AccessSize = 1; + } + + AcpiDescription->PM2_CNT_LEN = Fadt->Pm2CntLen; + + // + // Fill these fields by known values; 1 and 2 never used. + // Change by Slice. + // + AcpiDescription->SLP_TYPa = 5; + AcpiDescription->SLP3_TYPa = 5; + AcpiDescription->SLP4_TYPa = 7; + + // + // ** CHANGE END ** + // + + if (AcpiDescription->PM_TMR_BLK.Address == 0) { + AcpiDescription->PM_TMR_BLK.Address = Fadt->PmTmrBlk; + AcpiDescription->PM_TMR_BLK.AddressSpaceId = EFI_ACPI_3_0_SYSTEM_IO; + } + + // + // It's possible that the PM_TMR_BLK.RegisterBitWidth is always 32, + // we need to set the correct RegisterBitWidth value according to the TMR_VAL_EXT + // A zero indicates TMR_VAL is implemented as a 24-bit value. + // A one indicates TMR_VAL is implemented as a 32-bit value + // + AcpiDescription->PM_TMR_BLK.RegisterBitWidth = (UINT8) ((AcpiDescription->TMR_VAL_EXT == 0) ? 24 : 32); + + return ; +} + +VOID +PrepareHobLegacyTable ( + IN HOB_TEMPLATE *Hob + ) +{ + Hob->Acpi.Table = (EFI_PHYSICAL_ADDRESS)(UINTN)FindAcpiRsdPtr (); + Hob->Acpi20.Table = (EFI_PHYSICAL_ADDRESS)(UINTN)FindAcpiRsdPtr (); + Hob->Smbios.Table = (EFI_PHYSICAL_ADDRESS)(UINTN)FindSMBIOSPtr (); + Hob->Mps.Table = (EFI_PHYSICAL_ADDRESS)(UINTN)FindMPSPtr (); + + PrepareMcfgTable (Hob); + + PrepareFadtTable (Hob); + + return ; +} + diff --git a/Legacy/BootPlatform/DxeIpl/LegacyTable.h b/Legacy/BootPlatform/DxeIpl/LegacyTable.h new file mode 100644 index 0000000000000000000000000000000000000000..e5890c93226a466bca4451668f54c7819172586f --- /dev/null +++ b/Legacy/BootPlatform/DxeIpl/LegacyTable.h @@ -0,0 +1,31 @@ +/** @file + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + LegacyTable.h + +Abstract: + +Revision History: + +**/ + +#ifndef _DXELDR_LEGACY_TABLE_H_ +#define _DXELDR_LEGACY_TABLE_H_ + +#include "HobGeneration.h" + +VOID +PrepareHobLegacyTable ( + IN HOB_TEMPLATE *Hob + ); + +#endif diff --git a/Legacy/BootPlatform/DxeIpl/X64/EnterDxeCore.c b/Legacy/BootPlatform/DxeIpl/X64/EnterDxeCore.c new file mode 100644 index 0000000000000000000000000000000000000000..cc06e511b4dfd824724fd5e7001790b3643e3cd0 --- /dev/null +++ b/Legacy/BootPlatform/DxeIpl/X64/EnterDxeCore.c @@ -0,0 +1,32 @@ +/** @file + x64 specific code to enter DxeCore + +Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "DxeIpl.h" + +VOID +EnterDxeMain ( + IN VOID *StackTop, + IN VOID *DxeCoreEntryPoint, + IN VOID *Hob, + IN VOID *PageTable + ) +{ + AsmWriteCr3 ((UINTN) PageTable); + SwitchStack ( + (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint, + Hob, + NULL, + StackTop + ); +} diff --git a/Legacy/BootPlatform/DxeIpl/X64/Paging.c b/Legacy/BootPlatform/DxeIpl/X64/Paging.c new file mode 100644 index 0000000000000000000000000000000000000000..3a0bd8f7eb026b1d9fcc12e4d0b18fae982bc684 --- /dev/null +++ b/Legacy/BootPlatform/DxeIpl/X64/Paging.c @@ -0,0 +1,250 @@ +/** @file + +Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + Paging.c + +Abstract: + +Revision History: + +**/ + +#include "HobGeneration.h" +#include "VirtualMemory.h" + +// +// Create 2M-page table +// PML4 (47:39) +// PDPTE (38:30) +// PDE (29:21) +// + +#define EFI_2M_PAGE_BITS_NUM 21 +#define EFI_MAX_ENTRY_BITS_NUM 9 + +#define EFI_PAGE_SIZE_4K 0x1000 +#define EFI_PAGE_SIZE_2M (1 << EFI_2M_PAGE_BITS_NUM) + +#ifndef MIN + #define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#define ENTRY_NUM(x) ((UINTN)1 << (x)) + +UINT8 gPML4BitsNum; +UINT8 gPDPTEBitsNum; +UINT8 gPDEBitsNum; + +UINTN gPageNum2M; +UINTN gPageNum4K; + +VOID +EnableNullPointerProtection ( + UINT8 *PageTable + ) +{ + X64_PAGE_TABLE_ENTRY_4K *PageTableEntry4KB; + + PageTableEntry4KB = (X64_PAGE_TABLE_ENTRY_4K *) (PageTable + gPageNum2M * EFI_PAGE_SIZE_4K); + // + // Fill in the Page Table entries + // Mark 0~4K as not present + // + PageTableEntry4KB->Bits.Present = 0; + + return ; +} + +VOID +X64Create4KPageTables ( + UINT8 *PageTable + ) +/*++ +Routine Description: + Create 4K-Page-Table for the low 2M memory. + This will change the previously created 2M-Page-Table-Entry. +--*/ +{ + UINT64 PageAddress; + UINTN PTEIndex; + X64_PAGE_DIRECTORY_ENTRY_4K *PageDirectoryEntry4KB; + X64_PAGE_TABLE_ENTRY_4K *PageTableEntry4KB; + + // + // Page Table structure 4 level 4K. + // + // PageMapLevel4Entry : bits 47-39 + // PageDirectoryPointerEntry : bits 38-30 + // Page Table 4K : PageDirectoryEntry4K : bits 29-21 + // PageTableEntry : bits 20-12 + // + + PageTableEntry4KB = (X64_PAGE_TABLE_ENTRY_4K *)(PageTable + gPageNum2M * EFI_PAGE_SIZE_4K); + + PageDirectoryEntry4KB = (X64_PAGE_DIRECTORY_ENTRY_4K *) (PageTable + 2 * EFI_PAGE_SIZE_4K); + PageDirectoryEntry4KB->Uint64 = (UINT64)(UINTN)PageTableEntry4KB; + PageDirectoryEntry4KB->Bits.ReadWrite = 1; + PageDirectoryEntry4KB->Bits.Present = 1; + PageDirectoryEntry4KB->Bits.MustBeZero = 0; + + for (PTEIndex = 0, PageAddress = 0; + PTEIndex < ENTRY_NUM (EFI_MAX_ENTRY_BITS_NUM); + PTEIndex++, PageTableEntry4KB++, PageAddress += EFI_PAGE_SIZE_4K + ) { + // + // Fill in the Page Table entries + // + PageTableEntry4KB->Uint64 = (UINT64)PageAddress; + PageTableEntry4KB->Bits.ReadWrite = 1; + PageTableEntry4KB->Bits.Present = 1; + } + + return ; +} + +VOID +X64Create2MPageTables ( + UINT8 *PageTable + ) +{ + UINT64 PageAddress; + UINT8 *TempPageTable; + UINTN PML4Index; + UINTN PDPTEIndex; + UINTN PDEIndex; + X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry; + X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry; + X64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB; + + TempPageTable = PageTable; + PageAddress = 0; + + // + // Page Table structure 3 level 2MB. + // + // PageMapLevel4Entry : bits 47-39 + // PageDirectoryPointerEntry : bits 38-30 + // Page Table 2MB : PageDirectoryEntry2M : bits 29-21 + // + + PageMapLevel4Entry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)TempPageTable; + + for (PML4Index = 0; PML4Index < ENTRY_NUM (gPML4BitsNum); PML4Index++, PageMapLevel4Entry++) { + // + // Each PML4 entry points to a page of Page Directory Pointer entires. + // + TempPageTable += EFI_PAGE_SIZE_4K; + PageDirectoryPointerEntry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)TempPageTable; + + // + // Make a PML4 Entry + // + PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)(TempPageTable); + PageMapLevel4Entry->Bits.ReadWrite = 1; + PageMapLevel4Entry->Bits.Present = 1; + + for (PDPTEIndex = 0; PDPTEIndex < ENTRY_NUM (gPDPTEBitsNum); PDPTEIndex++, PageDirectoryPointerEntry++) { + // + // Each Directory Pointer entries points to a page of Page Directory entires. + // + TempPageTable += EFI_PAGE_SIZE_4K; + PageDirectoryEntry2MB = (X64_PAGE_TABLE_ENTRY_2M *)TempPageTable; + + // + // Fill in a Page Directory Pointer Entries + // + PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)(TempPageTable); + PageDirectoryPointerEntry->Bits.ReadWrite = 1; + PageDirectoryPointerEntry->Bits.Present = 1; + + for (PDEIndex = 0; PDEIndex < ENTRY_NUM (gPDEBitsNum); PDEIndex++, PageDirectoryEntry2MB++) { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress; + PageDirectoryEntry2MB->Bits.ReadWrite = 1; + PageDirectoryEntry2MB->Bits.Present = 1; + PageDirectoryEntry2MB->Bits.MustBe1 = 1; + + PageAddress += EFI_PAGE_SIZE_2M; + } + } + } + + return ; +} + +VOID * +PreparePageTable ( + VOID *PageNumberTop, + UINT8 SizeOfMemorySpace + ) +/*++ +Description: + Generate pagetable below PageNumberTop, + and return the bottom address of pagetable for putting other things later. +--*/ +{ + VOID *PageNumberBase; + + // + // ** CHANGE START ** + // For AMD hardware with 48 bit wide space the table is rather HUGE. + // Patch by nms42. + // + if (SizeOfMemorySpace > 40) { + SizeOfMemorySpace = 40; + } + // + // ** CHANGE END ** + // + + SizeOfMemorySpace -= EFI_2M_PAGE_BITS_NUM; + gPDEBitsNum = (UINT8) MIN (SizeOfMemorySpace, EFI_MAX_ENTRY_BITS_NUM); + SizeOfMemorySpace = (UINT8) (SizeOfMemorySpace - gPDEBitsNum); + gPDPTEBitsNum = (UINT8) MIN (SizeOfMemorySpace, EFI_MAX_ENTRY_BITS_NUM); + SizeOfMemorySpace = (UINT8) (SizeOfMemorySpace - gPDPTEBitsNum); + gPML4BitsNum = SizeOfMemorySpace; + if (gPML4BitsNum > EFI_MAX_ENTRY_BITS_NUM) { + return NULL; + } + + // + // Suppose we have: + // 2MPage: + // Entry: PML4 -> PDPTE -> PDE -> Page + // EntryNum: a b c + // then + // Occupy4KPage: 1 a a*b + // + // 2M 4KPage: + // Entry: PTE -> Page + // EntryNum: 512 + // then + // Occupy4KPage: 1 + // + + gPageNum2M = 1 + ENTRY_NUM (gPML4BitsNum) + ENTRY_NUM (gPML4BitsNum + gPDPTEBitsNum); + gPageNum4K = 1; + + + PageNumberBase = (VOID *)((UINTN)PageNumberTop - (gPageNum2M + gPageNum4K) * EFI_PAGE_SIZE_4K); + ZeroMem (PageNumberBase, (gPageNum2M + gPageNum4K) * EFI_PAGE_SIZE_4K); + + X64Create2MPageTables (PageNumberBase); + X64Create4KPageTables (PageNumberBase); + // + // Not enable NULL Pointer Protection if using INTx call + // +// EnableNullPointerProtection (PageNumberBase); + + return PageNumberBase; +} diff --git a/Legacy/BootPlatform/DxeIpl/X64/VirtualMemory.h b/Legacy/BootPlatform/DxeIpl/X64/VirtualMemory.h new file mode 100644 index 0000000000000000000000000000000000000000..4a07c351d1ea1ba69b0b340e17e37d029b802778 --- /dev/null +++ b/Legacy/BootPlatform/DxeIpl/X64/VirtualMemory.h @@ -0,0 +1,117 @@ +/** @file + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + VirtualMemory.h + +Abstract: + +Revision History: + +**/ + +#ifndef _VIRTUAL_MEMORY_H_ +#define _VIRTUAL_MEMORY_H_ + +#pragma pack(1) + +// +// Page Map Level 4 Offset (PML4) and +// Page Directory Pointer Table (PDPE) entries 4K & 2M +// + +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:2; // Must Be Zero + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K; + +// +// Page Directory Entry 4K +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 MustBeZero:3; // Must Be Zero + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} X64_PAGE_DIRECTORY_ENTRY_4K; + +// +// Page Table Entry 4K +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 PAT:1; // 0 = Ignore Page Attribute Table + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} X64_PAGE_TABLE_ENTRY_4K; + +// +// Page Table Entry 2M +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PAT:1; // + UINT64 MustBeZero:8; // Must be zero; + UINT64 PageTableBaseAddress:31; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} X64_PAGE_TABLE_ENTRY_2M; + +#pragma pack() + +#endif diff --git a/Legacy/BootPlatform/EfiLdr/EfiLdr.h b/Legacy/BootPlatform/EfiLdr/EfiLdr.h new file mode 100644 index 0000000000000000000000000000000000000000..ad945c3d4976fe8c4f490ae0161641c74378d310 --- /dev/null +++ b/Legacy/BootPlatform/EfiLdr/EfiLdr.h @@ -0,0 +1,89 @@ +/*++ + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + EfiLdr.c + +Abstract: + +Revision History: + +--*/ + +#ifndef _DUET_EFI_LOADER_H_ +#define _DUET_EFI_LOADER_H_ + +#include "Uefi.h" +#include "EfiLdrHandoff.h" + +#include +#include +#include +#include +#include +#include + +#define INT15_E820_AddressRangeMemory 1 +#define INT15_E820_AddressRangeReserved 2 +#define INT15_E820_AddressRangeACPI 3 +#define INT15_E820_AddressRangeNVS 4 + +#define EFI_FIRMWARE_BASE_ADDRESS 0x00200000 + +#define EFI_DECOMPRESSED_BUFFER_ADDRESS 0x00600000 + +#define EFI_MAX_MEMORY_DESCRIPTORS 64 + +#define LOADED_IMAGE_SIGNATURE SIGNATURE_32('l','d','r','i') + +typedef struct { + UINTN Signature; + CHAR16 *Name; // Displayable name + UINTN Type; + + BOOLEAN Started; // If entrypoint has been called + VOID *StartImageContext; + + EFI_IMAGE_ENTRY_POINT EntryPoint; // The image's entry point + EFI_LOADED_IMAGE_PROTOCOL Info; // loaded image protocol + + // + EFI_PHYSICAL_ADDRESS ImageBasePage; // Location in memory + UINTN NoPages; // Number of pages + UINT8 *ImageBase; // As a char pointer + UINT8 *ImageEof; // End of memory image + + // relocate info + UINT8 *ImageAdjust; // Bias for reloc calculations + UINTN StackAddress; + UINT8 *FixupData; // Original fixup data +} EFILDR_LOADED_IMAGE; + +#pragma pack(4) +typedef struct { + UINT64 BaseAddress; + UINT64 Length; + UINT32 Type; +} BIOS_MEMORY_MAP_ENTRY; +#pragma pack() + +typedef struct { + UINT32 MemoryMapSize; + BIOS_MEMORY_MAP_ENTRY MemoryMapEntry[1]; +} BIOS_MEMORY_MAP; + +typedef +VOID +(EFIAPI * EFI_MAIN_ENTRYPOINT) ( + IN EFILDRHANDOFF *Handoff + ); + +#endif //_DUET_EFI_LOADER_H_ diff --git a/Legacy/BootPlatform/EfiLdr/EfiLdr.inf b/Legacy/BootPlatform/EfiLdr/EfiLdr.inf new file mode 100644 index 0000000000000000000000000000000000000000..72ee6a20101be0f804384ce516347e7a1253fb6f --- /dev/null +++ b/Legacy/BootPlatform/EfiLdr/EfiLdr.inf @@ -0,0 +1,52 @@ +## @file +# +# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# EfiLdr.inf +# +# Abstract: +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = EfiLoader + FILE_GUID = A9620E5C-5FA1-40b7-8B21-50B632F88F38 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + +[Packages] + OpenCorePkg/OpenDuetPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + PrintLib + LzmaDecompressLib + SerialPortLib + +[Sources] + PeLoader.h + Support.h + EfiLdrHandoff.h + EfiLdr.h + EfiLoader.c + PeLoader.c + Support.c + LzmaDecompress.h + +[Guids] + gTianoCustomDecompressGuid + +[BuildOptions] + MSFT:*_*_*_DLINK_FLAGS = /BASE:0x10000 diff --git a/Legacy/BootPlatform/EfiLdr/EfiLdrHandoff.h b/Legacy/BootPlatform/EfiLdr/EfiLdrHandoff.h new file mode 100644 index 0000000000000000000000000000000000000000..341d40ec9eb6115c3d96aacfc34ac62d3aae2909 --- /dev/null +++ b/Legacy/BootPlatform/EfiLdr/EfiLdrHandoff.h @@ -0,0 +1,56 @@ +/*++ + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + EfiLdrHandoff.h + +Abstract: + +Revision History: + +--*/ + +#ifndef _EFILDR_HANDOFF_H_ +#define _EFILDR_HANDOFF_H_ + +#define EFILDR_BASE_SEGMENT 0x2000 +#define EFILDR_LOAD_ADDRESS (EFILDR_BASE_SEGMENT << 4) +#define EFILDR_HEADER_ADDRESS (EFILDR_LOAD_ADDRESS+0x2000) + +#define EFILDR_CB_VA 0x00 + +typedef struct _EFILDRHANDOFF { + UINTN MemDescCount; + EFI_MEMORY_DESCRIPTOR *MemDesc; + VOID *BfvBase; + UINTN BfvSize; + VOID *DxeIplImageBase; + UINTN DxeIplImageSize; + VOID *DxeCoreImageBase; + UINTN DxeCoreImageSize; + VOID *DxeCoreEntryPoint; +} EFILDRHANDOFF; + +typedef struct { + UINT32 CheckSum; + UINT32 Offset; + UINT32 Length; + UINT8 FileName[52]; +} EFILDR_IMAGE; + +typedef struct { + UINT32 Signature; + UINT32 HeaderCheckSum; + UINT32 FileLength; + UINT32 NumberOfImages; +} EFILDR_HEADER; + +#endif diff --git a/Legacy/BootPlatform/EfiLdr/EfiLoader.c b/Legacy/BootPlatform/EfiLdr/EfiLoader.c new file mode 100644 index 0000000000000000000000000000000000000000..8dd5c576bdd55bdaee203651cee7e6b5e72a9e81 --- /dev/null +++ b/Legacy/BootPlatform/EfiLdr/EfiLoader.c @@ -0,0 +1,234 @@ +/*++ + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + EfiLoader.c + +Abstract: + +Revision History: + +--*/ + +#include "EfiLdr.h" +#include "Support.h" +#include "PeLoader.h" +#include "LzmaDecompress.h" + +#include + +EFILDR_LOADED_IMAGE DxeCoreImage; +EFILDR_LOADED_IMAGE DxeIplImage; + +VOID +SystemHang ( + CHAR8 *Message + ) +{ + CpuDeadLoop(); +} + +VOID +EfiLoader ( + UINT32 BiosMemoryMapBaseAddress + ) +{ + BIOS_MEMORY_MAP *BiosMemoryMap; + EFILDR_IMAGE *EFILDRImage; + EFI_MEMORY_DESCRIPTOR EfiMemoryDescriptor[EFI_MAX_MEMORY_DESCRIPTORS]; + EFI_STATUS Status; + UINTN NumberOfMemoryMapEntries; + UINT32 DestinationSize; + UINT32 ScratchSize; + UINTN BfvPageNumber; + UINTN BfvBase; + EFI_MAIN_ENTRYPOINT EfiMainEntrypoint; + EFILDRHANDOFF Handoff; + +#if 0 + SerialPortInitialize (); + SerialPortWrite ((UINT8*) "EfiLdr\r\n", AsciiStrLen ("EfiLdr\r\n")); +#endif + + // + // Add all EfiConventionalMemory descriptors to the table. If there are partial pages, then + // round the start address up to the next page, and round the length down to a page boundary. + // + BiosMemoryMap = (BIOS_MEMORY_MAP *) (UINTN) BiosMemoryMapBaseAddress; + NumberOfMemoryMapEntries = 0; + GenMemoryMap (&NumberOfMemoryMapEntries, EfiMemoryDescriptor, BiosMemoryMap); + + // + // Get information on where the image is in memory + // + EFILDRImage = (EFILDR_IMAGE *)(UINTN)(EFILDR_HEADER_ADDRESS + sizeof(EFILDR_HEADER)); + + + // + // Point to the 4th image (Bfv) + // + EFILDRImage += 3; + + // + // Decompress the image + // + Status = LzmaUefiDecompressGetInfo ( + (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), + EFILDRImage->Length, + &DestinationSize, + &ScratchSize + ); + + if (EFI_ERROR (Status)) { + SystemHang ("Failed to get decompress information for BFV!\n"); + } + + Status = LzmaUefiDecompress ( + (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), + EFILDRImage->Length, + (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, + (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000) + ); + + + if (EFI_ERROR (Status)) { + SystemHang ("Failed to decompress BFV!\n"); + } + + BfvPageNumber = EFI_SIZE_TO_PAGES (DestinationSize); + BfvBase = (UINTN) FindSpace (BfvPageNumber, &NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesData, EFI_MEMORY_WB); + if (BfvBase == 0) { + SystemHang ("Failed to find free space to hold decompressed BFV\n"); + } + ZeroMem ((VOID *)(UINTN)BfvBase, BfvPageNumber * EFI_PAGE_SIZE); + CopyMem ((VOID *)(UINTN)BfvBase, (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, DestinationSize); + + // + // Point to the 2nd image (DxeIpl) + // + + EFILDRImage -= 2; + + // + // Decompress the image + // + Status = LzmaUefiDecompressGetInfo ( + (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), + EFILDRImage->Length, + &DestinationSize, + &ScratchSize + ); + if (EFI_ERROR (Status)) { + SystemHang ("Failed to get decompress information for DxeIpl!\n"); + } + + Status = LzmaUefiDecompress ( + (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), + EFILDRImage->Length, + (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, + (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000) + ); + if (EFI_ERROR (Status)) { + SystemHang ("Failed to decompress DxeIpl image\n"); + } + + // + // Load and relocate the EFI PE/COFF Firmware Image + // + Status = EfiLdrPeCoffLoadPeImage ( + (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS), + &DxeIplImage, + &NumberOfMemoryMapEntries, + EfiMemoryDescriptor + ); + if (EFI_ERROR (Status)) { + SystemHang ("Failed to load and relocate DxeIpl PE image!\n"); + } + + // + // Point to the 3rd image (DxeMain) + // + EFILDRImage++; + + // + // Decompress the image + // + Status = LzmaUefiDecompressGetInfo ( + + (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), + EFILDRImage->Length, + &DestinationSize, + &ScratchSize + ); + if (EFI_ERROR (Status)) { + SystemHang ("Failed to get decompress information for DxeMain FV image!\n"); + } + + Status = LzmaUefiDecompress ( + (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), + EFILDRImage->Length, + (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, + (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000) + ); + if (EFI_ERROR (Status)) { + SystemHang ("Failed to decompress DxeMain FV image!\n"); + } + + // + // Load and relocate the EFI PE/COFF Firmware Image + // + Status = EfiLdrPeCoffLoadPeImage ( + (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS), + &DxeCoreImage, + &NumberOfMemoryMapEntries, + EfiMemoryDescriptor + ); + if (EFI_ERROR (Status)) { + SystemHang ("Failed to load/relocate DxeMain!\n"); + } + + // + // Jump to EFI Firmware + // + + if (DxeIplImage.EntryPoint != NULL) { + + Handoff.MemDescCount = NumberOfMemoryMapEntries; + Handoff.MemDesc = EfiMemoryDescriptor; + Handoff.BfvBase = (VOID *)(UINTN)BfvBase; + Handoff.BfvSize = BfvPageNumber * EFI_PAGE_SIZE; + Handoff.DxeIplImageBase = (VOID *)(UINTN)DxeIplImage.ImageBasePage; + Handoff.DxeIplImageSize = DxeIplImage.NoPages * EFI_PAGE_SIZE; + Handoff.DxeCoreImageBase = (VOID *)(UINTN)DxeCoreImage.ImageBasePage; + Handoff.DxeCoreImageSize = DxeCoreImage.NoPages * EFI_PAGE_SIZE; + Handoff.DxeCoreEntryPoint = (VOID *)(UINTN)DxeCoreImage.EntryPoint; + + EfiMainEntrypoint = (EFI_MAIN_ENTRYPOINT)(UINTN) DxeIplImage.EntryPoint; + EfiMainEntrypoint (&Handoff); + } + + // + // There was a problem loading the image, so HALT the system. + // + + SystemHang ("Failed to jump to DxeIpl!\n"); +} + +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + UINT32 BiosMemoryMapBaseAddress + ) +{ + EfiLoader(BiosMemoryMapBaseAddress); + return EFI_SUCCESS; +} + diff --git a/Legacy/BootPlatform/EfiLdr/LzmaDecompress.h b/Legacy/BootPlatform/EfiLdr/LzmaDecompress.h new file mode 100644 index 0000000000000000000000000000000000000000..010817d20cc6fc50383f332dc2c6b2a3f300e781 --- /dev/null +++ b/Legacy/BootPlatform/EfiLdr/LzmaDecompress.h @@ -0,0 +1,70 @@ +/** @file + LZMA Decompress Library header file + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __LZMADECOMPRESS_H__ +#define __LZMADECOMPRESS_H__ + +/** + The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo(). + + @param Source The source buffer containing the compressed data. + @param SourceSize The size of source buffer + @param DestinationSize The size of destination buffer. + @param ScratchSize The size of scratch buffer. + + @retval RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved. + @retval RETURN_INVALID_PARAMETER - The source data is corrupted +**/ +RETURN_STATUS +EFIAPI +LzmaUefiDecompressGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); + +/** + Decompresses a Lzma compressed source buffer. + + Extracts decompressed data to its original form. + If the compressed source data specified by Source is successfully decompressed + into Destination, then RETURN_SUCCESS is returned. If the compressed source data + specified by Source is not in a valid compressed data format, + then RETURN_INVALID_PARAMETER is returned. + + @param Source The source buffer containing the compressed data. + @param SourceSize The size of source buffer. + @param Destination The destination buffer to store the decompressed data + @param Scratch A temporary scratch buffer that is used to perform the decompression. + This is an optional parameter that may be NULL if the + required scratch buffer size is 0. + + @retval RETURN_SUCCESS Decompression completed successfully, and + the uncompressed buffer is returned in Destination. + @retval RETURN_INVALID_PARAMETER + The source buffer specified by Source is corrupted + (not in a valid compressed format). +**/ +RETURN_STATUS +EFIAPI +LzmaUefiDecompress ( + IN CONST VOID *Source, + IN UINTN SourceSize, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ); + +#endif // __LZMADECOMPRESS_H__ + diff --git a/Legacy/BootPlatform/EfiLdr/PeLoader.c b/Legacy/BootPlatform/EfiLdr/PeLoader.c new file mode 100644 index 0000000000000000000000000000000000000000..51766b5ce0abedc7919a560003eaf93df7d17ead --- /dev/null +++ b/Legacy/BootPlatform/EfiLdr/PeLoader.c @@ -0,0 +1,596 @@ +/*++ + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + PeLoader.c + +Abstract: + +Revision History: + +--*/ +#include "EfiLdr.h" +#include "Support.h" + +EFI_STATUS +EfiLdrPeCoffLoadPeRelocate ( + IN EFILDR_LOADED_IMAGE *Image, + IN EFI_IMAGE_DATA_DIRECTORY *RelocDir, + IN UINTN Adjust, + IN UINTN *NumberOfMemoryMapEntries, + IN EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor + ); + +EFI_STATUS +EfiLdrPeCoffImageRead ( + IN VOID *FHand, + IN UINTN Offset, + IN OUT UINTN ReadSize, + OUT VOID *Buffer + ); + +VOID * +EfiLdrPeCoffImageAddress ( + IN EFILDR_LOADED_IMAGE *Image, + IN UINTN Address + ); + +EFI_STATUS +EfiLdrPeCoffSetImageType ( + IN OUT EFILDR_LOADED_IMAGE *Image, + IN UINTN ImageType + ); + +EFI_STATUS +EfiLdrPeCoffCheckImageMachineType ( + IN UINT16 MachineType + ); + +EFI_STATUS +EfiLdrGetPeImageInfo ( + IN VOID *FHand, + OUT UINT64 *ImageBase, + OUT UINT32 *ImageSize + ) +{ + EFI_STATUS Status; + EFI_IMAGE_DOS_HEADER DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr; + + ZeroMem (&DosHdr, sizeof(DosHdr)); + ZeroMem (&PeHdr, sizeof(PeHdr)); + + // + // Read image headers + // + + EfiLdrPeCoffImageRead (FHand, 0, sizeof(DosHdr), &DosHdr); + if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) { + return EFI_UNSUPPORTED; + } + + EfiLdrPeCoffImageRead (FHand, DosHdr.e_lfanew, sizeof(PeHdr), &PeHdr); + + if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + return EFI_UNSUPPORTED; + } + + // + // Verify machine type + // + + Status = EfiLdrPeCoffCheckImageMachineType (PeHdr.Pe32.FileHeader.Machine); + if (EFI_ERROR(Status)) { + return Status; + } + + if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + *ImageBase = (UINT32)PeHdr.Pe32.OptionalHeader.ImageBase; + } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + *ImageBase = PeHdr.Pe32Plus.OptionalHeader.ImageBase; + } else { + return EFI_UNSUPPORTED; + } + + *ImageSize = PeHdr.Pe32.OptionalHeader.SizeOfImage; + + return EFI_SUCCESS; +} + +EFI_STATUS +EfiLdrPeCoffLoadPeImage ( + IN VOID *FHand, + IN EFILDR_LOADED_IMAGE *Image, + IN UINTN *NumberOfMemoryMapEntries, + IN EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor + ) +{ + EFI_IMAGE_DOS_HEADER DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr; + EFI_IMAGE_SECTION_HEADER *FirstSection; + EFI_IMAGE_SECTION_HEADER *Section; + UINTN Index; + EFI_STATUS Status; + UINT8 *Base; + UINT8 *End; + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + UINTN DirCount; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY TempDebugEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN CodeViewSize; + UINTN CodeViewOffset; + UINTN CodeViewFileOffset; + UINTN OptionalHeaderSize; + UINTN PeHeaderSize; + UINT32 NumberOfRvaAndSizes; + EFI_IMAGE_DATA_DIRECTORY *DataDirectory; + UINT64 ImageBase; + + ZeroMem (&DosHdr, sizeof(DosHdr)); + ZeroMem (&PeHdr, sizeof(PeHdr)); + + // + // Read image headers + // + + EfiLdrPeCoffImageRead (FHand, 0, sizeof(DosHdr), &DosHdr); + if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) { + return EFI_UNSUPPORTED; + } + + EfiLdrPeCoffImageRead (FHand, DosHdr.e_lfanew, sizeof(PeHdr), &PeHdr); + + if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + return EFI_UNSUPPORTED; + } + + // + // Set the image subsystem type + // + + Status = EfiLdrPeCoffSetImageType (Image, PeHdr.Pe32.OptionalHeader.Subsystem); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Verify machine type + // + + Status = EfiLdrPeCoffCheckImageMachineType (PeHdr.Pe32.FileHeader.Machine); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Compute the amount of memory needed to load the image and + // allocate it. This will include all sections plus the codeview debug info. + // Since the codeview info is actually outside of the image, we calculate + // its size seperately and add it to the total. + // + // Memory starts off as data + // + + CodeViewSize = 0; + CodeViewFileOffset = 0; + if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(PeHdr.Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(PeHdr.Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + } else { + return EFI_UNSUPPORTED; + } + for (DirCount = 0; + (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && (CodeViewSize == 0); + DirCount++) { + Status = EfiLdrPeCoffImageRead ( + FHand, + DirectoryEntry->VirtualAddress + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), + sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), + &TempDebugEntry + ); + if (!EFI_ERROR (Status)) { + if (TempDebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + CodeViewSize = TempDebugEntry.SizeOfData; + CodeViewFileOffset = TempDebugEntry.FileOffset; + } + } + } + + CodeViewOffset = PeHdr.Pe32.OptionalHeader.SizeOfImage + PeHdr.Pe32.OptionalHeader.SectionAlignment; + Image->NoPages = EFI_SIZE_TO_PAGES (CodeViewOffset + CodeViewSize); + + // + // Compute the amount of memory needed to load the image and + // allocate it. Memory starts off as data + // + + Image->ImageBasePage = (EFI_PHYSICAL_ADDRESS)(UINTN)FindSpace (Image->NoPages, NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesCode, EFI_MEMORY_WB); + if (Image->ImageBasePage == 0) { + return EFI_OUT_OF_RESOURCES; + } + + if (EFI_ERROR(Status)) { + return Status; + } + + Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageBasePage; + Image->Info.ImageSize = (Image->NoPages << EFI_PAGE_SHIFT) - 1; + Image->ImageBase = (UINT8 *)(UINTN)Image->ImageBasePage; + Image->ImageEof = Image->ImageBase + Image->Info.ImageSize; + Image->ImageAdjust = Image->ImageBase; + + // + // Copy the Image header to the base location + // + Status = EfiLdrPeCoffImageRead ( + FHand, + 0, + PeHdr.Pe32.OptionalHeader.SizeOfHeaders, + Image->ImageBase + ); + + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Load each directory of the image into memory... + // Save the address of the Debug directory for later + // + if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + NumberOfRvaAndSizes = PeHdr.Pe32.OptionalHeader.NumberOfRvaAndSizes; + DataDirectory = PeHdr.Pe32.OptionalHeader.DataDirectory; + } else { + NumberOfRvaAndSizes = PeHdr.Pe32Plus.OptionalHeader.NumberOfRvaAndSizes; + DataDirectory = PeHdr.Pe32Plus.OptionalHeader.DataDirectory; + } + DebugEntry = NULL; + for (Index = 0; Index < NumberOfRvaAndSizes; Index++) { + if ((DataDirectory[Index].VirtualAddress != 0) && (DataDirectory[Index].Size != 0)) { + Status = EfiLdrPeCoffImageRead ( + FHand, + DataDirectory[Index].VirtualAddress, + DataDirectory[Index].Size, + Image->ImageBase + DataDirectory[Index].VirtualAddress + ); + if (EFI_ERROR(Status)) { + return Status; + } + if (Index == EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (Image->ImageBase + DataDirectory[Index].VirtualAddress); + } + } + } + + // + // Load each section of the image + // + + // BUGBUG: change this to use the in memory copy + if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + OptionalHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER32); + PeHeaderSize = sizeof(EFI_IMAGE_NT_HEADERS32); + } else { + OptionalHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER64); + PeHeaderSize = sizeof(EFI_IMAGE_NT_HEADERS64); + } + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + Image->ImageBase + + DosHdr.e_lfanew + + PeHeaderSize + + PeHdr.Pe32.FileHeader.SizeOfOptionalHeader - + OptionalHeaderSize + ); + + Section = FirstSection; + for (Index=0; Index < PeHdr.Pe32.FileHeader.NumberOfSections; Index += 1) { + + // + // Compute sections address + // + + Base = EfiLdrPeCoffImageAddress (Image, (UINTN)Section->VirtualAddress); + End = EfiLdrPeCoffImageAddress (Image, (UINTN)(Section->VirtualAddress + Section->Misc.VirtualSize)); + + if (EFI_ERROR(Status) || !Base || !End) { + return EFI_LOAD_ERROR; + } + + // + // Read the section + // + + if (Section->SizeOfRawData) { + Status = EfiLdrPeCoffImageRead (FHand, Section->PointerToRawData, Section->SizeOfRawData, Base); + if (EFI_ERROR(Status)) { + return Status; + } + } + + // + // If raw size is less then virt size, zero fill the remaining + // + + if (Section->SizeOfRawData < Section->Misc.VirtualSize) { + ZeroMem ( + Base + Section->SizeOfRawData, + Section->Misc.VirtualSize - Section->SizeOfRawData + ); + } + + // + // Next Section + // + + Section += 1; + } + + // + // Copy in CodeView information if it exists + // + if (CodeViewSize != 0) { + Status = EfiLdrPeCoffImageRead (FHand, CodeViewFileOffset, CodeViewSize, Image->ImageBase + CodeViewOffset); + DebugEntry->RVA = (UINT32) (CodeViewOffset); + } + + // + // Apply relocations only if needed + // + if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + ImageBase = (UINT64)PeHdr.Pe32.OptionalHeader.ImageBase; + } else { + ImageBase = PeHdr.Pe32Plus.OptionalHeader.ImageBase; + } + if ((UINTN)(Image->ImageBase) != (UINTN) (ImageBase)) { + Status = EfiLdrPeCoffLoadPeRelocate ( + Image, + &DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC], + (UINTN) Image->ImageBase - (UINTN)ImageBase, + NumberOfMemoryMapEntries, + EfiMemoryDescriptor + ); + + if (EFI_ERROR(Status)) { + return Status; + } + } + + // + // Use exported EFI specific interface if present, else use the image's entry point + // + Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN) + (EfiLdrPeCoffImageAddress( + Image, + PeHdr.Pe32.OptionalHeader.AddressOfEntryPoint + )); + + return Status; +} + +EFI_STATUS +EfiLdrPeCoffLoadPeRelocate ( + IN EFILDR_LOADED_IMAGE *Image, + IN EFI_IMAGE_DATA_DIRECTORY *RelocDir, + IN UINTN Adjust, + IN UINTN *NumberOfMemoryMapEntries, + IN EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor + ) +{ + EFI_IMAGE_BASE_RELOCATION *RelocBase; + EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd; + UINT16 *Reloc; + UINT16 *RelocEnd; + UINT8 *Fixup; + UINT8 *FixupBase; + UINT16 *F16; + UINT32 *F32; + UINT64 *F64; + UINT8 *FixupData; + UINTN NoFixupPages; + + // + // Find the relocation block + // + + RelocBase = EfiLdrPeCoffImageAddress (Image, RelocDir->VirtualAddress); + RelocBaseEnd = EfiLdrPeCoffImageAddress (Image, RelocDir->VirtualAddress + RelocDir->Size); + if (!RelocBase || !RelocBaseEnd) { + return EFI_LOAD_ERROR; + } + + NoFixupPages = EFI_SIZE_TO_PAGES (RelocDir->Size / sizeof(UINT16) * sizeof(UINTN)); + Image->FixupData = (UINT8*) FindSpace (NoFixupPages, NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesData, EFI_MEMORY_WB); + if (Image->FixupData == 0) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Run the whole relocation block + // + + FixupData = Image->FixupData; + while (RelocBase < RelocBaseEnd) { + + Reloc = (UINT16 *) ((UINT8 *) RelocBase + sizeof(EFI_IMAGE_BASE_RELOCATION)); + RelocEnd = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock); + FixupBase = EfiLdrPeCoffImageAddress (Image, RelocBase->VirtualAddress); + if ((UINT8 *) RelocEnd < Image->ImageBase || (UINT8 *) RelocEnd > Image->ImageEof) { + return EFI_LOAD_ERROR; + } + + // + // Run this relocation record + // + + while (Reloc < RelocEnd) { + + Fixup = FixupBase + (*Reloc & 0xFFF); + switch ((*Reloc) >> 12) { + + case EFI_IMAGE_REL_BASED_ABSOLUTE: + break; + + case EFI_IMAGE_REL_BASED_HIGH: + F16 = (UINT16 *) Fixup; + *F16 = (UINT16) (*F16 + (UINT16)(((UINT32)Adjust) >> 16)); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *F16; + FixupData = FixupData + sizeof(UINT16); + } + break; + + case EFI_IMAGE_REL_BASED_LOW: + F16 = (UINT16 *) Fixup; + *F16 = (UINT16) (*F16 + (UINT16) Adjust); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *F16; + FixupData = FixupData + sizeof(UINT16); + } + break; + + case EFI_IMAGE_REL_BASED_HIGHLOW: + F32 = (UINT32 *) Fixup; + *F32 = *F32 + (UINT32) Adjust; + if (FixupData != NULL) { + FixupData = ALIGN_POINTER(FixupData, sizeof(UINT32)); + *(UINT32 *) FixupData = *F32; + FixupData = FixupData + sizeof(UINT32); + } + break; + + case EFI_IMAGE_REL_BASED_DIR64: + F64 = (UINT64 *) Fixup; + *F64 = *F64 + (UINT64) Adjust; + if (FixupData != NULL) { + FixupData = ALIGN_POINTER(FixupData, sizeof(UINT64)); + *(UINT64 *) FixupData = *F64; + FixupData = FixupData + sizeof(UINT64); + } + break; + + case EFI_IMAGE_REL_BASED_HIGHADJ: + CpuDeadLoop(); // BUGBUG: not done + break; + + default: + CpuDeadLoop(); + return EFI_LOAD_ERROR; + } + + // Next reloc record + Reloc += 1; + } + + // next reloc block + RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd; + } + + // + // Add Fixup data to whole Image (assume Fixup data just below the image), so that there is no hole in the descriptor. + // Because only NoPages or ImageBasePage will be used in EfiLoader(), we update these 2 fields. + // + Image->NoPages += NoFixupPages; + Image->ImageBasePage -= (NoFixupPages << EFI_PAGE_SHIFT); + + return EFI_SUCCESS; +} + +EFI_STATUS +EfiLdrPeCoffImageRead ( + IN VOID *FHand, + IN UINTN Offset, + IN OUT UINTN ReadSize, + OUT VOID *Buffer + ) +{ + CopyMem (Buffer, (VOID *)((UINTN)FHand + Offset), ReadSize); + + return EFI_SUCCESS; +} + +VOID * +EfiLdrPeCoffImageAddress ( + IN EFILDR_LOADED_IMAGE *Image, + IN UINTN Address + ) +{ + UINT8 *FixedAddress; + + FixedAddress = Image->ImageAdjust + Address; + + if ((FixedAddress < Image->ImageBase) || (FixedAddress > Image->ImageEof)) { + FixedAddress = NULL; + } + + return FixedAddress; +} + + +EFI_STATUS +EfiLdrPeCoffSetImageType ( + IN OUT EFILDR_LOADED_IMAGE *Image, + IN UINTN ImageType + ) +{ + EFI_MEMORY_TYPE CodeType; + EFI_MEMORY_TYPE DataType; + + switch (ImageType) { + case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION: + CodeType = EfiLoaderCode; + DataType = EfiLoaderData; + break; + + case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: + CodeType = EfiBootServicesCode; + DataType = EfiBootServicesData; + break; + + case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: + CodeType = EfiRuntimeServicesCode; + DataType = EfiRuntimeServicesData; + break; + + default: + return EFI_INVALID_PARAMETER; + } + + Image->Type = ImageType; + Image->Info.ImageCodeType = CodeType; + Image->Info.ImageDataType = DataType; + + return EFI_SUCCESS; +} + +EFI_STATUS +EfiLdrPeCoffCheckImageMachineType ( + IN UINT16 MachineType + ) +{ + EFI_STATUS Status; + + Status = EFI_UNSUPPORTED; + +#ifdef MDE_CPU_IA32 + if (MachineType == EFI_IMAGE_MACHINE_IA32) { + Status = EFI_SUCCESS; + } +#endif + +#ifdef MDE_CPU_X64 + if (MachineType == EFI_IMAGE_MACHINE_X64) { + Status = EFI_SUCCESS; + } +#endif + + return Status; +} diff --git a/Legacy/BootPlatform/EfiLdr/PeLoader.h b/Legacy/BootPlatform/EfiLdr/PeLoader.h new file mode 100644 index 0000000000000000000000000000000000000000..dcea63f58fad43781372fe8d09e8615d8a7a0959 --- /dev/null +++ b/Legacy/BootPlatform/EfiLdr/PeLoader.h @@ -0,0 +1,42 @@ +/*++ + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + PeLoader.h + +Abstract: + +Revision History: + +--*/ + +#ifndef _EFILDR_PELOADER_H_ +#define _EFILDR_PELOADER_H_ + +#include "EfiLdr.h" + +EFI_STATUS +EfiLdrGetPeImageInfo ( + IN VOID *FHand, + OUT UINT64 *ImageBase, + OUT UINT32 *ImageSize + ); + +EFI_STATUS +EfiLdrPeCoffLoadPeImage ( + IN VOID *FHand, + IN EFILDR_LOADED_IMAGE *Image, + IN UINTN *NumberOfMemoryMapEntries, + IN EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor + ); + + +#endif diff --git a/Legacy/BootPlatform/EfiLdr/Support.c b/Legacy/BootPlatform/EfiLdr/Support.c new file mode 100644 index 0000000000000000000000000000000000000000..b09c9b67425032f9310276c86e543ec79144a973 --- /dev/null +++ b/Legacy/BootPlatform/EfiLdr/Support.c @@ -0,0 +1,311 @@ +/*++ + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + Support.c + +Abstract: + +Revision History: + +--*/ +#include "EfiLdr.h" +#include + +EFI_STATUS +EfiAddMemoryDescriptor( + UINTN *NoDesc, + EFI_MEMORY_DESCRIPTOR *Desc, + EFI_MEMORY_TYPE Type, + EFI_PHYSICAL_ADDRESS BaseAddress, + UINT64 NoPages, + UINT64 Attribute + ) +{ + UINTN NumberOfDesc; + UINT64 Temp; + UINTN Index; + + if (NoPages == 0) { + return EFI_SUCCESS; + } + + // + // See if the new memory descriptor needs to be carved out of an existing memory descriptor + // + + NumberOfDesc = *NoDesc; + for (Index = 0; Index < NumberOfDesc; Index++) { + + if (Desc[Index].Type == EfiConventionalMemory) { + + Temp = DivU64x32 ((BaseAddress - Desc[Index].PhysicalStart), EFI_PAGE_SIZE) + NoPages; + + if ((Desc[Index].PhysicalStart < BaseAddress) && (Desc[Index].NumberOfPages >= Temp)) { + if (Desc[Index].NumberOfPages > Temp) { + Desc[*NoDesc].Type = EfiConventionalMemory; + Desc[*NoDesc].PhysicalStart = BaseAddress + MultU64x32 (NoPages, EFI_PAGE_SIZE); + Desc[*NoDesc].NumberOfPages = Desc[Index].NumberOfPages - Temp; + Desc[*NoDesc].VirtualStart = 0; + Desc[*NoDesc].Attribute = Desc[Index].Attribute; + *NoDesc = *NoDesc + 1; + } + Desc[Index].NumberOfPages = Temp - NoPages; + } + + if ((Desc[Index].PhysicalStart == BaseAddress) && (Desc[Index].NumberOfPages == NoPages)) { + Desc[Index].Type = Type; + Desc[Index].Attribute = Attribute; + return EFI_SUCCESS; + } + + if ((Desc[Index].PhysicalStart == BaseAddress) && (Desc[Index].NumberOfPages > NoPages)) { + Desc[Index].NumberOfPages -= NoPages; + Desc[Index].PhysicalStart += MultU64x32 (NoPages, EFI_PAGE_SIZE); + } + } + } + + // + // Add the new memory descriptor + // + + Desc[*NoDesc].Type = Type; + Desc[*NoDesc].PhysicalStart = BaseAddress; + Desc[*NoDesc].NumberOfPages = NoPages; + Desc[*NoDesc].VirtualStart = 0; + Desc[*NoDesc].Attribute = Attribute; + *NoDesc = *NoDesc + 1; + + return EFI_SUCCESS; +} + +UINTN +FindSpace ( + UINTN NoPages, + IN UINTN *NumberOfMemoryMapEntries, + IN EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor, + EFI_MEMORY_TYPE Type, + UINT64 Attribute + ) +{ + EFI_PHYSICAL_ADDRESS MaxPhysicalStart; + UINT64 MaxNoPages; + UINTN Index; + EFI_MEMORY_DESCRIPTOR *CurrentMemoryDescriptor; + + MaxPhysicalStart = 0; + MaxNoPages = 0; + CurrentMemoryDescriptor = NULL; + for (Index = 0; Index < *NumberOfMemoryMapEntries; Index++) { + if (EfiMemoryDescriptor[Index].PhysicalStart + LShiftU64(EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT) <= 0x100000) { + continue; + } + if ((EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) && + (EfiMemoryDescriptor[Index].NumberOfPages >= NoPages)) { + if (EfiMemoryDescriptor[Index].PhysicalStart > MaxPhysicalStart) { + if (EfiMemoryDescriptor[Index].PhysicalStart + LShiftU64(EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT) <= 0x100000000ULL) { + MaxPhysicalStart = EfiMemoryDescriptor[Index].PhysicalStart; + MaxNoPages = EfiMemoryDescriptor[Index].NumberOfPages; + CurrentMemoryDescriptor = &EfiMemoryDescriptor[Index]; + } + } + } + if ((EfiMemoryDescriptor[Index].Type == EfiReservedMemoryType) || + (EfiMemoryDescriptor[Index].Type >= EfiACPIReclaimMemory) ) { + continue; + } + if ((EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesCode) || + (EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesData)) { + break; + } + } + + if (MaxPhysicalStart == 0) { + return 0; + } + + if (MaxNoPages != NoPages) { + CurrentMemoryDescriptor->NumberOfPages = MaxNoPages - NoPages; + EfiMemoryDescriptor[*NumberOfMemoryMapEntries].Type = Type; + EfiMemoryDescriptor[*NumberOfMemoryMapEntries].PhysicalStart = MaxPhysicalStart + LShiftU64(MaxNoPages - NoPages, EFI_PAGE_SHIFT); + EfiMemoryDescriptor[*NumberOfMemoryMapEntries].NumberOfPages = NoPages; + EfiMemoryDescriptor[*NumberOfMemoryMapEntries].VirtualStart = 0; + EfiMemoryDescriptor[*NumberOfMemoryMapEntries].Attribute = Attribute; + *NumberOfMemoryMapEntries = *NumberOfMemoryMapEntries + 1; + } else { + CurrentMemoryDescriptor->Type = Type; + CurrentMemoryDescriptor->Attribute = Attribute; + } + + return (UINTN)(MaxPhysicalStart + LShiftU64(MaxNoPages - NoPages, EFI_PAGE_SHIFT)); +} + +VOID +GenMemoryMap ( + UINTN *NumberOfMemoryMapEntries, + EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor, + BIOS_MEMORY_MAP *BiosMemoryMap + ) +{ + UINT64 BaseAddress; + UINT64 Length; + EFI_MEMORY_TYPE Type; + UINTN Index; + UINTN Attr; + UINT64 Ceiling; + UINT64 EBDAaddr; + UINT64 EBDAmax; + UINT64 EBDAsize; + + // + // ** CHANGE START ** + // See DxeIpl PrepareHobMemory. + // EBDA memory protection + // + EBDAaddr = LShiftU64 ((UINT64)(*(volatile UINT16 *)(UINTN)(0x40E)), 4); + if (EBDAaddr < 0x90000 || EBDAaddr > 0x9F800) { + EBDAaddr = 0x9A000; + } + EBDAmax = 0x100000; + EBDAsize = 2; + // + // ** CHANGE END ** + // + + Ceiling = 0xFFFFFFFF; + for (Index = 0; Index < BiosMemoryMap->MemoryMapSize / sizeof(BIOS_MEMORY_MAP_ENTRY); Index++) { + + switch (BiosMemoryMap->MemoryMapEntry[Index].Type) { + case (INT15_E820_AddressRangeMemory): + Type = EfiConventionalMemory; + Attr = EFI_MEMORY_WB; + break; + case (INT15_E820_AddressRangeReserved): + Type = EfiReservedMemoryType; + Attr = EFI_MEMORY_UC; + break; + case (INT15_E820_AddressRangeACPI): + Type = EfiACPIReclaimMemory; + Attr = EFI_MEMORY_WB; + break; + case (INT15_E820_AddressRangeNVS): + Type = EfiACPIMemoryNVS; + Attr = EFI_MEMORY_UC; + break; + default: + // We should not get here, according to ACPI 2.0 Spec. + // BIOS behaviour of the Int15h, E820h + Type = EfiReservedMemoryType; + Attr = EFI_MEMORY_UC; + break; + } + if (Type == EfiConventionalMemory) { + BaseAddress = BiosMemoryMap->MemoryMapEntry[Index].BaseAddress; + Length = BiosMemoryMap->MemoryMapEntry[Index].Length; + if (BaseAddress & EFI_PAGE_MASK) { + Length = Length + (BaseAddress & EFI_PAGE_MASK) - EFI_PAGE_SIZE; + // + // ** CHANGE ** + // Formerly was LShiftU64 (RShiftU64 (BaseAddress, EFI_PAGE_SHIFT) + 1. + // + BaseAddress = LShiftU64 (RShiftU64 (BaseAddress + EFI_PAGE_MASK, EFI_PAGE_SHIFT), EFI_PAGE_SHIFT); + } + } else { + BaseAddress = BiosMemoryMap->MemoryMapEntry[Index].BaseAddress; + Length = BiosMemoryMap->MemoryMapEntry[Index].Length + (BaseAddress & EFI_PAGE_MASK); + BaseAddress = LShiftU64 (RShiftU64 (BaseAddress, EFI_PAGE_SHIFT), EFI_PAGE_SHIFT); + if (Length & EFI_PAGE_MASK) { + Length = LShiftU64 (RShiftU64 (Length, EFI_PAGE_SHIFT) + 1, EFI_PAGE_SHIFT); + } + // + // Update Memory Ceiling + // + if ((BaseAddress >= 0x100000ULL) && (BaseAddress < 0x100000000ULL)) { + if (Ceiling > BaseAddress) { + Ceiling = BaseAddress; + } + } + // + // ** CHANGE START ** + // Ignore the EBDA and bios rom area + // + if (BaseAddress < EBDAaddr) { + if ((BaseAddress + Length) >= EBDAaddr) { + continue; + } + } else if (BaseAddress < EBDAmax) { + continue; + } + // + // ** CHANGE END ** + // + } + + EfiAddMemoryDescriptor ( + NumberOfMemoryMapEntries, + EfiMemoryDescriptor, + Type, + (EFI_PHYSICAL_ADDRESS)(UINTN) BaseAddress, + RShiftU64 (Length, EFI_PAGE_SHIFT), + Attr + ); + } + + // + // ** CHANGE START ** + // Workaround memory KP in SnowLeopard by protecting from the EBDA to the 1MB barrier. + // + EBDAsize = EBDAmax - EBDAaddr; + EfiAddMemoryDescriptor ( + NumberOfMemoryMapEntries, + EfiMemoryDescriptor, + EfiReservedMemoryType, + (EFI_PHYSICAL_ADDRESS)EBDAaddr, + RShiftU64 (EBDAsize + EFI_PAGE_MASK, EFI_PAGE_SHIFT), + EFI_MEMORY_UC + ); + + // + // Reserve our bootstrap code as we may access this memory later. + // + EfiAddMemoryDescriptor ( + NumberOfMemoryMapEntries, + EfiMemoryDescriptor, + EfiReservedMemoryType, + (EFI_PHYSICAL_ADDRESS) BOOT1_BASE, + 1, + EFI_MEMORY_UC + ); + + // + // Update MemoryMap according to Ceiling + // +#if 0 + // + // We'll leave BIOS mem map untouched and add those EfiConventionalMemory + // areas to UEFI mem map in BdsPlatformLib:UpdateMemoryMap(). + // Change by dmazar. + // + for (Index = 0; Index < *NumberOfMemoryMapEntries; Index++) { + if ((EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) && + (EfiMemoryDescriptor[Index].PhysicalStart > 0x100000ULL) && + (EfiMemoryDescriptor[Index].PhysicalStart < 0x100000000ULL)) { + if (EfiMemoryDescriptor[Index].PhysicalStart >= Ceiling) { + EfiMemoryDescriptor[Index].Type = EfiReservedMemoryType; + } + } + } +#endif + // + // ** CHANGE END ** + // +} diff --git a/Legacy/BootPlatform/EfiLdr/Support.h b/Legacy/BootPlatform/EfiLdr/Support.h new file mode 100644 index 0000000000000000000000000000000000000000..0b1318b1cf16dc95c6fbd0fa7a2a1a9d451e35e5 --- /dev/null +++ b/Legacy/BootPlatform/EfiLdr/Support.h @@ -0,0 +1,50 @@ +/*++ + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + Support.h + +Abstract: + +Revision History: + +--*/ + +#ifndef _EFILDR_SUPPORT_H_ +#define _EFILDR_SUPPORT_H_ + +EFI_STATUS +EfiAddMemoryDescriptor( + UINTN *NoDesc, + EFI_MEMORY_DESCRIPTOR *Desc, + EFI_MEMORY_TYPE Type, + EFI_PHYSICAL_ADDRESS BaseAddress, + UINT64 NoPages, + UINT64 Attribute + ); + +UINTN +FindSpace( + UINTN NoPages, + IN UINTN *NumberOfMemoryMapEntries, + IN EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor, + EFI_MEMORY_TYPE Type, + UINT64 Attribute + ); + +VOID +GenMemoryMap ( + UINTN *NumberOfMemoryMapEntries, + EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor, + BIOS_MEMORY_MAP *BiosMemoryMap + ); + +#endif diff --git a/Legacy/BootPlatform/LegacyRegion2Dxe/LegacyRegion2.c b/Legacy/BootPlatform/LegacyRegion2Dxe/LegacyRegion2.c new file mode 100644 index 0000000000000000000000000000000000000000..4e8932d97ebdd6e719d375b486b1d192d9d20702 --- /dev/null +++ b/Legacy/BootPlatform/LegacyRegion2Dxe/LegacyRegion2.c @@ -0,0 +1,792 @@ +/** @file + Legacy Region Support + + Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are + licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Modified by dmazar with support for different chipsets and added newer ones. + +**/ + +#include "LegacyRegion2.h" + +// +// Current chipset's tables +// +UINT32 mVendorDeviceId = 0; +STATIC PAM_REGISTER_VALUE *mRegisterValues = NULL; +UINT8 mPamPciBus = 0; +UINT8 mPamPciDev = 0; +UINT8 mPamPciFunc = 0; + +// +// Intel 830 Chipset and similar +// + +// +// 440 PAM map. +// +// PAM Range Offset Bits Operation +// =============== ====== ==== =============================================================== +// 0xC0000-0xC3FFF 0x5a 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xC4000-0xC7FFF 0x5a 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xC8000-0xCBFFF 0x5b 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xCC000-0xCFFFF 0x5b 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xD0000-0xD3FFF 0x5c 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xD4000-0xD7FFF 0x5c 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xD8000-0xDBFFF 0x5d 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xDC000-0xDFFFF 0x5d 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xE0000-0xE3FFF 0x5e 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xE4000-0xE7FFF 0x5e 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xE8000-0xEBFFF 0x5f 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xEC000-0xEFFFF 0x5f 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xF0000-0xFFFFF 0x59 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// +STATIC LEGACY_MEMORY_SECTION_INFO mSectionArray[] = { + {0xC0000, SIZE_16KB, FALSE, FALSE}, + {0xC4000, SIZE_16KB, FALSE, FALSE}, + {0xC8000, SIZE_16KB, FALSE, FALSE}, + {0xCC000, SIZE_16KB, FALSE, FALSE}, + {0xD0000, SIZE_16KB, FALSE, FALSE}, + {0xD4000, SIZE_16KB, FALSE, FALSE}, + {0xD8000, SIZE_16KB, FALSE, FALSE}, + {0xDC000, SIZE_16KB, FALSE, FALSE}, + {0xE0000, SIZE_16KB, FALSE, FALSE}, + {0xE4000, SIZE_16KB, FALSE, FALSE}, + {0xE8000, SIZE_16KB, FALSE, FALSE}, + {0xEC000, SIZE_16KB, FALSE, FALSE}, + {0xF0000, SIZE_64KB, FALSE, FALSE} +}; + +STATIC PAM_REGISTER_VALUE mRegisterValues830[] = { + {REG_PAM1_OFFSET_830, 0x01, 0x02}, + {REG_PAM1_OFFSET_830, 0x10, 0x20}, + {REG_PAM2_OFFSET_830, 0x01, 0x02}, + {REG_PAM2_OFFSET_830, 0x10, 0x20}, + {REG_PAM3_OFFSET_830, 0x01, 0x02}, + {REG_PAM3_OFFSET_830, 0x10, 0x20}, + {REG_PAM4_OFFSET_830, 0x01, 0x02}, + {REG_PAM4_OFFSET_830, 0x10, 0x20}, + {REG_PAM5_OFFSET_830, 0x01, 0x02}, + {REG_PAM5_OFFSET_830, 0x10, 0x20}, + {REG_PAM6_OFFSET_830, 0x01, 0x02}, + {REG_PAM6_OFFSET_830, 0x10, 0x20}, + {REG_PAM0_OFFSET_830, 0x10, 0x20} +}; + + +// +// Intel 4 Series Chipset and similar +// + +// +// PAM map. +// +// PAM Range Offset Bits Operation +// =============== ====== ==== =============================================================== +// 0xC0000-0xC3FFF 0x91 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xC4000-0xC7FFF 0x91 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xC8000-0xCBFFF 0x92 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xCC000-0xCFFFF 0x92 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xD0000-0xD3FFF 0x93 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xD4000-0xD7FFF 0x93 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xD8000-0xDBFFF 0x94 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xDC000-0xDFFFF 0x94 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xE0000-0xE3FFF 0x95 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xE4000-0xE7FFF 0x95 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xE8000-0xEBFFF 0x96 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xEC000-0xEFFFF 0x96 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xF0000-0xFFFFF 0x90 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// + +STATIC PAM_REGISTER_VALUE mRegisterValuesS4[] = { + {REG_PAM1_OFFSET_S4, 0x01, 0x02}, + {REG_PAM1_OFFSET_S4, 0x10, 0x20}, + {REG_PAM2_OFFSET_S4, 0x01, 0x02}, + {REG_PAM2_OFFSET_S4, 0x10, 0x20}, + {REG_PAM3_OFFSET_S4, 0x01, 0x02}, + {REG_PAM3_OFFSET_S4, 0x10, 0x20}, + {REG_PAM4_OFFSET_S4, 0x01, 0x02}, + {REG_PAM4_OFFSET_S4, 0x10, 0x20}, + {REG_PAM5_OFFSET_S4, 0x01, 0x02}, + {REG_PAM5_OFFSET_S4, 0x10, 0x20}, + {REG_PAM6_OFFSET_S4, 0x01, 0x02}, + {REG_PAM6_OFFSET_S4, 0x10, 0x20}, + {REG_PAM0_OFFSET_S4, 0x10, 0x20} +}; + +// +// Core processors +// + +// +// PAM map. +// +// PAM Range Offset Bits Operation +// =============== ====== ==== =============================================================== +// 0xC0000-0xC3FFF 0x81 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xC4000-0xC7FFF 0x81 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xC8000-0xCBFFF 0x82 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xCC000-0xCFFFF 0x82 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xD0000-0xD3FFF 0x83 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xD4000-0xD7FFF 0x83 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xD8000-0xDBFFF 0x84 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xDC000-0xDFFFF 0x84 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xE0000-0xE3FFF 0x85 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xE4000-0xE7FFF 0x85 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xE8000-0xEBFFF 0x86 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xEC000-0xEFFFF 0x86 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// 0xF0000-0xFFFFF 0x80 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal +// + +STATIC PAM_REGISTER_VALUE mRegisterValuesCP[] = { + {REG_PAM1_OFFSET_CP, 0x01, 0x02}, + {REG_PAM1_OFFSET_CP, 0x10, 0x20}, + {REG_PAM2_OFFSET_CP, 0x01, 0x02}, + {REG_PAM2_OFFSET_CP, 0x10, 0x20}, + {REG_PAM3_OFFSET_CP, 0x01, 0x02}, + {REG_PAM3_OFFSET_CP, 0x10, 0x20}, + {REG_PAM4_OFFSET_CP, 0x01, 0x02}, + {REG_PAM4_OFFSET_CP, 0x10, 0x20}, + {REG_PAM5_OFFSET_CP, 0x01, 0x02}, + {REG_PAM5_OFFSET_CP, 0x10, 0x20}, + {REG_PAM6_OFFSET_CP, 0x01, 0x02}, + {REG_PAM6_OFFSET_CP, 0x10, 0x20}, + {REG_PAM0_OFFSET_CP, 0x10, 0x20} +}; + +STATIC PAM_REGISTER_VALUE mRegisterValuesNH[] = { + {REG_PAM1_OFFSET_NH, 0x01, 0x02}, + {REG_PAM1_OFFSET_NH, 0x10, 0x20}, + {REG_PAM2_OFFSET_NH, 0x01, 0x02}, + {REG_PAM2_OFFSET_NH, 0x10, 0x20}, + {REG_PAM3_OFFSET_NH, 0x01, 0x02}, + {REG_PAM3_OFFSET_NH, 0x10, 0x20}, + {REG_PAM4_OFFSET_NH, 0x01, 0x02}, + {REG_PAM4_OFFSET_NH, 0x10, 0x20}, + {REG_PAM5_OFFSET_NH, 0x01, 0x02}, + {REG_PAM5_OFFSET_NH, 0x10, 0x20}, + {REG_PAM6_OFFSET_NH, 0x01, 0x02}, + {REG_PAM6_OFFSET_NH, 0x10, 0x20}, + {REG_PAM0_OFFSET_NH, 0x10, 0x20} +}; + +// +// NForce chipset +// + +STATIC PAM_REGISTER_VALUE mRegisterValuesNV[] = { + {REG_PAM1_OFFSET_NV, 0x01, 0x02}, + {REG_PAM1_OFFSET_NV, 0x10, 0x20}, + {REG_PAM2_OFFSET_NV, 0x01, 0x02}, + {REG_PAM2_OFFSET_NV, 0x10, 0x20}, + {REG_PAM3_OFFSET_NV, 0x01, 0x02}, + {REG_PAM3_OFFSET_NV, 0x10, 0x20}, + {REG_PAM4_OFFSET_NV, 0x01, 0x02}, + {REG_PAM4_OFFSET_NV, 0x10, 0x20}, + {REG_PAM5_OFFSET_NV, 0x01, 0x02}, + {REG_PAM5_OFFSET_NV, 0x10, 0x20}, + {REG_PAM6_OFFSET_NV, 0x01, 0x02}, + {REG_PAM6_OFFSET_NV, 0x10, 0x20}, + {REG_PAM0_OFFSET_NV, 0x10, 0x20} +}; + +// +// Handle used to install the Legacy Region Protocol +// +STATIC EFI_HANDLE mHandle = NULL; + +// +// Instance of the Legacy Region Protocol to install into the handle database +// +STATIC EFI_LEGACY_REGION2_PROTOCOL mLegacyRegion2 = { + LegacyRegion2Decode, + LegacyRegion2Lock, + LegacyRegion2BootLock, + LegacyRegion2Unlock, + LegacyRegionGetInfo +}; + +STATIC +EFI_STATUS +LegacyRegionManipulationInternal ( + IN UINT32 Start, + IN UINT32 Length, + IN BOOLEAN *ReadEnable, + IN BOOLEAN *WriteEnable, + OUT UINT32 *Granularity + ) +{ + UINT32 EndAddress; + UINTN Index; + UINTN StartIndex; + + // + // Validate input parameters. + // + if (Length == 0 || Granularity == NULL) { + return EFI_INVALID_PARAMETER; + } + EndAddress = Start + Length - 1; + if ((Start < PAM_BASE_ADDRESS) || EndAddress > PAM_LIMIT_ADDRESS) { + return EFI_INVALID_PARAMETER; + } + + // + // Loop to find the start PAM. + // + StartIndex = 0; + for (Index = 0; Index < (sizeof(mSectionArray) / sizeof(mSectionArray[0])); Index++) { + if ((Start >= mSectionArray[Index].Start) && (Start < (mSectionArray[Index].Start + mSectionArray[Index].Length))) { + StartIndex = Index; + break; + } + } + ASSERT (Index < (sizeof(mSectionArray) / sizeof(mSectionArray[0]))); + + // + // Program PAM until end PAM is encountered + // + for (Index = StartIndex; Index < (sizeof(mSectionArray) / sizeof(mSectionArray[0])); Index++) { + if (ReadEnable != NULL) { + if (*ReadEnable) { + PciOr8 ( + PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, mRegisterValues[Index].PAMRegOffset), + mRegisterValues[Index].ReadEnableData + ); + } else { + PciAnd8 ( + PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, mRegisterValues[Index].PAMRegOffset), + (UINT8) (~mRegisterValues[Index].ReadEnableData) + ); + } + } + if (WriteEnable != NULL) { + if (*WriteEnable) { + PciOr8 ( + PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, mRegisterValues[Index].PAMRegOffset), + mRegisterValues[Index].WriteEnableData + ); + } else { + PciAnd8 ( + PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, mRegisterValues[Index].PAMRegOffset), + (UINT8) (~mRegisterValues[Index].WriteEnableData) + ); + } + } + + // + // If the end PAM is encountered, record its length as granularity and jump out. + // + if ((EndAddress >= mSectionArray[Index].Start) && (EndAddress < (mSectionArray[Index].Start + mSectionArray[Index].Length))) { + *Granularity = mSectionArray[Index].Length; + break; + } + } + ASSERT (Index < (sizeof(mSectionArray) / sizeof(mSectionArray[0]))); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +LegacyRegionGetInfoInternal ( + OUT UINT32 *DescriptorCount, + OUT LEGACY_MEMORY_SECTION_INFO **Descriptor + ) +{ + UINTN Index; + UINT8 PamValue; + + // + // Check input parameters + // + if (DescriptorCount == NULL || Descriptor == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Fill in current status of legacy region. + // + *DescriptorCount = (sizeof(mSectionArray) / sizeof(mSectionArray[0])); + for (Index = 0; Index < *DescriptorCount; Index++) { + PamValue = PciRead8 (PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, mRegisterValues[Index].PAMRegOffset)); + mSectionArray[Index].ReadEnabled = FALSE; + if ((PamValue & mRegisterValues[Index].ReadEnableData) != 0) { + mSectionArray[Index].ReadEnabled = TRUE; + } + mSectionArray[Index].WriteEnabled = FALSE; + if ((PamValue & mRegisterValues[Index].WriteEnableData) != 0) { + mSectionArray[Index].WriteEnabled = TRUE; + } + } + + *Descriptor = mSectionArray; + return EFI_SUCCESS; +} + +/** + Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region. + + If the On parameter evaluates to TRUE, this function enables memory reads in the address range + Start to (Start + Length - 1). + If the On parameter evaluates to FALSE, this function disables memory reads in the address range + Start to (Start + Length - 1). + + @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance. + @param Start[in] The beginning of the physical address of the region whose attributes + should be modified. + @param Length[in] The number of bytes of memory whose attributes should be modified. + The actual number of bytes modified may be greater than the number + specified. + @param Granularity[out] The number of bytes in the last region affected. This may be less + than the total number of bytes affected if the starting address + was not aligned to a region's starting address or if the length + was greater than the number of bytes in the first region. + @param On[in] Decode / Non-Decode flag. + + @retval EFI_SUCCESS The region's attributes were successfully modified. + @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region. + +**/ +EFI_STATUS +EFIAPI +LegacyRegion2Decode ( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity, + IN BOOLEAN *On + ) +{ + return LegacyRegionManipulationInternal (Start, Length, On, NULL, Granularity); +} + + +/** + Modify the hardware to disallow memory attribute changes in a region. + + This function makes the attributes of a region read only. Once a region is boot-locked with this + function, the read and write attributes of that region cannot be changed until a power cycle has + reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect. + + @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance. + @param Start[in] The beginning of the physical address of the region whose + attributes should be modified. + @param Length[in] The number of bytes of memory whose attributes should be modified. + The actual number of bytes modified may be greater than the number + specified. + @param Granularity[out] The number of bytes in the last region affected. This may be less + than the total number of bytes affected if the starting address was + not aligned to a region's starting address or if the length was + greater than the number of bytes in the first region. + + @retval EFI_SUCCESS The region's attributes were successfully modified. + @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region. + @retval EFI_UNSUPPORTED The chipset does not support locking the configuration registers in + a way that will not affect memory regions outside the legacy memory + region. + +**/ +EFI_STATUS +EFIAPI +LegacyRegion2BootLock ( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity + ) +{ + if ((Start < 0xC0000) || ((Start + Length - 1) > 0xFFFFF)) { + return EFI_INVALID_PARAMETER; + } + + return EFI_UNSUPPORTED; +} + + +/** + Modify the hardware to disallow memory writes in a region. + + This function changes the attributes of a memory range to not allow writes. + + @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance. + @param Start[in] The beginning of the physical address of the region whose + attributes should be modified. + @param Length[in] The number of bytes of memory whose attributes should be modified. + The actual number of bytes modified may be greater than the number + specified. + @param Granularity[out] The number of bytes in the last region affected. This may be less + than the total number of bytes affected if the starting address was + not aligned to a region's starting address or if the length was + greater than the number of bytes in the first region. + + @retval EFI_SUCCESS The region's attributes were successfully modified. + @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region. + +**/ +EFI_STATUS +EFIAPI +LegacyRegion2Lock ( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity + ) +{ + BOOLEAN WriteEnable; + + WriteEnable = FALSE; + return LegacyRegionManipulationInternal (Start, Length, NULL, &WriteEnable, Granularity); +} + + +/** + Modify the hardware to allow memory writes in a region. + + This function changes the attributes of a memory range to allow writes. + + @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance. + @param Start[in] The beginning of the physical address of the region whose + attributes should be modified. + @param Length[in] The number of bytes of memory whose attributes should be modified. + The actual number of bytes modified may be greater than the number + specified. + @param Granularity[out] The number of bytes in the last region affected. This may be less + than the total number of bytes affected if the starting address was + not aligned to a region's starting address or if the length was + greater than the number of bytes in the first region. + + @retval EFI_SUCCESS The region's attributes were successfully modified. + @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region. + +**/ +EFI_STATUS +EFIAPI +LegacyRegion2Unlock ( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity + ) +{ + BOOLEAN WriteEnable; + + WriteEnable = TRUE; + return LegacyRegionManipulationInternal (Start, Length, NULL, &WriteEnable, Granularity); +} + +/** + Get region information for the attributes of the Legacy Region. + + This function is used to discover the granularity of the attributes for the memory in the legacy + region. Each attribute may have a different granularity and the granularity may not be the same + for all memory ranges in the legacy region. + + @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance. + @param DescriptorCount[out] The number of region descriptor entries returned in the Descriptor + buffer. + @param Descriptor[out] A pointer to a pointer used to return a buffer where the legacy + region information is deposited. This buffer will contain a list of + DescriptorCount number of region descriptors. This function will + provide the memory for the buffer. + + @retval EFI_SUCCESS The region's attributes were successfully modified. + @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region. + +**/ +EFI_STATUS +EFIAPI +LegacyRegionGetInfo ( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + OUT UINT32 *DescriptorCount, + OUT EFI_LEGACY_REGION_DESCRIPTOR **Descriptor + ) +{ + LEGACY_MEMORY_SECTION_INFO *SectionInfo; + UINT32 SectionCount; + EFI_LEGACY_REGION_DESCRIPTOR *DescriptorArray; + UINTN Index; + UINTN DescriptorIndex; + + // + // Get section numbers and information + // + LegacyRegionGetInfoInternal (&SectionCount, &SectionInfo); + + // + // Each section has 3 descriptors, corresponding to readability, writeability, and lock status. + // + DescriptorArray = AllocatePool (sizeof (EFI_LEGACY_REGION_DESCRIPTOR) * SectionCount * 3); + if (DescriptorArray == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + DescriptorIndex = 0; + for (Index = 0; Index < SectionCount; Index++) { + DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start; + DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length; + DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length; + if (SectionInfo[Index].ReadEnabled) { + DescriptorArray[DescriptorIndex].Attribute = LegacyRegionDecoded; + } else { + DescriptorArray[DescriptorIndex].Attribute = LegacyRegionNotDecoded; + } + DescriptorIndex++; + + // + // Create descriptor for writeability, according to lock status + // + DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start; + DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length; + DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length; + if (SectionInfo[Index].WriteEnabled) { + DescriptorArray[DescriptorIndex].Attribute = LegacyRegionWriteEnabled; + } else { + DescriptorArray[DescriptorIndex].Attribute = LegacyRegionWriteDisabled; + } + DescriptorIndex++; + + // + // Chipset does not support bootlock. + // + DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start; + DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length; + DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length; + DescriptorArray[DescriptorIndex].Attribute = LegacyRegionNotLocked; + DescriptorIndex++; + } + + *DescriptorCount = (UINT32) DescriptorIndex; + *Descriptor = DescriptorArray; + + return EFI_SUCCESS; +} + + +/** + Detects chipset and initialize PAM support tables + + @retval EFI_SUCCESS Successfully initialized + +**/ +EFI_STATUS +DetectChipset ( + VOID + ) +{ + UINT16 VID = 0; + UINT16 DID = 0; + + mRegisterValues = NULL; + + mVendorDeviceId = PciRead32 (PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, 0)); + + switch (mVendorDeviceId) { + + // + // Intel 830 and similar + // Copied from 915 resolution created by steve tomljenovic, + // Resolution module by Evan Lojewski + // + case 0x35758086: // 830 + case 0x35808086: // 855GM + /// Intel 830 and similar (PAM 0x59-0x5f). + mRegisterValues = mRegisterValues830; + break; + + case 0x25C08086: // 5000 + case 0x25D48086: // 5000V + case 0x65C08086: // 5100 + /// Intel 5000 and similar (PAM 0x59-0x5f). + mRegisterValues = mRegisterValues830; + mPamPciDev = 16; + break; + + // + // Intel Series 4 and similar + // Copied from 915 resolution created by steve tomljenovic, + // Resolution module by Evan Lojewski + // + case 0x25608086: // 845G + case 0x25708086: // 865G + case 0x25808086: // 915G + case 0x25908086: // 915GM + + case 0x27708086: // 945G + case 0x27748086: // 955X + case 0x277c8086: // 975X + case 0x27a08086: // 945GM - Dell D430 Offset 090: 10 11 11 00 00 + case 0x27ac8086: // 945GME + case 0x29208086: // G45 + case 0x29708086: // 946GZ + case 0x29808086: // G965 + case 0x29908086: // Q965 + case 0x29a08086: // P965 + case 0x29b08086: // R845 + case 0x29c08086: // G31/P35 + case 0x29d08086: // Q33 + case 0x29e08086: // X38/X48 + case 0x2a008086: // 965GM + case 0x2a108086: // GME965/GLE960 + case 0x2a408086: // PM/GM45/47 + case 0x2e008086: // Eaglelake + case 0x2e108086: // B43 + case 0x2e208086: // P45 + case 0x2e308086: // G41 + case 0x2e408086: // B43 Base + case 0x2e908086: // B43 Soft Sku + case 0x81008086: // 500 + case 0xA0008086: // 3150 + /// Intel Series 4 and similar (PAM 0x90-0x96). + mRegisterValues = mRegisterValuesS4; + break; + + // + // Core processors + // http://pci-ids.ucw.cz/read/PC/8086 + // + case 0x01008086: // 2nd Generation Core Processor Family DRAM Controller + case 0x01048086: // 2nd Generation Core Processor Family DRAM Controller + case 0x01088086: // Xeon E3-1200 2nd Generation Core Processor Family DRAM Controller + case 0x010c8086: // Xeon E3-1200 2nd Generation Core Processor Family DRAM Controller + + case 0x01508086: // 3rd Generation Core Processor Family DRAM Controller + case 0x01548086: // 3rd Generation Core Processor Family DRAM Controller + case 0x01588086: // 3rd Generation Core Processor Family DRAM Controller + case 0x015c8086: // 3rd Generation Core Processor Family DRAM Controller + + case 0x01608086: // 3rd Generation Core Processor Family DRAM Controller + case 0x01648086: // 3rd Generation Core Processor Family DRAM Controller + + case 0x0C008086: // 4rd Generation Core Processor Family DRAM Controller + case 0x0C048086: // 4rd Generation M-Processor Series + case 0x0C088086: // 4rd Generation Haswell Xeon + case 0x0A048086: // 4rd Generation U-Processor Series + case 0x0D048086: // 4rd Generation H-Processor Series (BGA) with GT3 Graphics + case 0x16048086: // 5th Generation Core Processor Family DRAM Controller + + case 0x191f8086: // 6th Generation (Skylake) DRAM Controller (Z170X) + + case 0x0F008086: // Bay Trail Family DRAM Controller + /// Next Generation Core processors (PAM 0x80-0x86). + mRegisterValues = mRegisterValuesCP; + break; + + // + // 1st gen i7 - Nehalem + // + case 0x00408086: // Core Processor DRAM Controller + case 0x00448086: // Core Processor DRAM Controller - Arrandale + case 0x00488086: // Core Processor DRAM Controller + case 0x00698086: // Core Processor DRAM Controller + + case 0xD1308086: // Xeon(R) CPU L3426 Processor DRAM Controller + case 0xD1318086: // Core-i Processor DRAM Controller + case 0xD1328086: // PM55 i7-720QM DRAM Controller + case 0x34008086: // Core-i Processor DRAM Controller + case 0x34018086: // Core-i Processor DRAM Controller + case 0x34028086: // Core-i Processor DRAM Controller + case 0x34038086: // Core-i Processor DRAM Controller + case 0x34048086: // Core-i Processor DRAM Controller + case 0x34058086: // X58 Core-i Processor DRAM Controller + case 0x34068086: // Core-i Processor DRAM Controller + case 0x34078086: // Core-i Processor DRAM Controller + /// Core i7 processors (PAM 0x40-0x47). + mRegisterValues = mRegisterValuesNH; + mPamPciBus = 0xFF; + for (mPamPciBus = 0xFF; mPamPciBus > 0x1F; mPamPciBus >>= 1) { + VID = PciRead16 (PCI_LIB_ADDRESS(mPamPciBus, 0, 1, 0x00)); + if (VID != 0x8086) { + continue; + } + DID = PciRead16 (PCI_LIB_ADDRESS(mPamPciBus, 0, 1, 0x02)); + if (DID > 0x2c00) { + break; + } + } + if ((VID != 0x8086) || (DID < 0x2c00)) { + // + // Nehalem bus is not found, assume 0. + // + mPamPciBus = 0; + } else { + mPamPciFunc = 1; + } + break; + case 0x3C008086: // Xeon E5 Processor + /// Xeon E5 processors (PAM 0x40-0x47). + mRegisterValues = mRegisterValuesNH; + mPamPciBus = PciRead8 (PCI_LIB_ADDRESS(0, 5, 0, 0x109)); + mPamPciDev = 12; + mPamPciFunc = 6; + break; + + case 0x0a8210de: + case 0x0a8610de: + /// NForce MCP79 and similar (PAM 0xC0-0xC7). + mRegisterValues = mRegisterValuesNV; + break; + + default: + // Unknown chipset. + break; + } + + return mRegisterValues != NULL ? EFI_SUCCESS : EFI_NOT_FOUND; +} + +/** + Initialize Legacy Region support + + @retval EFI_SUCCESS Successfully initialized + +**/ +EFI_STATUS +EFIAPI +LegacyRegion2Install ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + VOID *Protocol; + + // + // Check for presence of gEfiLegacyRegionProtocolGuid + // and gEfiLegacyRegion2ProtocolGuid + // + Status = gBS->LocateProtocol (&gEfiLegacyRegionProtocolGuid, NULL, (VOID **) &Protocol); + if (Status == EFI_SUCCESS) { + return EFI_UNSUPPORTED; + } + + Status = gBS->LocateProtocol (&gEfiLegacyRegion2ProtocolGuid, NULL, (VOID **) &Protocol); + if (Status == EFI_SUCCESS) { + return EFI_UNSUPPORTED; + } + + Status = DetectChipset (); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Install the Legacy Region Protocol on a new handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mHandle, + &gEfiLegacyRegion2ProtocolGuid, + &mLegacyRegion2, + NULL + ); + + return Status; +} diff --git a/Legacy/BootPlatform/LegacyRegion2Dxe/LegacyRegion2.h b/Legacy/BootPlatform/LegacyRegion2Dxe/LegacyRegion2.h new file mode 100644 index 0000000000000000000000000000000000000000..fafe56d17e2f262dfa5aac151625917ba9b58712 --- /dev/null +++ b/Legacy/BootPlatform/LegacyRegion2Dxe/LegacyRegion2.h @@ -0,0 +1,251 @@ +/** @file + Legacy Region Support + + Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are + licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _LEGACY_REGION_DXE_H_ +#define _LEGACY_REGION_DXE_H_ + +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#define PAM_PCI_BUS 0 +#define PAM_PCI_DEV 0 +#define PAM_PCI_FUNC 0 + +#define REG_PAM0_OFFSET_NH 0x40 // Programmable Attribute Map 0 +#define REG_PAM1_OFFSET_NH 0x41 // Programmable Attribute Map 1 +#define REG_PAM2_OFFSET_NH 0x42 // Programmable Attribute Map 2 +#define REG_PAM3_OFFSET_NH 0x43 // Programmable Attribute Map 3 +#define REG_PAM4_OFFSET_NH 0x44 // Programmable Attribute Map 4 +#define REG_PAM5_OFFSET_NH 0x45 // Programmable Attribute Map 5 +#define REG_PAM6_OFFSET_NH 0x46 // Programmable Attribute Map 6 + + +#define REG_PAM0_OFFSET_830 0x59 // Programmable Attribute Map 0 +#define REG_PAM1_OFFSET_830 0x5a // Programmable Attribute Map 1 +#define REG_PAM2_OFFSET_830 0x5b // Programmable Attribute Map 2 +#define REG_PAM3_OFFSET_830 0x5c // Programmable Attribute Map 3 +#define REG_PAM4_OFFSET_830 0x5d // Programmable Attribute Map 4 +#define REG_PAM5_OFFSET_830 0x5e // Programmable Attribute Map 5 +#define REG_PAM6_OFFSET_830 0x5f // Programmable Attribute Map 6 + +#define REG_PAM0_OFFSET_S4 0x90 // Programmable Attribute Map 0 +#define REG_PAM1_OFFSET_S4 0x91 // Programmable Attribute Map 1 +#define REG_PAM2_OFFSET_S4 0x92 // Programmable Attribute Map 2 +#define REG_PAM3_OFFSET_S4 0x93 // Programmable Attribute Map 3 +#define REG_PAM4_OFFSET_S4 0x94 // Programmable Attribute Map 4 +#define REG_PAM5_OFFSET_S4 0x95 // Programmable Attribute Map 5 +#define REG_PAM6_OFFSET_S4 0x96 // Programmable Attribute Map 6 + +#define REG_PAM0_OFFSET_CP 0x80 // Programmable Attribute Map 0 +#define REG_PAM1_OFFSET_CP 0x81 // Programmable Attribute Map 1 +#define REG_PAM2_OFFSET_CP 0x82 // Programmable Attribute Map 2 +#define REG_PAM3_OFFSET_CP 0x83 // Programmable Attribute Map 3 +#define REG_PAM4_OFFSET_CP 0x84 // Programmable Attribute Map 4 +#define REG_PAM5_OFFSET_CP 0x85 // Programmable Attribute Map 5 +#define REG_PAM6_OFFSET_CP 0x86 // Programmable Attribute Map 6 + +#define REG_PAM0_OFFSET_NV 0xC0 // Programmable Attribute Map 0 +#define REG_PAM1_OFFSET_NV 0xC1 // Programmable Attribute Map 1 +#define REG_PAM2_OFFSET_NV 0xC2 // Programmable Attribute Map 2 +#define REG_PAM3_OFFSET_NV 0xC3 // Programmable Attribute Map 3 +#define REG_PAM4_OFFSET_NV 0xC4 // Programmable Attribute Map 4 +#define REG_PAM5_OFFSET_NV 0xC5 // Programmable Attribute Map 5 +#define REG_PAM6_OFFSET_NV 0xC6 // Programmable Attribute Map 6 + +#define PAM_BASE_ADDRESS 0xc0000 +#define PAM_LIMIT_ADDRESS BASE_1MB + +// +// Describes Legacy Region blocks and status. +// +typedef struct { + UINT32 Start; + UINT32 Length; + BOOLEAN ReadEnabled; + BOOLEAN WriteEnabled; +} LEGACY_MEMORY_SECTION_INFO; + +// +// Provides a map of the PAM registers and bits used to set Read/Write access. +// +typedef struct { + UINT8 PAMRegOffset; + UINT8 ReadEnableData; + UINT8 WriteEnableData; +} PAM_REGISTER_VALUE; + +/** + Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region. + + If the On parameter evaluates to TRUE, this function enables memory reads in the address range + Start to (Start + Length - 1). + If the On parameter evaluates to FALSE, this function disables memory reads in the address range + Start to (Start + Length - 1). + + @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance. + @param Start[in] The beginning of the physical address of the region whose attributes + should be modified. + @param Length[in] The number of bytes of memory whose attributes should be modified. + The actual number of bytes modified may be greater than the number + specified. + @param Granularity[out] The number of bytes in the last region affected. This may be less + than the total number of bytes affected if the starting address + was not aligned to a region's starting address or if the length + was greater than the number of bytes in the first region. + @param On[in] Decode / Non-Decode flag. + + @retval EFI_SUCCESS The region's attributes were successfully modified. + @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region. + +**/ +EFI_STATUS +EFIAPI +LegacyRegion2Decode ( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity, + IN BOOLEAN *On + ); + +/** + Modify the hardware to disallow memory writes in a region. + + This function changes the attributes of a memory range to not allow writes. + + @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance. + @param Start[in] The beginning of the physical address of the region whose + attributes should be modified. + @param Length[in] The number of bytes of memory whose attributes should be modified. + The actual number of bytes modified may be greater than the number + specified. + @param Granularity[out] The number of bytes in the last region affected. This may be less + than the total number of bytes affected if the starting address was + not aligned to a region's starting address or if the length was + greater than the number of bytes in the first region. + + @retval EFI_SUCCESS The region's attributes were successfully modified. + @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region. + +**/ +EFI_STATUS +EFIAPI +LegacyRegion2Lock ( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity + ); + +/** + Modify the hardware to disallow memory attribute changes in a region. + + This function makes the attributes of a region read only. Once a region is boot-locked with this + function, the read and write attributes of that region cannot be changed until a power cycle has + reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect. + + @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance. + @param Start[in] The beginning of the physical address of the region whose + attributes should be modified. + @param Length[in] The number of bytes of memory whose attributes should be modified. + The actual number of bytes modified may be greater than the number + specified. + @param Granularity[out] The number of bytes in the last region affected. This may be less + than the total number of bytes affected if the starting address was + not aligned to a region's starting address or if the length was + greater than the number of bytes in the first region. + + @retval EFI_SUCCESS The region's attributes were successfully modified. + @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region. + @retval EFI_UNSUPPORTED The chipset does not support locking the configuration registers in + a way that will not affect memory regions outside the legacy memory + region. + +**/ +EFI_STATUS +EFIAPI +LegacyRegion2BootLock ( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity + ); + +/** + Modify the hardware to allow memory writes in a region. + + This function changes the attributes of a memory range to allow writes. + + @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance. + @param Start[in] The beginning of the physical address of the region whose + attributes should be modified. + @param Length[in] The number of bytes of memory whose attributes should be modified. + The actual number of bytes modified may be greater than the number + specified. + @param Granularity[out] The number of bytes in the last region affected. This may be less + than the total number of bytes affected if the starting address was + not aligned to a region's starting address or if the length was + greater than the number of bytes in the first region. + + @retval EFI_SUCCESS The region's attributes were successfully modified. + @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region. + +**/ +EFI_STATUS +EFIAPI +LegacyRegion2Unlock ( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity + ); + +/** + Get region information for the attributes of the Legacy Region. + + This function is used to discover the granularity of the attributes for the memory in the legacy + region. Each attribute may have a different granularity and the granularity may not be the same + for all memory ranges in the legacy region. + + @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance. + @param DescriptorCount[out] The number of region descriptor entries returned in the Descriptor + buffer. + @param Descriptor[out] A pointer to a pointer used to return a buffer where the legacy + region information is deposited. This buffer will contain a list of + DescriptorCount number of region descriptors. This function will + provide the memory for the buffer. + + @retval EFI_SUCCESS The region's attributes were successfully modified. + @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region. + +**/ +EFI_STATUS +EFIAPI +LegacyRegionGetInfo ( + IN EFI_LEGACY_REGION2_PROTOCOL *This, + OUT UINT32 *DescriptorCount, + OUT EFI_LEGACY_REGION_DESCRIPTOR **Descriptor + ); + +#endif diff --git a/Legacy/BootPlatform/LegacyRegion2Dxe/LegacyRegion2Dxe.inf b/Legacy/BootPlatform/LegacyRegion2Dxe/LegacyRegion2Dxe.inf new file mode 100644 index 0000000000000000000000000000000000000000..5a8e8704afec274e67ec344e893249f349d9602a --- /dev/null +++ b/Legacy/BootPlatform/LegacyRegion2Dxe/LegacyRegion2Dxe.inf @@ -0,0 +1,61 @@ +## @file +# Produces the Legacy Region 2 Protocol. +# +# This generic implementation of the Legacy Region 2 Protocol does not actually +# perform any lock/unlock operations. This module may be used on platforms +# that do not provide HW locking of the legacy memory regions. It can also +# be used as a template driver for implementing the Legacy Region 2 Protocol on +# a platform that does support HW locking of the legacy memory regions. +# +# Note: This module does not fully comply with PI Specification of Legacy Region 2 +# Protocol. For Lock/UnLock/Decode, EFI_SUCCESS is returned although the region's +# attributes were not actually modified. +# +# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = LegacyRegion2Dxe + FILE_GUID = EC2BEECA-E84A-445B-869B-F7A73C96F58A + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = LegacyRegion2Install + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + LegacyRegion2.c + LegacyRegion2.h + +[Packages] + OpenCorePkg/OpenDuetPkg.dec + OpenCorePkg/OpenCorePkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DebugLib + MemoryAllocationLib + UefiBootServicesTableLib + PciLib + +[Protocols] + gEfiLegacyRegionProtocolGuid ## CHECKS + gEfiLegacyRegion2ProtocolGuid ## PRODUCES + +[Depex] + TRUE diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/ComponentName.c b/Legacy/BootPlatform/PciBusNoEnumerationDxe/ComponentName.c new file mode 100644 index 0000000000000000000000000000000000000000..ecec19b8b068f93082b0b6e8e99eca06cd94363b --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/ComponentName.c @@ -0,0 +1,161 @@ +/*++ + +Copyright (c) 2005 - 2007, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + ComponentName.c + +Abstract: + +--*/ + +#include "PciBus.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +PciBusComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +PciBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName = { + PciBusComponentNameGetDriverName, + PciBusComponentNameGetControllerName, + "eng" +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PciBusComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PciBusComponentNameGetControllerName, + "en" +}; + + +EFI_UNICODE_STRING_TABLE mPciBusDriverNameTable[] = { + { "eng;en", L"PCI Bus Driver" }, + { NULL, NULL } +}; + +EFI_STATUS +EFIAPI +PciBusComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + 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. + DriverName - 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. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mPciBusDriverNameTable, + DriverName, + (BOOLEAN)(This == &gPciBusComponentName) + ); +} + +EFI_STATUS +EFIAPI +PciBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers 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. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller 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. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciBus.c b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciBus.c new file mode 100644 index 0000000000000000000000000000000000000000..aa3316226927b1dbc005937525bd044ac80ab132 --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciBus.c @@ -0,0 +1,346 @@ +/*++ + +Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciBus.c + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#include "PciBus.h" + +// +// PCI Bus Support Function Prototypes +// + +EFI_STATUS +EFIAPI +PciBusEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STATUS +EFIAPI +PciBusDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +PciBusDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +PciBusDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + + +// +// PCI Bus Driver Global Variables +// + +EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding = { + PciBusDriverBindingSupported, + PciBusDriverBindingStart, + PciBusDriverBindingStop, + 0xa, + NULL, + NULL +}; + +BOOLEAN gFullEnumeration; + +UINT64 gAllOne = 0xFFFFFFFFFFFFFFFFULL; +UINT64 gAllZero = 0; + +// +// PCI Bus Driver Support Functions +// +EFI_STATUS +EFIAPI +PciBusEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Initialize the global variables + publish the driver binding protocol + +Arguments: + + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + +Returns: + + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +{ + EFI_STATUS Status; + + // + // Initialize the EFI Driver Library + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gPciBusDriverBinding, + ImageHandle, + &gPciBusComponentName, + &gPciBusComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + InitializePciDevicePool (); + + gFullEnumeration = TRUE; + + return Status; +} + +EFI_STATUS +EFIAPI +PciBusDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + Check to see if pci bus driver supports the given controller + +Arguments: + + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + EFI_DEV_PATH_PTR Node; + + if (RemainingDevicePath != NULL) { + Node.DevPath = RemainingDevicePath; + if (Node.DevPath->Type != HARDWARE_DEVICE_PATH || + Node.DevPath->SubType != HW_PCI_DP || + DevicePathNodeLength(Node.DevPath) != sizeof(PCI_DEVICE_PATH)) { + return EFI_UNSUPPORTED; + } + } + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **) &PciRootBridgeIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PciBusDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + Start to management the controller passed in + +Arguments: + + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + +Returns: + + +--*/ +{ + EFI_STATUS Status; + + // + // Enumerate the entire host bridge + // After enumeration, a database that records all the device information will be created + // + // + Status = PciEnumerator (Controller); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Enable PCI device specified by remaining device path. BDS or other driver can call the + // start more than once. + // + + StartPciDevices (Controller, RemainingDevicePath); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PciBusDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + Stop one or more children created at start of pci bus driver + if all the the children get closed, close the protocol + +Arguments: + + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + +Returns: + + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + BOOLEAN AllChildrenStopped; + + if (NumberOfChildren == 0) { + // + // Close the bus driver + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + DestroyRootBridgeByHandle ( + Controller + ); + + return EFI_SUCCESS; + } + + // + // Stop all the children + // + + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + + // + // De register all the pci device + // + Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]); + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciBus.h b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciBus.h new file mode 100644 index 0000000000000000000000000000000000000000..d707984a3dd624459069ad670fdcf6ee93d0458c --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciBus.h @@ -0,0 +1,200 @@ +/*++ + +Copyright (c) 2005 - 2007, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciBus.h + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_BUS_H +#define _EFI_PCI_BUS_H + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Driver Produced Protocol Prototypes +// + +#define VGABASE1 0x3B0 +#define VGALIMIT1 0x3BB + +#define VGABASE2 0x3C0 +#define VGALIMIT2 0x3DF + +#define ISABASE 0x100 +#define ISALIMIT 0x3FF + +typedef enum { + PciBarTypeUnknown = 0, + PciBarTypeIo16, + PciBarTypeIo32, + PciBarTypeMem32, + PciBarTypePMem32, + PciBarTypeMem64, + PciBarTypePMem64, + PciBarTypeIo, + PciBarTypeMem, + PciBarTypeMaxType +} PCI_BAR_TYPE; + +typedef struct { + UINT64 BaseAddress; + UINT64 Length; + UINT64 Alignment; + PCI_BAR_TYPE BarType; + BOOLEAN Prefetchable; + UINT8 MemType; + UINT8 Offset; +} PCI_BAR; + +#define PCI_IO_DEVICE_SIGNATURE SIGNATURE_32 ('p','c','i','o') + +#define EFI_BRIDGE_IO32_DECODE_SUPPORTED 0x0001 +#define EFI_BRIDGE_PMEM32_DECODE_SUPPORTED 0x0002 +#define EFI_BRIDGE_PMEM64_DECODE_SUPPORTED 0x0004 +#define EFI_BRIDGE_IO16_DECODE_SUPPORTED 0x0008 +#define EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED 0x0010 +#define EFI_BRIDGE_MEM64_DECODE_SUPPORTED 0x0020 +#define EFI_BRIDGE_MEM32_DECODE_SUPPORTED 0x0040 + + +typedef struct _PCI_IO_DEVICE { + UINT32 Signature; + EFI_HANDLE Handle; + EFI_PCI_IO_PROTOCOL PciIo; + LIST_ENTRY Link; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + // + // PCI configuration space header type + // + PCI_TYPE00 Pci; + + // + // Bus number, Device number, Function number + // + UINT8 BusNumber; + UINT8 DeviceNumber; + UINT8 FunctionNumber; + + // + // BAR for this PCI Device + // + PCI_BAR PciBar[PCI_MAX_BAR]; + + // + // The bridge device this pci device is subject to + // + struct _PCI_IO_DEVICE *Parent; + + // + // A linked list for children Pci Device if it is bridge device + // + LIST_ENTRY ChildList; + + // + // TRUE if the PCI bus driver creates the handle for this PCI device + // + BOOLEAN Registered; + + // + // TRUE if the PCI bus driver successfully allocates the resource required by + // this PCI device + // + BOOLEAN Allocated; + + // + // The attribute this PCI device currently set + // + UINT64 Attributes; + + // + // The attributes this PCI device actually supports + // + UINT64 Supports; + + // + // The resource decode the bridge supports + // + UINT32 Decodes; + + // + // A list tracking reserved resource on a bridge device + // + LIST_ENTRY ReservedResourceList; + + BOOLEAN IsPciExp; + +} PCI_IO_DEVICE; + + +#define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ + CR (a, PCI_IO_DEVICE, PciIo, PCI_IO_DEVICE_SIGNATURE) + +#define PCI_IO_DEVICE_FROM_LINK(a) \ + CR (a, PCI_IO_DEVICE, Link, PCI_IO_DEVICE_SIGNATURE) + +// +// Global Variables +// +extern EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2; +extern EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding; + +extern BOOLEAN gFullEnumeration; +extern UINT64 gAllOne; +extern UINT64 gAllZero; + +#include "PciIo.h" +#include "PciCommand.h" +#include "PciDeviceSupport.h" +#include "PciEnumerator.h" +#include "PciEnumeratorSupport.h" +#include "PciPowerManagement.h" + + +#define IS_ISA_BRIDGE(_p) IS_CLASS2 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA) +#define IS_INTEL_ISA_BRIDGE(_p) (IS_CLASS2 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE) && ((_p)->Hdr.VendorId == 0x8086) && ((_p)->Hdr.DeviceId == 0x7110)) +#define IS_PCI_GFX(_p) IS_CLASS2 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_OTHER) + +#endif diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf new file mode 100644 index 0000000000000000000000000000000000000000..6f790181d2999b3b2469479b607bdd8bfc1c2068 --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf @@ -0,0 +1,65 @@ +## @file +# +# Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Abstract: +# +## +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PciBusNoEnumerationDxe + FILE_GUID = 35C0C168-2607-4e51-BB53-448E3ED1A87F + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = PciBusEntryPoint + +[Packages] + MdePkg/MdePkg.dec + OpenCorePkg/OpenDuetPkg.dec + +[LibraryClasses] + DebugLib + BaseLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + BaseMemoryLib + ReportStatusCodeLib + DevicePathLib + PeCoffLib + +[Sources] + PciBus.h + PciIo.h + PciCommand.h + PciDeviceSupport.h + PciEnumerator.h + PciEnumeratorSupport.h + PciPowerManagement.h + PciPowerManagement.c + PciEnumerator.c + PciEnumeratorSupport.c + PciCommand.c + ComponentName.c + PciDeviceSupport.c + PciBus.c + PciIo.c + +[Protocols] + gEfiPciRootBridgeIoProtocolGuid + gEfiPciIoProtocolGuid + gEfiDevicePathProtocolGuid + gEfiDecompressProtocolGuid + +[Guids] + gEfiPciOptionRomTableGuid diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciCommand.c b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciCommand.c new file mode 100644 index 0000000000000000000000000000000000000000..6682830b0f3d74a05c648a87449c12ec552fa984 --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciCommand.c @@ -0,0 +1,453 @@ +/*++ + +Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciCommand.c + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#include "PciBus.h" + + +EFI_STATUS +PciReadCommandRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + OUT UINT16 *Command +) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + + EFI_PCI_IO_PROTOCOL *PciIo; + + *Command = 0; + PciIo = &PciIoDevice->PciIo; + + return PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + PCI_COMMAND_OFFSET, + 1, + Command + ); +} + +EFI_STATUS +PciSetCommandRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command +) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + UINT16 Temp; + EFI_PCI_IO_PROTOCOL *PciIo; + + Temp = Command; + PciIo = &PciIoDevice->PciIo; + + return PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + PCI_COMMAND_OFFSET, + 1, + &Temp + ); + +} + + +EFI_STATUS +PciEnableCommandRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command +) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + UINT16 OldCommand; + EFI_PCI_IO_PROTOCOL *PciIo; + + OldCommand = 0; + PciIo = &PciIoDevice->PciIo; + + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + PCI_COMMAND_OFFSET, + 1, + &OldCommand + ); + + OldCommand = (UINT16) (OldCommand | Command); + + return PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + PCI_COMMAND_OFFSET, + 1, + &OldCommand + ); + +} + + +EFI_STATUS +PciDisableCommandRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command +) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + UINT16 OldCommand; + EFI_PCI_IO_PROTOCOL *PciIo; + + OldCommand = 0; + PciIo = &PciIoDevice->PciIo; + + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + PCI_COMMAND_OFFSET, + 1, + &OldCommand + ); + + OldCommand = (UINT16) (OldCommand & ~(Command)); + + return PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + PCI_COMMAND_OFFSET, + 1, + &OldCommand + ); + +} + + + +EFI_STATUS +PciSetBridgeControlRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command +) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + UINT16 Temp; + EFI_PCI_IO_PROTOCOL *PciIo; + + Temp = Command; + PciIo = &PciIoDevice->PciIo; + + return PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + PCI_BRIDGE_CONTROL_REGISTER_OFFSET, + 1, + &Temp + ); + +} + + +EFI_STATUS +PciEnableBridgeControlRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command +) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + UINT16 OldCommand; + EFI_PCI_IO_PROTOCOL *PciIo; + + OldCommand = 0; + PciIo = &PciIoDevice->PciIo; + + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + PCI_BRIDGE_CONTROL_REGISTER_OFFSET, + 1, + &OldCommand + ); + + OldCommand = (UINT16) (OldCommand | Command); + + return PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + PCI_BRIDGE_CONTROL_REGISTER_OFFSET, + 1, + &OldCommand + ); + +} + +EFI_STATUS +PciDisableBridgeControlRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command +) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + UINT16 OldCommand; + EFI_PCI_IO_PROTOCOL *PciIo; + + OldCommand = 0; + PciIo = &PciIoDevice->PciIo; + + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + PCI_BRIDGE_CONTROL_REGISTER_OFFSET, + 1, + &OldCommand + ); + + OldCommand = (UINT16) (OldCommand & ~(Command)); + + return PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + PCI_BRIDGE_CONTROL_REGISTER_OFFSET, + 1, + &OldCommand + ); + +} + + + +EFI_STATUS +PciReadBridgeControlRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + OUT UINT16 *Command +) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + + EFI_PCI_IO_PROTOCOL *PciIo; + + *Command = 0; + PciIo = &PciIoDevice->PciIo; + + return PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + PCI_BRIDGE_CONTROL_REGISTER_OFFSET, + 1, + Command + ); + +} + +BOOLEAN +PciCapabilitySupport ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +{ + + if (PciIoDevice->Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) { + return TRUE; + } + + return FALSE; +} + +EFI_STATUS +LocateCapabilityRegBlock ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT8 CapId, + IN OUT UINT8 *Offset, + OUT UINT8 *NextRegBlock OPTIONAL + ) +/*++ + +Routine Description: + + Locate Capability register. + +Arguments: + + PciIoDevice - A pointer to the PCI_IO_DEVICE. + CapId - The capability ID. + Offset - A pointer to the offset. + As input: the default offset; + As output: the offset of the found block. + NextRegBlock - An optional pointer to return the value of next block. + +Returns: + + EFI_UNSUPPORTED - The Pci Io device is not supported. + EFI_NOT_FOUND - The Pci Io device cannot be found. + EFI_SUCCESS - The Pci Io device is successfully located. + +--*/ +{ + UINT8 CapabilityPtr; + UINT16 CapabilityEntry; + UINT8 CapabilityID; + + // + // To check the capability of this device supports + // + if (!PciCapabilitySupport (PciIoDevice)) { + return EFI_UNSUPPORTED; + } + + if (*Offset != 0) { + CapabilityPtr = *Offset; + } else { + + CapabilityPtr = 0; + if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { + + PciIoDevice->PciIo.Pci.Read ( + &PciIoDevice->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR, + 1, + &CapabilityPtr + ); + } else { + + PciIoDevice->PciIo.Pci.Read ( + &PciIoDevice->PciIo, + EfiPciIoWidthUint8, + PCI_CAPBILITY_POINTER_OFFSET, + 1, + &CapabilityPtr + ); + } + } + + while ((CapabilityPtr >= 0x40) && ((CapabilityPtr & 0x03) == 0x00)) { + PciIoDevice->PciIo.Pci.Read ( + &PciIoDevice->PciIo, + EfiPciIoWidthUint16, + CapabilityPtr, + 1, + &CapabilityEntry + ); + + CapabilityID = (UINT8) CapabilityEntry; + + if (CapabilityID == CapId) { + *Offset = CapabilityPtr; + if (NextRegBlock != NULL) { + *NextRegBlock = (UINT8) (CapabilityEntry >> 8); + } + + return EFI_SUCCESS; + } + + CapabilityPtr = (UINT8) (CapabilityEntry >> 8); + } + + return EFI_NOT_FOUND; +} diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciCommand.h b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciCommand.h new file mode 100644 index 0000000000000000000000000000000000000000..da67b7844c55da9be971c5d18b56037e28832d3a --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciCommand.h @@ -0,0 +1,167 @@ +/*++ + +Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciCommand.h + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_COMMAND_H +#define _EFI_PCI_COMMAND_H + +#include "PciBus.h" + +// +// The PCI Command register bits owned by PCI Bus driver. +// +// They should be cleared at the beginning. The other registers +// are owned by chipset, we should not touch them. +// +#define EFI_PCI_COMMAND_BITS_OWNED ( \ + EFI_PCI_COMMAND_IO_SPACE | \ + EFI_PCI_COMMAND_MEMORY_SPACE | \ + EFI_PCI_COMMAND_BUS_MASTER | \ + EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE | \ + EFI_PCI_COMMAND_VGA_PALETTE_SNOOP | \ + EFI_PCI_COMMAND_FAST_BACK_TO_BACK \ + ) + +// +// The PCI Bridge Control register bits owned by PCI Bus driver. +// +// They should be cleared at the beginning. The other registers +// are owned by chipset, we should not touch them. +// +#define EFI_PCI_BRIDGE_CONTROL_BITS_OWNED ( \ + EFI_PCI_BRIDGE_CONTROL_ISA | \ + EFI_PCI_BRIDGE_CONTROL_VGA | \ + EFI_PCI_BRIDGE_CONTROL_VGA_16 | \ + EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK \ + ) + +// +// The PCCard Bridge Control register bits owned by PCI Bus driver. +// +// They should be cleared at the beginning. The other registers +// are owned by chipset, we should not touch them. +// +#define EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED ( \ + EFI_PCI_BRIDGE_CONTROL_ISA | \ + EFI_PCI_BRIDGE_CONTROL_VGA | \ + EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK \ + ) + +EFI_STATUS +PciReadCommandRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + OUT UINT16 *Command +); + + +EFI_STATUS +PciSetCommandRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command +); + +EFI_STATUS +PciEnableCommandRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command +); + +EFI_STATUS +PciDisableCommandRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command +); + +EFI_STATUS +PciDisableBridgeControlRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command +); + + +EFI_STATUS +PciEnableBridgeControlRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command +); + +EFI_STATUS +PciReadBridgeControlRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + OUT UINT16 *Command +); + +BOOLEAN +PciCapabilitySupport ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +LocateCapabilityRegBlock ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT8 CapId, + IN OUT UINT8 *Offset, + OUT UINT8 *NextRegBlock OPTIONAL + ) +/*++ + +Routine Description: + + Locate Capability register. + +Arguments: + + PciIoDevice - A pointer to the PCI_IO_DEVICE. + CapId - The capability ID. + Offset - A pointer to the offset. + As input: the default offset; + As output: the offset of the found block. + NextRegBlock - An optional pointer to return the value of next block. + +Returns: + + EFI_UNSUPPORTED - The Pci Io device is not supported. + EFI_NOT_FOUND - The Pci Io device cannot be found. + EFI_SUCCESS - The Pci Io device is successfully located. + +--*/ +; + + +#endif + diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciDeviceSupport.c b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciDeviceSupport.c new file mode 100644 index 0000000000000000000000000000000000000000..7ae1eaf54dc41c6b6fc90156a9853f6d44e8d6b4 --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciDeviceSupport.c @@ -0,0 +1,946 @@ +/*++ + +Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciDeviceSupport.c + +Abstract: + + This file provides routine to support Pci device node manipulation + +Revision History + +--*/ + +#include "PciBus.h" + +// +// This device structure is serviced as a header. +// Its Next field points to the first root bridge device node +// +LIST_ENTRY gPciDevicePool; + +EFI_STATUS +InitializePciDevicePool ( + VOID + ) +/*++ + +Routine Description: + + Initialize the gPciDevicePool + +Arguments: + +Returns: + + None + +--*/ +{ + InitializeListHead (&gPciDevicePool); + + return EFI_SUCCESS; +} + +EFI_STATUS +InsertRootBridge ( + IN PCI_IO_DEVICE *RootBridge + ) +/*++ + +Routine Description: + + Insert a root bridge into PCI device pool + +Arguments: + + RootBridge - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +{ + InsertTailList (&gPciDevicePool, &(RootBridge->Link)); + + return EFI_SUCCESS; +} + +EFI_STATUS +InsertPciDevice ( + PCI_IO_DEVICE *Bridge, + PCI_IO_DEVICE *PciDeviceNode + ) +/*++ + +Routine Description: + + This function is used to insert a PCI device node under + a bridge + +Arguments: + Bridge - A pointer to the PCI_IO_DEVICE. + PciDeviceNode - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ + +{ + + InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link)); + PciDeviceNode->Parent = Bridge; + + return EFI_SUCCESS; +} + +EFI_STATUS +DestroyRootBridge ( + IN PCI_IO_DEVICE *RootBridge + ) +/*++ + +Routine Description: + + +Arguments: + + RootBridge - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +{ + DestroyPciDeviceTree (RootBridge); + + gBS->FreePool (RootBridge); + + return EFI_SUCCESS; +} + +EFI_STATUS +DestroyPciDeviceTree ( + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + Destroy all the pci device node under the bridge. + Bridge itself is not included. + +Arguments: + + Bridge - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +{ + LIST_ENTRY *CurrentLink; + PCI_IO_DEVICE *Temp; + + while (!IsListEmpty (&Bridge->ChildList)) { + + CurrentLink = Bridge->ChildList.ForwardLink; + + // + // Remove this node from the linked list + // + RemoveEntryList (CurrentLink); + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + if (IS_PCI_BRIDGE (&(Temp->Pci))) { + DestroyPciDeviceTree (Temp); + } + gBS->FreePool (Temp); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +DestroyRootBridgeByHandle ( + EFI_HANDLE Controller + ) +/*++ + +Routine Description: + + Destroy all device nodes under the root bridge + specified by Controller. + The root bridge itself is also included. + +Arguments: + + Controller - An efi handle. + +Returns: + + None + +--*/ +{ + + LIST_ENTRY *CurrentLink; + PCI_IO_DEVICE *Temp; + + CurrentLink = gPciDevicePool.ForwardLink; + + while (CurrentLink && CurrentLink != &gPciDevicePool) { + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + if (Temp->Handle == Controller) { + + RemoveEntryList (CurrentLink); + + DestroyPciDeviceTree (Temp); + + gBS->FreePool(Temp); + + return EFI_SUCCESS; + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +RegisterPciDevice ( + IN EFI_HANDLE Controller, + IN PCI_IO_DEVICE *PciIoDevice, + OUT EFI_HANDLE *Handle OPTIONAL + ) +/*++ + +Routine Description: + + This function registers the PCI IO device. It creates a handle for this PCI IO device + (if the handle does not exist), attaches appropriate protocols onto the handle, does + necessary initialization, and sets up parent/child relationship with its bus controller. + +Arguments: + + Controller - An EFI handle for the PCI bus controller. + PciIoDevice - A PCI_IO_DEVICE pointer to the PCI IO device to be registered. + Handle - A pointer to hold the EFI handle for the PCI IO device. + +Returns: + + EFI_SUCCESS - The PCI device is successfully registered. + Others - An error occurred when registering the PCI device. + +--*/ +{ + EFI_STATUS Status; + UINT8 PciExpressCapRegOffset; + + // + // Install the pciio protocol, device path protocol + // + + Status = gBS->InstallMultipleProtocolInterfaces ( + &PciIoDevice->Handle, + &gEfiDevicePathProtocolGuid, + PciIoDevice->DevicePath, + &gEfiPciIoProtocolGuid, + &PciIoDevice->PciIo, + NULL + ); + + if (EFI_ERROR (Status)) { + return Status; + } else { + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **)&(PciIoDevice->PciRootBridgeIo), + gPciBusDriverBinding.DriverBindingHandle, + PciIoDevice->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + if (Handle != NULL) { + *Handle = PciIoDevice->Handle; + } + + // + // Detect if PCI Express Device + // + PciExpressCapRegOffset = 0; + Status = LocateCapabilityRegBlock ( + PciIoDevice, + EFI_PCI_CAPABILITY_ID_PCIEXP, + &PciExpressCapRegOffset, + NULL + ); + if (!EFI_ERROR (Status)) { + PciIoDevice->IsPciExp = TRUE; + DEBUG ((EFI_D_ERROR, "PciExp - %x (B-%x, D-%x, F-%x)\n", PciIoDevice->IsPciExp, PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber)); + } + + // + // Indicate the pci device is registered + // + PciIoDevice->Registered = TRUE; + + return EFI_SUCCESS; +} + + +EFI_STATUS +DeRegisterPciDevice ( + IN EFI_HANDLE Controller, + IN EFI_HANDLE Handle + ) +/*++ + +Routine Description: + + This function is used to de-register the PCI device from the EFI, + That includes un-installing PciIo protocol from the specified PCI + device handle. + +Arguments: + + Controller - An efi handle. + Handle - An efi handle. + +Returns: + + None + +--*/ +{ + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + PCI_IO_DEVICE *Node; + LIST_ENTRY *CurrentLink; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + Status = gBS->OpenProtocol ( + Handle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + gPciBusDriverBinding.DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo); + + // + // If it is already de-registered + // + if (!PciIoDevice->Registered) { + return EFI_SUCCESS; + } + + // + // If it is PPB, first de-register its children + // + + if (IS_PCI_BRIDGE (&(PciIoDevice->Pci))) { + + CurrentLink = PciIoDevice->ChildList.ForwardLink; + + while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) { + Node = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + Status = DeRegisterPciDevice (Controller, Node->Handle); + + if (EFI_ERROR (Status)) { + return Status; + } + + CurrentLink = CurrentLink->ForwardLink; + } + } + + // + // First disconnect this device + // +// PciIoDevice->PciIo.Attributes(&(PciIoDevice->PciIo), +// EfiPciIoAttributeOperationDisable, +// EFI_PCI_DEVICE_ENABLE, +// NULL +// ); + + // + // Close the child handle + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + gPciBusDriverBinding.DriverBindingHandle, + Handle + ); + + // + // Un-install the device path protocol and pci io protocol + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + Handle, + &gEfiDevicePathProtocolGuid, + PciIoDevice->DevicePath, + &gEfiPciIoProtocolGuid, + &PciIoDevice->PciIo, + NULL + ); + + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **) &PciRootBridgeIo, + gPciBusDriverBinding.DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + return Status; + } + + // + // The Device Driver should disable this device after disconnect + // so the Pci Bus driver will not touch this device any more. + // Restore the register field to the original value + // + PciIoDevice->Registered = FALSE; + PciIoDevice->Handle = NULL; + } else { + + // + // Handle may be closed before + // + return EFI_SUCCESS; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EnableBridgeAttributes ( + IN PCI_IO_DEVICE *PciIoDevice + ) +{ + PCI_TYPE01 PciData; + + // + // NOTE: We should not set EFI_PCI_DEVICE_ENABLE for a bridge + // directly, because some legacy BIOS will NOT assign + // IO or Memory resource for a bridge who has no child + // device. So we add check IO or Memory here. + // + + PciIoDevice->PciIo.Pci.Read ( + &PciIoDevice->PciIo, + EfiPciIoWidthUint8, + 0, + sizeof (PciData), + &PciData + ); + + if ((((PciData.Bridge.IoBase & 0xF) == 0) && + (PciData.Bridge.IoBase != 0 || PciData.Bridge.IoLimit != 0)) || + (((PciData.Bridge.IoBase & 0xF) == 1) && + ((PciData.Bridge.IoBase & 0xF0) != 0 || (PciData.Bridge.IoLimit & 0xF0) != 0 || PciData.Bridge.IoBaseUpper16 != 0 || PciData.Bridge.IoLimitUpper16 != 0))) { + PciIoDevice->PciIo.Attributes( + &(PciIoDevice->PciIo), + EfiPciIoAttributeOperationEnable, + (EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER), + NULL + ); + } + if ((PciData.Bridge.MemoryBase & 0xFFF0) != 0 || (PciData.Bridge.MemoryLimit & 0xFFF0) != 0) { + PciIoDevice->PciIo.Attributes( + &(PciIoDevice->PciIo), + EfiPciIoAttributeOperationEnable, + (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER), + NULL + ); + } + if ((((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 0) && + (PciData.Bridge.PrefetchableMemoryBase != 0 || PciData.Bridge.PrefetchableMemoryLimit != 0)) || + (((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 1) && + ((PciData.Bridge.PrefetchableMemoryBase & 0xFFF0) != 0 || (PciData.Bridge.PrefetchableMemoryLimit & 0xFFF0) != 0 || PciData.Bridge.PrefetchableBaseUpper32 != 0 || PciData.Bridge.PrefetchableLimitUpper32 != 0))) { + PciIoDevice->PciIo.Attributes( + &(PciIoDevice->PciIo), + EfiPciIoAttributeOperationEnable, + (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER), + NULL + ); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +StartPciDevicesOnBridge ( + IN EFI_HANDLE Controller, + IN PCI_IO_DEVICE *RootBridge, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge + +Arguments: + + Controller - An efi handle. + RootBridge - A pointer to the PCI_IO_DEVICE. + RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL. + NumberOfChildren - Children number. + ChildHandleBuffer - A pointer to the child handle buffer. + +Returns: + + None + +--*/ +{ + PCI_IO_DEVICE *Temp; + PCI_IO_DEVICE *PciIoDevice; + EFI_DEV_PATH_PTR Node; + EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath; + EFI_STATUS Status; + LIST_ENTRY *CurrentLink; + + CurrentLink = RootBridge->ChildList.ForwardLink; + + while (CurrentLink && CurrentLink != &RootBridge->ChildList) { + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + if (RemainingDevicePath != NULL) { + + Node.DevPath = RemainingDevicePath; + + if (Node.Pci->Device != Temp->DeviceNumber || + Node.Pci->Function != Temp->FunctionNumber) { + CurrentLink = CurrentLink->ForwardLink; + continue; + } + + // + // Check if the device has been assigned with required resource + // + if (!Temp->Allocated) { + return EFI_NOT_READY; + } + + // + // Check if the current node has been registered before + // If it is not, register it + // + if (!Temp->Registered) { + PciIoDevice = Temp; + + Status = RegisterPciDevice ( + Controller, + PciIoDevice, + NULL + ); + + } + + // + // Get the next device path + // + CurrentDevicePath = NextDevicePathNode (RemainingDevicePath); + if (IsDevicePathEnd (CurrentDevicePath)) { + return EFI_SUCCESS; + } + + // + // If it is a PPB + // + if (IS_PCI_BRIDGE (&(Temp->Pci))) { + Status = StartPciDevicesOnBridge ( + Controller, + Temp, + CurrentDevicePath + ); + EnableBridgeAttributes (Temp); + + return Status; + } else { + + // + // Currently, the PCI bus driver only support PCI-PCI bridge + // + return EFI_UNSUPPORTED; + } + + } else { + + // + // If remaining device path is NULL, + // try to enable all the pci devices under this bridge + // + + if (!Temp->Registered && Temp->Allocated) { + + PciIoDevice = Temp; + + Status = RegisterPciDevice ( + Controller, + PciIoDevice, + NULL + ); + + } + + if (IS_PCI_BRIDGE (&(Temp->Pci))) { + Status = StartPciDevicesOnBridge ( + Controller, + Temp, + RemainingDevicePath + ); + EnableBridgeAttributes (Temp); + } + + CurrentLink = CurrentLink->ForwardLink; + continue; + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +StartPciDevices ( + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + Start to manage the PCI device according to RemainingDevicePath + If RemainingDevicePath == NULL, the PCI bus driver will start + to manage all the PCI devices it found previously + +Arguments: + Controller - An efi handle. + RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL. + +Returns: + + None + +--*/ +{ + EFI_DEV_PATH_PTR Node; + PCI_IO_DEVICE *RootBridge; + LIST_ENTRY *CurrentLink; + + if (RemainingDevicePath != NULL) { + + // + // Check if the RemainingDevicePath is valid + // + Node.DevPath = RemainingDevicePath; + if (Node.DevPath->Type != HARDWARE_DEVICE_PATH || + Node.DevPath->SubType != HW_PCI_DP || + DevicePathNodeLength (Node.DevPath) != sizeof (PCI_DEVICE_PATH) + ) { + return EFI_UNSUPPORTED; + } + } + + CurrentLink = gPciDevicePool.ForwardLink; + + while (CurrentLink && CurrentLink != &gPciDevicePool) { + + RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + // + // Locate the right root bridge to start + // + if (RootBridge->Handle == Controller) { + StartPciDevicesOnBridge ( + Controller, + RootBridge, + RemainingDevicePath + ); + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return EFI_SUCCESS; +} + +PCI_IO_DEVICE * +CreateRootBridge ( + IN EFI_HANDLE RootBridgeHandle + ) +/*++ + +Routine Description: + + +Arguments: + RootBridgeHandle - An efi handle. + +Returns: + + None + +--*/ +{ + + EFI_STATUS Status; + PCI_IO_DEVICE *Dev; + + Dev = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (PCI_IO_DEVICE), + (VOID **) &Dev + ); + + if (EFI_ERROR (Status)) { + return NULL; + } + + ZeroMem (Dev, sizeof (PCI_IO_DEVICE)); + Dev->Signature = PCI_IO_DEVICE_SIGNATURE; + Dev->Handle = RootBridgeHandle; + InitializeListHead (&Dev->ChildList); + + return Dev; +} + +PCI_IO_DEVICE * +GetRootBridgeByHandle ( + EFI_HANDLE RootBridgeHandle + ) +/*++ + +Routine Description: + + +Arguments: + + RootBridgeHandle - An efi handle. + +Returns: + + None + +--*/ +{ + PCI_IO_DEVICE *RootBridgeDev; + LIST_ENTRY *CurrentLink; + + CurrentLink = gPciDevicePool.ForwardLink; + + while (CurrentLink && CurrentLink != &gPciDevicePool) { + + RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + if (RootBridgeDev->Handle == RootBridgeHandle) { + return RootBridgeDev; + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return NULL; +} + +BOOLEAN +RootBridgeExisted ( + IN EFI_HANDLE RootBridgeHandle + ) +/*++ + +Routine Description: + + This function searches if RootBridgeHandle has already existed + in current device pool. + + If so, it means the given root bridge has been already enumerated. + +Arguments: + + RootBridgeHandle - An efi handle. + +Returns: + + None + +--*/ +{ + PCI_IO_DEVICE *Bridge; + + Bridge = GetRootBridgeByHandle (RootBridgeHandle); + + if (Bridge != NULL) { + return TRUE; + } + + return FALSE; +} + +BOOLEAN +PciDeviceExisted ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + + Bridge - A pointer to the PCI_IO_DEVICE. + PciIoDevice - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +{ + + PCI_IO_DEVICE *Temp; + LIST_ENTRY *CurrentLink; + + CurrentLink = Bridge->ChildList.ForwardLink; + + while (CurrentLink && CurrentLink != &Bridge->ChildList) { + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + if (Temp == PciIoDevice) { + return TRUE; + } + + if (!IsListEmpty (&Temp->ChildList)) { + if (PciDeviceExisted (Temp, PciIoDevice)) { + return TRUE; + } + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return FALSE; +} + +PCI_IO_DEVICE * +ActiveVGADeviceOnTheSameSegment ( + IN PCI_IO_DEVICE *VgaDevice + ) +/*++ + +Routine Description: + +Arguments: + + VgaDevice - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +{ + LIST_ENTRY *CurrentLink; + PCI_IO_DEVICE *Temp; + + CurrentLink = gPciDevicePool.ForwardLink; + + while (CurrentLink && CurrentLink != &gPciDevicePool) { + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) { + + Temp = ActiveVGADeviceOnTheRootBridge (Temp); + + if (Temp != NULL) { + return Temp; + } + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return NULL; +} + +PCI_IO_DEVICE * +ActiveVGADeviceOnTheRootBridge ( + IN PCI_IO_DEVICE *RootBridge + ) +/*++ + +Routine Description: + +Arguments: + + RootBridge - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +{ + LIST_ENTRY *CurrentLink; + PCI_IO_DEVICE *Temp; + + CurrentLink = RootBridge->ChildList.ForwardLink; + + while (CurrentLink && CurrentLink != &RootBridge->ChildList) { + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + if (IS_PCI_VGA(&Temp->Pci) && + (Temp->Attributes & + (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | + EFI_PCI_IO_ATTRIBUTE_VGA_IO | + EFI_PCI_IO_ATTRIBUTE_VGA_IO_16))) { + return Temp; + } + + if (IS_PCI_BRIDGE (&Temp->Pci)) { + + Temp = ActiveVGADeviceOnTheRootBridge (Temp); + + if (Temp != NULL) { + return Temp; + } + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return NULL; +} diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciDeviceSupport.h b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciDeviceSupport.h new file mode 100644 index 0000000000000000000000000000000000000000..07fd54bcedfeff4217ebb1a8d6a2b3d274551049 --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciDeviceSupport.h @@ -0,0 +1,324 @@ +/*++ + +Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciDeviceSupport.h + +Abstract: + + + +Revision History + +--*/ + +#ifndef _EFI_PCI_DEVICE_SUPPORT_H +#define _EFI_PCI_DEVICE_SUPPORT_H + +EFI_STATUS +InitializePciDevicePool ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + None + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +InsertPciDevice ( + PCI_IO_DEVICE *Bridge, + PCI_IO_DEVICE *PciDeviceNode + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + PciDeviceNode - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DestroyPciDeviceTree ( + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DestroyRootBridgeByHandle ( + EFI_HANDLE Controller + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Controller - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +RegisterPciDevice ( + IN EFI_HANDLE Controller, + IN PCI_IO_DEVICE *PciIoDevice, + OUT EFI_HANDLE *Handle OPTIONAL + ) +/*++ + +Routine Description: + + This function registers the PCI IO device. It creates a handle for this PCI IO device + (if the handle does not exist), attaches appropriate protocols onto the handle, does + necessary initialization, and sets up parent/child relationship with its bus controller. + +Arguments: + + Controller - An EFI handle for the PCI bus controller. + PciIoDevice - A PCI_IO_DEVICE pointer to the PCI IO device to be registered. + Handle - A pointer to hold the EFI handle for the PCI IO device. + +Returns: + + EFI_SUCCESS - The PCI device is successfully registered. + Others - An error occurred when registering the PCI device. + +--*/ +; + +EFI_STATUS +DeRegisterPciDevice ( + IN EFI_HANDLE Controller, + IN EFI_HANDLE Handle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Controller - TODO: add argument description + Handle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +StartPciDevices ( + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Controller - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_IO_DEVICE * +CreateRootBridge ( + IN EFI_HANDLE RootBridgeHandle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridgeHandle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_IO_DEVICE * +GetRootBridgeByHandle ( + EFI_HANDLE RootBridgeHandle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridgeHandle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +InsertRootBridge ( + PCI_IO_DEVICE *RootBridge +); + +EFI_STATUS +DestroyRootBridge ( + IN PCI_IO_DEVICE *RootBridge +); + +BOOLEAN +RootBridgeExisted ( + IN EFI_HANDLE RootBridgeHandle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridgeHandle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +PciDeviceExisted ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_IO_DEVICE * +ActiveVGADeviceOnTheSameSegment ( + IN PCI_IO_DEVICE *VgaDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + VgaDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_IO_DEVICE * +ActiveVGADeviceOnTheRootBridge ( + IN PCI_IO_DEVICE *RootBridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; +#endif diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciEnumerator.c b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciEnumerator.c new file mode 100644 index 0000000000000000000000000000000000000000..729c567c408af207f181578d9cdb843ef45f300a --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciEnumerator.c @@ -0,0 +1,57 @@ +/*++ + +Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciEnumerator.c + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#include "PciBus.h" + +EFI_STATUS +PciEnumerator ( + IN EFI_HANDLE Controller + ) +/*++ + +Routine Description: + + This routine is used to enumerate entire pci bus system + in a given platform + +Arguments: + +Returns: + + None + +--*/ +{ + // + // This PCI bus driver depends on the legacy BIOS + // to do the resource allocation + // + gFullEnumeration = FALSE; + + return PciEnumeratorLight (Controller) ; + +} + + + + diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciEnumerator.h b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciEnumerator.h new file mode 100644 index 0000000000000000000000000000000000000000..09c9d6961238403fdcb2c970e29572b179c32d50 --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciEnumerator.h @@ -0,0 +1,47 @@ +/*++ + +Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciEnumerator.h + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_ENUMERATOR_H +#define _EFI_PCI_ENUMERATOR_H + +EFI_STATUS +PciEnumerator ( + IN EFI_HANDLE Controller + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Controller - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; +#endif diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciEnumeratorSupport.c b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciEnumeratorSupport.c new file mode 100644 index 0000000000000000000000000000000000000000..eceecfadd351c1805f9353fe17edd125597fe8e4 --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciEnumeratorSupport.c @@ -0,0 +1,1364 @@ +/*++ + +Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciEnumeratorSupport.c + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#include "PciBus.h" + +EFI_STATUS +InitializePPB ( + IN PCI_IO_DEVICE *PciIoDevice +); + +EFI_STATUS +InitializeP2C ( + IN PCI_IO_DEVICE *PciIoDevice +); + +PCI_IO_DEVICE* +CreatePciIoDevice ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func +); + + +PCI_IO_DEVICE* +GatherP2CInfo ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func +); + +UINTN +PciParseBar ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINTN Offset, + IN UINTN BarIndex +); + + +EFI_STATUS +PciSearchDevice ( + IN PCI_IO_DEVICE *Bridge, + PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func, + PCI_IO_DEVICE **PciDevice +); + + +EFI_STATUS +DetermineDeviceAttribute ( + IN PCI_IO_DEVICE *PciIoDevice +); + +EFI_STATUS +BarExisted ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINTN Offset, + OUT UINT32 *BarLengthValue, + OUT UINT32 *OriginalBarValue + ); + + + +EFI_DEVICE_PATH_PROTOCOL* +CreatePciDevicePath( + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN PCI_IO_DEVICE *PciIoDevice +); + +PCI_IO_DEVICE* +GatherDeviceInfo ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func +); + +PCI_IO_DEVICE* +GatherPPBInfo ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func +); + +EFI_STATUS +PciDevicePresent ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + + This routine is used to check whether the pci device is present + +Arguments: + +Returns: + + None + +--*/ +{ + UINT64 Address; + EFI_STATUS Status; + + // + // Create PCI address map in terms of Bus, Device and Func + // + Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0); + + // + // Read the Vendor Id register + // + Status = PciRootBridgeIo->Pci.Read ( + PciRootBridgeIo, + EfiPciWidthUint32, + Address, + 1, + Pci + ); + + if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) { + + // + // Read the entire config header for the device + // + + PciRootBridgeIo->Pci.Read ( + PciRootBridgeIo, + EfiPciWidthUint32, + Address, + sizeof (PCI_TYPE00) / sizeof (UINT32), + Pci + ); + + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +PciPciDeviceInfoCollector ( + IN PCI_IO_DEVICE *Bridge, + UINT8 StartBusNumber + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_TYPE00 Pci; + UINT8 Device; + UINT8 Func; + UINT8 SecBus; + PCI_IO_DEVICE *PciIoDevice; + EFI_PCI_IO_PROTOCOL *PciIo; + + Status = EFI_SUCCESS; + SecBus = 0; + PciIoDevice = NULL; + + for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) { + + for (Func = 0; Func <= PCI_MAX_FUNC; Func++) { + + // + // Check to see whether PCI device is present + // + + Status = PciDevicePresent ( + Bridge->PciRootBridgeIo, + &Pci, + (UINT8) StartBusNumber, + (UINT8) Device, + (UINT8) Func + ); + + if (EFI_ERROR (Status) && Func == 0) { + // + // go to next device if there is no Function 0 + // + break; + } + + if (!EFI_ERROR (Status)) { + + // + // Collect all the information about the PCI device discovered + // + Status = PciSearchDevice ( + Bridge, + &Pci, + (UINT8) StartBusNumber, + Device, + Func, + &PciIoDevice + ); + + // + // Recursively scan PCI busses on the other side of PCI-PCI bridges + // + // + + if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) { + + // + // If it is PPB, we need to get the secondary bus to continue the enumeration + // + PciIo = &(PciIoDevice->PciIo); + + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // If the PCI bridge is initialized then enumerate the next level bus + // + if (SecBus != 0) { + Status = PciPciDeviceInfoCollector ( + PciIoDevice, + (UINT8) (SecBus) + ); + } + } + + if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) { + + // + // Skip sub functions, this is not a multi function device + // + Func = PCI_MAX_FUNC; + } + } + + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciSearchDevice ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_TYPE00 *Pci, + IN UINT8 Bus, + IN UINT8 Device, + IN UINT8 Func, + OUT PCI_IO_DEVICE **PciDevice + ) +/*++ + +Routine Description: + + Search required device. + +Arguments: + + Bridge - A pointer to the PCI_IO_DEVICE. + Pci - A pointer to the PCI_TYPE00. + Bus - Bus number. + Device - Device number. + Func - Function number. + PciDevice - The Required pci device. + +Returns: + + Status code. + +--*/ +{ + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = NULL; + + if (!IS_PCI_BRIDGE (Pci)) { + + if (IS_CARDBUS_BRIDGE (Pci)) { + PciIoDevice = GatherP2CInfo ( + Bridge->PciRootBridgeIo, + Pci, + Bus, + Device, + Func + ); + if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) { + InitializeP2C (PciIoDevice); + } + } else { + + // + // Create private data for Pci Device + // + PciIoDevice = GatherDeviceInfo ( + Bridge->PciRootBridgeIo, + Pci, + Bus, + Device, + Func + ); + + } + + } else { + + // + // Create private data for PPB + // + PciIoDevice = GatherPPBInfo ( + Bridge->PciRootBridgeIo, + Pci, + Bus, + Device, + Func + ); + + // + // Special initialization for PPB including making the PPB quiet + // + if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) { + InitializePPB (PciIoDevice); + } + } + + if (!PciIoDevice) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Create a device path for this PCI device and store it into its private data + // + CreatePciDevicePath( + Bridge->DevicePath, + PciIoDevice + ); + + // + // ** CHANGE ** + // PCI Option ROM support removed (continuation of patch by nms42). + // + if (gFullEnumeration) { + ResetPowerManagementFeature (PciIoDevice); + } + + + // + // Insert it into a global tree for future reference + // + InsertPciDevice (Bridge, PciIoDevice); + + // + // Determine PCI device attributes + // + DetermineDeviceAttribute (PciIoDevice); + + if (PciDevice != NULL) { + *PciDevice = PciIoDevice; + } + + return EFI_SUCCESS; +} + +PCI_IO_DEVICE * +GatherDeviceInfo ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + UINTN Offset; + UINTN BarIndex; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = CreatePciIoDevice ( + PciRootBridgeIo, + Pci, + Bus, + Device, + Func + ); + + if (!PciIoDevice) { + return NULL; + } + + // + // If it is a full enumeration, disconnect the device in advance + // + if (gFullEnumeration) { + + PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED); + + } + + // + // Start to parse the bars + // + for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) { + Offset = PciParseBar (PciIoDevice, Offset, BarIndex); + } + + return PciIoDevice; +} + +PCI_IO_DEVICE * +GatherPPBInfo ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + PCI_IO_DEVICE *PciIoDevice; + EFI_STATUS Status; + UINT8 Value; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Temp; + + PciIoDevice = CreatePciIoDevice ( + PciRootBridgeIo, + Pci, + Bus, + Device, + Func + ); + + if (!PciIoDevice) { + return NULL; + } + + if (gFullEnumeration) { + PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED); + + // + // Initalize the bridge control register + // + PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED); + } + + PciIo = &PciIoDevice->PciIo; + + // + // Test whether it support 32 decode or not + // + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne); + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp); + + if (Value) { + if (Value & 0x01) { + PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED; + } else { + PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED; + } + } + + Status = BarExisted ( + PciIoDevice, + 0x24, + NULL, + NULL + ); + + // + // test if it supports 64 memory or not + // + if (!EFI_ERROR (Status)) { + + Status = BarExisted ( + PciIoDevice, + 0x28, + NULL, + NULL + ); + + if (!EFI_ERROR (Status)) { + PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED; + PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED; + } else { + PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED; + } + } + + // + // Memory 32 code is required for ppb + // + PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED; + + return PciIoDevice; +} + +PCI_IO_DEVICE * +GatherP2CInfo ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = CreatePciIoDevice ( + PciRootBridgeIo, + Pci, + Bus, + Device, + Func + ); + + if (!PciIoDevice) { + return NULL; + } + + if (gFullEnumeration) { + PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED); + + // + // Initalize the bridge control register + // + PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED); + + } + // + // P2C only has one bar that is in 0x10 + // + PciParseBar(PciIoDevice, 0x10, 0); + + PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED | + EFI_BRIDGE_PMEM32_DECODE_SUPPORTED | + EFI_BRIDGE_IO32_DECODE_SUPPORTED; + + return PciIoDevice; +} + +EFI_DEVICE_PATH_PROTOCOL * +CreatePciDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + + PCI_DEVICE_PATH PciNode; + + // + // Create PCI device path + // + PciNode.Header.Type = HARDWARE_DEVICE_PATH; + PciNode.Header.SubType = HW_PCI_DP; + SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode)); + + PciNode.Device = PciIoDevice->DeviceNumber; + PciNode.Function = PciIoDevice->FunctionNumber; + PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header); + + return PciIoDevice->DevicePath; +} + +EFI_STATUS +BarExisted ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINTN Offset, + OUT UINT32 *BarLengthValue, + OUT UINT32 *OriginalBarValue + ) +/*++ + +Routine Description: + + Check the bar is existed or not. + +Arguments: + + PciIoDevice - A pointer to the PCI_IO_DEVICE. + Offset - The offset. + BarLengthValue - The bar length value. + OriginalBarValue - The original bar value. + +Returns: + + EFI_NOT_FOUND - The bar don't exist. + EFI_SUCCESS - The bar exist. + +--*/ +{ + EFI_PCI_IO_PROTOCOL *PciIo; + UINT32 OriginalValue; + UINT32 Value; + EFI_TPL OldTpl; + + PciIo = &PciIoDevice->PciIo; + + // + // Preserve the original value + // + + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue); + + // + // Raise TPL to high level to disable timer interrupt while the BAR is probed + // + OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne); + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value); + + // + // Write back the original value + // + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue); + + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (BarLengthValue != NULL) { + *BarLengthValue = Value; + } + + if (OriginalBarValue != NULL) { + *OriginalBarValue = OriginalValue; + } + + if (Value == 0) { + return EFI_NOT_FOUND; + } else { + return EFI_SUCCESS; + } +} + + +EFI_STATUS +DetermineDeviceAttribute ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + Determine the related attributes of all devices under a Root Bridge + +Arguments: + +Returns: + + None + +--*/ +{ + UINT16 Command; + UINT16 BridgeControl; + + Command = 0; + + PciIoDevice->Supports |= EFI_PCI_DEVICE_ENABLE; + PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE; + + if (IS_PCI_VGA (&(PciIoDevice->Pci))){ + + // + // If the device is VGA, VGA related Attributes are supported + // + PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ; + PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY ; + PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_IO ; + } + + if(IS_ISA_BRIDGE(&(PciIoDevice->Pci)) || IS_INTEL_ISA_BRIDGE(&(PciIoDevice->Pci))) { + // + // If the devie is a ISA Bridge, set the two attributes + // + PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO; + PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_IO; + } + + if (IS_PCI_GFX (&(PciIoDevice->Pci))) { + + // + // If the device is GFX, then only set the EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO + // attribute + // + PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ; + } + + + // + // If the device is IDE, IDE related attributes are supported + // + if (IS_PCI_IDE (&(PciIoDevice->Pci))) { + PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO ; + PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO ; + } + + PciReadCommandRegister(PciIoDevice, &Command); + + + if (Command & EFI_PCI_COMMAND_IO_SPACE) { + PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_IO; + } + + if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) { + PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY; + } + + if (Command & EFI_PCI_COMMAND_BUS_MASTER) { + PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER; + } + + if (IS_PCI_BRIDGE (&(PciIoDevice->Pci)) || + IS_CARDBUS_BRIDGE (&(PciIoDevice->Pci))){ + + // + // If it is a PPB, read the Bridge Control Register to determine + // the relevant attributes + // + BridgeControl = 0; + PciReadBridgeControlRegister(PciIoDevice, &BridgeControl); + + // + // Determine whether the ISA bit is set + // If ISA Enable on Bridge is set, the PPB + // will block forwarding 0x100-0x3ff for each 1KB in the + // first 64KB I/O range. + // + if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) { + PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO; + } + + // + // Determine whether the VGA bit is set + // If it is set, the bridge is set to decode VGA memory range + // and palette register range + // + if (IS_PCI_VGA (&(PciIoDevice->Pci)) &&BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) { + PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO; + PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY; + PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO; + } + + // + // if the palette snoop bit is set, then the brige is set to + // decode palette IO write + // + if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) { + PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO; + } + } + + return EFI_SUCCESS; +} + +UINTN +PciParseBar ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINTN Offset, + IN UINTN BarIndex + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + UINT32 Value; + UINT32 OriginalValue; + UINT32 Mask; + EFI_STATUS Status; + + OriginalValue = 0; + Value = 0; + + Status = BarExisted ( + PciIoDevice, + Offset, + &Value, + &OriginalValue + ); + + if (EFI_ERROR (Status)) { + PciIoDevice->PciBar[BarIndex].BaseAddress = 0; + PciIoDevice->PciBar[BarIndex].Length = 0; + PciIoDevice->PciBar[BarIndex].Alignment = 0; + + // + // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway + // + PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset; + return Offset + 4; + } + + PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset; + if (Value & 0x01) { + // + // Device I/Os + // + Mask = 0xfffffffc; + + if (Value & 0xFFFF0000) { + // + // It is a IO32 bar + // + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32; + PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1); + PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; + + } else { + // + // It is a IO16 bar + // + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16; + PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1); + PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; + + } + // + // Workaround. Some platforms inplement IO bar with 0 length + // Need to treat it as no-bar + // + if (PciIoDevice->PciBar[BarIndex].Length == 0) { + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown; + } + + PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE; + PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask; + + } else { + + Mask = 0xfffffff0; + + PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask; + + switch (Value & 0x07) { + + // + //memory space; anywhere in 32 bit address space + // + case 0x00: + if (Value & 0x08) { + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32; + } else { + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32; + } + + PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1; + PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; + + break; + + // + // memory space; anywhere in 64 bit address space + // + case 0x04: + if (Value & 0x08) { + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64; + } else { + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64; + } + + // + // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar + // is regarded as an extension for the first bar. As a result + // the sizing will be conducted on combined 64 bit value + // Here just store the masked first 32bit value for future size + // calculation + // + PciIoDevice->PciBar[BarIndex].Length = Value & Mask; + PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; + + // + // Increment the offset to point to next DWORD + // + Offset += 4; + + Status = BarExisted ( + PciIoDevice, + Offset, + &Value, + &OriginalValue + ); + + if (EFI_ERROR (Status)) { + return Offset + 4; + } + + // + // Fix the length to support some spefic 64 bit BAR + // + Value |= ((UINT32)(-1) << HighBitSet32 (Value)); + + // + // Calculate the size of 64bit bar + // + PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32); + + PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32); + PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1; + PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; + + break; + + // + // reserved + // + default: + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown; + PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1; + PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; + + break; + } + } + + // + // Check the length again so as to keep compatible with some special bars + // + if (PciIoDevice->PciBar[BarIndex].Length == 0) { + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown; + PciIoDevice->PciBar[BarIndex].BaseAddress = 0; + PciIoDevice->PciBar[BarIndex].Alignment = 0; + } + + // + // Increment number of bar + // + return Offset + 4; +} + +EFI_STATUS +InitializePPB ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_PCI_IO_PROTOCOL *PciIo; + + PciIo = &(PciIoDevice->PciIo); + + // + // Put all the resource apertures including IO16 + // Io32, pMem32, pMem64 to quiescent state + // Resource base all ones, Resource limit all zeros + // + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero); + + // + // don't support use io32 as for now + // + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero); + + return EFI_SUCCESS; +} + +EFI_STATUS +InitializeP2C ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_PCI_IO_PROTOCOL *PciIo; + + PciIo = &(PciIoDevice->PciIo); + + // + // Put all the resource apertures including IO16 + // Io32, pMem32, pMem64 to quiescent state( + // Resource base all ones, Resource limit all zeros + // + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero); + + return EFI_SUCCESS; +} + +PCI_IO_DEVICE * +CreatePciIoDevice ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = NULL; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (PCI_IO_DEVICE), + (VOID **) &PciIoDevice + ); + + if (EFI_ERROR (Status)) { + return NULL; + } + + ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE)); + + PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE; + PciIoDevice->Handle = NULL; + PciIoDevice->PciRootBridgeIo = PciRootBridgeIo; + PciIoDevice->DevicePath = NULL; + PciIoDevice->BusNumber = Bus; + PciIoDevice->DeviceNumber = Device; + PciIoDevice->FunctionNumber = Func; + PciIoDevice->Decodes = 0; + if (gFullEnumeration) { + PciIoDevice->Allocated = FALSE; + } else { + PciIoDevice->Allocated = TRUE; + } + + PciIoDevice->Attributes = 0; + PciIoDevice->Supports = 0; + PciIoDevice->IsPciExp = FALSE; + + CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01)); + + // + // Initialize the PCI I/O instance structure + // + + InitializePciIoInstance (PciIoDevice); + + if (EFI_ERROR (Status)) { + gBS->FreePool (PciIoDevice); + return NULL; + } + + // + // Initialize the reserved resource list + // + InitializeListHead (&PciIoDevice->ReservedResourceList); + + // + // Initialize the child list + // + InitializeListHead (&PciIoDevice->ChildList); + + return PciIoDevice; +} + +EFI_STATUS +PciEnumeratorLight ( + IN EFI_HANDLE Controller + ) +/*++ + +Routine Description: + + This routine is used to enumerate entire pci bus system + in a given platform + +Arguments: + +Returns: + + None + +--*/ +{ + + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + PCI_IO_DEVICE *RootBridgeDev; + UINT16 MinBus; + UINT16 MaxBus; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; + + MinBus = 0; + MaxBus = PCI_MAX_BUS; + Descriptors = NULL; + + // + // If this host bridge has been already enumerated, then return successfully + // + if (RootBridgeExisted (Controller)) { + return EFI_SUCCESS; + } + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller , + &gEfiDevicePathProtocolGuid, + (VOID **)&ParentDevicePath, + gPciBusDriverBinding.DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + + // + // Open pci root bridge io protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **) &PciRootBridgeIo, + gPciBusDriverBinding.DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + + // + // ** CHANGE ** + // PCI Option ROM support removed (continuation of patch by nms42). + // + + Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors); + + if (EFI_ERROR (Status)) { + return Status; + } + + while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) { + + // + // Create a device node for root bridge device with a NULL host bridge controller handle + // + RootBridgeDev = CreateRootBridge (Controller); + + // + // Record the root bridge device path + // + RootBridgeDev->DevicePath = ParentDevicePath; + + // + // Record the root bridge io protocol + // + RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo; + + Status = PciPciDeviceInfoCollector ( + RootBridgeDev, + (UINT8) MinBus + ); + + if (!EFI_ERROR (Status)) { + + // + // If successfully, insert the node into device pool + // + InsertRootBridge (RootBridgeDev); + } else { + + // + // If unsuccessly, destroy the entire node + // + DestroyRootBridge (RootBridgeDev); + } + + Descriptors++; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciGetBusRange ( + IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors, + OUT UINT16 *MinBus, + OUT UINT16 *MaxBus, + OUT UINT16 *BusRange + ) +/*++ + +Routine Description: + + Get the bus range. + +Arguments: + + Descriptors - A pointer to the address space descriptor. + MinBus - The min bus. + MaxBus - The max bus. + BusRange - The bus range. + +Returns: + + Status Code. + +--*/ +{ + + while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) { + if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) { + if (MinBus != NULL) { + *MinBus = (UINT16)(*Descriptors)->AddrRangeMin; + } + + if (MaxBus != NULL) { + *MaxBus = (UINT16)(*Descriptors)->AddrRangeMax; + } + + if (BusRange != NULL) { + *BusRange = (UINT16)(*Descriptors)->AddrLen; + } + return EFI_SUCCESS; + } + + (*Descriptors)++; + } + + return EFI_NOT_FOUND; +} + diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciEnumeratorSupport.h b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciEnumeratorSupport.h new file mode 100644 index 0000000000000000000000000000000000000000..aa2aba2efe7e79969fc86db6cc6a24c672c09b47 --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciEnumeratorSupport.h @@ -0,0 +1,108 @@ +/*++ + +Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciEnumeratorSupport.h + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_ENUMERATOR_SUPPORT_H +#define _EFI_PCI_ENUMERATOR_SUPPORT_H + +#include "PciBus.h" + +EFI_STATUS +PciPciDeviceInfoCollector ( + IN PCI_IO_DEVICE *Bridge, + UINT8 StartBusNumber + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + StartBusNumber - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciDevicePresent( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func +); + +EFI_STATUS +PciEnumeratorLight ( + IN EFI_HANDLE Controller + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Controller - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciGetBusRange ( + IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors, + OUT UINT16 *MinBus, + OUT UINT16 *MaxBus, + OUT UINT16 *BusRange + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Descriptors - TODO: add argument description + MinBus - TODO: add argument description + MaxBus - TODO: add argument description + BusRange - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; +#endif diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciIo.c b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciIo.c new file mode 100644 index 0000000000000000000000000000000000000000..5efedecd3010e8eafd3a37fcbae8445fe2044d53 --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciIo.c @@ -0,0 +1,1853 @@ +/*++ + +Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciIo.c + +Abstract: + + PCI I/O Abstraction Driver + +Revision History + +--*/ + +#include "PciBus.h" + +// +// PCI I/O Support Function Prototypes +// +// + +BOOLEAN +PciDevicesOnTheSamePath ( + IN PCI_IO_DEVICE *PciDevice1, + IN PCI_IO_DEVICE *PciDevice2 +); + + +EFI_STATUS +UpStreamBridgesAttributes ( + IN PCI_IO_DEVICE *PciIoDevice, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes +); + + +BOOLEAN +CheckBarType ( + IN PCI_IO_DEVICE *PciIoDevice, + UINT8 BarIndex, + PCI_BAR_TYPE BarType +); + + +EFI_STATUS +SetBootVGA ( + IN PCI_IO_DEVICE *PciIoDevice +); + +EFI_STATUS +DisableBootVGA ( + IN PCI_IO_DEVICE *PciIoDevice +); + + +EFI_STATUS +PciIoVerifyBarAccess ( + PCI_IO_DEVICE *PciIoDevice, + UINT8 BarIndex, + PCI_BAR_TYPE Type, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + UINT64 *Offset +); + +EFI_STATUS +PciIoVerifyConfigAccess ( + PCI_IO_DEVICE *PciIoDevice, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN UINT64 *Offset +); + +EFI_STATUS +EFIAPI +PciIoPollMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result +); + +EFI_STATUS +EFIAPI +PciIoPollIo ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result +); + +EFI_STATUS +EFIAPI +PciIoMemRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer +); + +EFI_STATUS +EFIAPI +PciIoMemWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer +); + +EFI_STATUS +EFIAPI +PciIoIoRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer +); + +EFI_STATUS +EFIAPI +PciIoIoWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer +); + +EFI_STATUS +EFIAPI +PciIoConfigRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer +); + +EFI_STATUS +EFIAPI +PciIoConfigWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer +); + +EFI_STATUS +EFIAPI +PciIoCopyMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 DestBarIndex, + IN UINT64 DestOffset, + IN UINT8 SrcBarIndex, + IN UINT64 SrcOffset, + IN UINTN Count +); + +EFI_STATUS +EFIAPI +PciIoMap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping +); + +EFI_STATUS +EFIAPI +PciIoUnmap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN VOID *Mapping +); + +EFI_STATUS +EFIAPI +PciIoAllocateBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes +); + +EFI_STATUS +EFIAPI +PciIoFreeBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ); + +EFI_STATUS +EFIAPI +PciIoFlush ( + IN EFI_PCI_IO_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +PciIoGetLocation ( + IN EFI_PCI_IO_PROTOCOL *This, + OUT UINTN *Segment, + OUT UINTN *Bus, + OUT UINTN *Device, + OUT UINTN *Function + ); + +EFI_STATUS +EFIAPI +PciIoAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes, + OUT UINT64 *Result OPTIONAL + ); + +EFI_STATUS +EFIAPI +PciIoGetBarAttributes( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT8 BarIndex, + OUT UINT64 *Supports, OPTIONAL + OUT VOID **Resources OPTIONAL + ); + +EFI_STATUS +EFIAPI +PciIoSetBarAttributes( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN UINT8 BarIndex, + IN OUT UINT64 *Offset, + IN OUT UINT64 *Length + ); + + +// +// Pci Io Protocol Interface +// +EFI_PCI_IO_PROTOCOL PciIoInterface = { + PciIoPollMem, + PciIoPollIo, + { + PciIoMemRead, + PciIoMemWrite + }, + { + PciIoIoRead, + PciIoIoWrite + }, + { + PciIoConfigRead, + PciIoConfigWrite + }, + PciIoCopyMem, + PciIoMap, + PciIoUnmap, + PciIoAllocateBuffer, + PciIoFreeBuffer, + PciIoFlush, + PciIoGetLocation, + PciIoAttributes, + PciIoGetBarAttributes, + PciIoSetBarAttributes, + 0, + NULL +}; + + +EFI_STATUS +InitializePciIoInstance ( + PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + Initializes a PCI I/O Instance + +Arguments: + +Returns: + + None + +--*/ + +{ + CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL)); + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoVerifyBarAccess ( + PCI_IO_DEVICE *PciIoDevice, + UINT8 BarIndex, + PCI_BAR_TYPE Type, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + UINT64 *Offset + ) +/*++ + +Routine Description: + + Verifies access to a PCI Base Address Register (BAR) + +Arguments: + +Returns: + + None + +--*/ +{ + if ((UINT32)Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) { + return EFI_SUCCESS; + } + + // + // BarIndex 0-5 is legal + // + if (BarIndex >= PCI_MAX_BAR) { + return EFI_INVALID_PARAMETER; + } + + if (!CheckBarType (PciIoDevice, BarIndex, Type)) { + return EFI_INVALID_PARAMETER; + } + + // + // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX + // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX + // + if (Width >= EfiPciIoWidthFifoUint8 && Width <= EfiPciIoWidthFifoUint64) { + Count = 1; + } + + Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03); + + if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) { + return EFI_INVALID_PARAMETER; + } + + *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress; + + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoVerifyConfigAccess ( + PCI_IO_DEVICE *PciIoDevice, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN UINT64 *Offset + ) +/*++ + +Routine Description: + + Verifies access to a PCI Config Header + +Arguments: + +Returns: + + None + +--*/ +{ + UINT64 ExtendOffset; + + if ((UINT32)Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + // + // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX + // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX + // + Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03); + + if (PciIoDevice->IsPciExp) { + if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) { + return EFI_UNSUPPORTED; + } + + ExtendOffset = LShiftU64 (*Offset, 32); + *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0); + *Offset = (*Offset) | ExtendOffset; + + } else { + if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) { + return EFI_UNSUPPORTED; + } + + *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PciIoPollMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +/*++ + +Routine Description: + + Poll PCI Memmory + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if ((UINT32)Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + if (Width > EfiPciIoWidthUint64) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoDevice->PciRootBridgeIo->PollMem ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Offset, + Mask, + Value, + Delay, + Result + ); + return Status; +} + +EFI_STATUS +EFIAPI +PciIoPollIo ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +/*++ + +Routine Description: + + Poll PCI IO + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if ((UINT32)Width > EfiPciIoWidthUint64) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = PciIoDevice->PciRootBridgeIo->PollIo ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Offset, + Mask, + Value, + Delay, + Result + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoMemRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs a PCI Memory Read Cycle + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + if (Buffer == NULL){ + return EFI_INVALID_PARAMETER; + } + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if ((UINT32)Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = PciIoDevice->PciRootBridgeIo->Mem.Read ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Offset, + Count, + Buffer + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoMemWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs a PCI Memory Write Cycle + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + if (Buffer == NULL){ + return EFI_INVALID_PARAMETER; + } + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if ((UINT32)Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = PciIoDevice->PciRootBridgeIo->Mem.Write ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Offset, + Count, + Buffer + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoIoRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs a PCI I/O Read Cycle + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + if (Buffer == NULL){ + return EFI_INVALID_PARAMETER; + } + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if ((UINT32)Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = PciIoDevice->PciRootBridgeIo->Io.Read ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Offset, + Count, + Buffer + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoIoWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs a PCI I/O Write Cycle + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + if (Buffer == NULL){ + return EFI_INVALID_PARAMETER; + } + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if ((UINT32)Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = PciIoDevice->PciRootBridgeIo->Io.Write ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Offset, + Count, + Buffer + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoConfigRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs a PCI Configuration Read Cycle + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + UINT64 Address; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + Address = Offset; + Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciIoDevice->PciRootBridgeIo->Pci.Read ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Address, + Count, + Buffer + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoConfigWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs a PCI Configuration Write Cycle + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + UINT64 Address; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + Address = Offset; + Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciIoDevice->PciRootBridgeIo->Pci.Write ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Address, + Count, + Buffer + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoCopyMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 DestBarIndex, + IN UINT64 DestOffset, + IN UINT8 SrcBarIndex, + IN UINT64 SrcOffset, + IN UINTN Count + ) +/*++ + +Routine Description: + + Copy PCI Memory + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if ((UINT32)Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + if (Width == EfiPciIoWidthFifoUint8 || + Width == EfiPciIoWidthFifoUint16 || + Width == EfiPciIoWidthFifoUint32 || + Width == EfiPciIoWidthFifoUint64 || + Width == EfiPciIoWidthFillUint8 || + Width == EfiPciIoWidthFillUint16 || + Width == EfiPciIoWidthFillUint32 || + Width == EfiPciIoWidthFillUint64) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = PciIoDevice->PciRootBridgeIo->CopyMem ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + DestOffset, + SrcOffset, + Count + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoMap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +/*++ + +Routine Description: + + Maps a memory region for DMA + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if ((UINT32)Operation >= EfiPciIoOperationMaximum) { + return EFI_INVALID_PARAMETER; + } + + if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) { + Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64); + } + + Status = PciIoDevice->PciRootBridgeIo->Map ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoUnmap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN VOID *Mapping + ) +/*++ + +Routine Description: + + Unmaps a memory region for DMA + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + Status = PciIoDevice->PciRootBridgeIo->Unmap ( + PciIoDevice->PciRootBridgeIo, + Mapping + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoAllocateBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + + Allocates a common buffer for DMA + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + if (Attributes & + (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) { + return EFI_UNSUPPORTED; + } + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) { + Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE; + } + + Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer ( + PciIoDevice->PciRootBridgeIo, + Type, + MemoryType, + Pages, + HostAddress, + Attributes + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoFreeBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +/*++ + +Routine Description: + + Frees a common buffer + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + if( HostAddress == NULL ){ + return EFI_INVALID_PARAMETER; + } + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + Status = PciIoDevice->PciRootBridgeIo->FreeBuffer ( + PciIoDevice->PciRootBridgeIo, + Pages, + HostAddress + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoFlush ( + IN EFI_PCI_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + Flushes a DMA buffer + +Arguments: + +Returns: + + None + +--*/ + +{ + EFI_STATUS Status; + UINT32 Register; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + // + // If the device is behind a PCI-PCI Bridge, then perform a read cycles to the device to + // flush the posted write cycles through the PCI-PCI bridges + // + if (PciIoDevice->Parent != NULL) { + Status = This->Pci.Read (This, EfiPciIoWidthUint32, 0, 1, &Register); + } + + // + // Call the PCI Root Bridge I/O Protocol to flush the posted write cycles through the chipset + // + Status = PciIoDevice->PciRootBridgeIo->Flush ( + PciIoDevice->PciRootBridgeIo + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoGetLocation ( + IN EFI_PCI_IO_PROTOCOL *This, + OUT UINTN *Segment, + OUT UINTN *Bus, + OUT UINTN *Device, + OUT UINTN *Function + ) +/*++ + +Routine Description: + + Gets a PCI device's current bus number, device number, and function number. + +Arguments: + +Returns: + + None + +--*/ +{ + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Segment = PciIoDevice->PciRootBridgeIo->SegmentNumber; + *Bus = PciIoDevice->BusNumber; + *Device = PciIoDevice->DeviceNumber; + *Function = PciIoDevice->FunctionNumber; + + return EFI_SUCCESS; +} + +BOOLEAN +CheckBarType ( + IN PCI_IO_DEVICE *PciIoDevice, + UINT8 BarIndex, + PCI_BAR_TYPE BarType + ) +/*++ + +Routine Description: + + Sets a PCI controllers attributes on a resource range + +Arguments: + +Returns: + + None + +--*/ +{ + switch (BarType) { + + case PciBarTypeMem: + + if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32 && + PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 && + PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 && + PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64 ) { + return FALSE; + } + + return TRUE; + + case PciBarTypeIo: + if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 && + PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){ + return FALSE; + } + + return TRUE; + + default: + break; + } + + return FALSE; +} + +EFI_STATUS +EFIAPI +PciIoAttributes ( + IN EFI_PCI_IO_PROTOCOL * This, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes, + OUT UINT64 *Result OPTIONAL + ) +/*++ + +Routine Description: + + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + + PCI_IO_DEVICE *PciIoDevice; + PCI_IO_DEVICE *Temp; + UINT64 NewAttributes; + UINT64 PciRootBridgeSupports; + UINT64 PciRootBridgeAttributes; + UINT64 NewPciRootBridgeAttributes; + UINT64 NewUpStreamBridgeAttributes; + UINT64 ModifiedPciRootBridgeAttributes; + UINT16 EnableCommand; + UINT16 DisableCommand; + UINT16 EnableBridge; + UINT16 DisableBridge; + UINT16 Command; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + NewUpStreamBridgeAttributes = 0; + + EnableCommand = 0; + DisableCommand = 0; + EnableBridge = 0; + DisableBridge = 0; + + switch (Operation) { + case EfiPciIoAttributeOperationGet: + if (Result == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Result = PciIoDevice->Attributes; + return EFI_SUCCESS; + + case EfiPciIoAttributeOperationSupported: + if (Result == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Result = PciIoDevice->Supports; + return EFI_SUCCESS; + + case EfiPciIoAttributeOperationEnable: + if(Attributes & ~(PciIoDevice->Supports)) { + return EFI_UNSUPPORTED; + } + NewAttributes = PciIoDevice->Attributes | Attributes; + break; + case EfiPciIoAttributeOperationDisable: + if(Attributes & ~(PciIoDevice->Supports)) { + return EFI_UNSUPPORTED; + } + NewAttributes = PciIoDevice->Attributes & (~Attributes); + break; + case EfiPciIoAttributeOperationSet: + if(Attributes & ~(PciIoDevice->Supports)) { + return EFI_UNSUPPORTED; + } + NewAttributes = Attributes; + break; + default: + return EFI_INVALID_PARAMETER; + } + + // + // If VGA_IO is set, then set VGA_MEMORY too. This driver can not enable them seperately. + // + if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) { + NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY; + } + + // + // If VGA_MEMORY is set, then set VGA_IO too. This driver can not enable them seperately. + // + if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY) { + NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO; + } + + // + // If the attributes are already set correctly, then just return EFI_SUCCESS; + // + if ((NewAttributes ^ PciIoDevice->Attributes) == 0) { + return EFI_SUCCESS; + } + + // + // This driver takes care of EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY, and + // EFI_PCI_IO_ATTRIBUTE_BUS_MASTER. Strip these 3 bits off the new attribute mask so + // a call to the PCI Root Bridge I/O Protocol can be made + // + + if (!IS_PCI_BRIDGE(&PciIoDevice->Pci)) { + NewPciRootBridgeAttributes = NewAttributes & (~(EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE)); + + // + // Get the current attributes of this PCI device's PCI Root Bridge + // + Status = PciIoDevice->PciRootBridgeIo->GetAttributes ( + PciIoDevice->PciRootBridgeIo, + &PciRootBridgeSupports, + &PciRootBridgeAttributes + ); + + // + // Check to see if any of the PCI Root Bridge attributes are being modified + // + ModifiedPciRootBridgeAttributes = NewPciRootBridgeAttributes ^ PciRootBridgeAttributes; + if (ModifiedPciRootBridgeAttributes) { + + // + // Check to see if the PCI Root Bridge supports modifiying the attributes that are changing + // + if ((ModifiedPciRootBridgeAttributes & PciRootBridgeSupports) != ModifiedPciRootBridgeAttributes) { + // return EFI_UNSUPPORTED; + } + // + // Call the PCI Root Bridge to attempt to modify the attributes + // + Status = PciIoDevice->PciRootBridgeIo->SetAttributes ( + PciIoDevice->PciRootBridgeIo, + NewPciRootBridgeAttributes, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + // + // The PCI Root Bridge could not modify the attributes, so return the error. + // + return Status; + } + } + } + + + if (IS_PCI_BRIDGE(&PciIoDevice->Pci)) { + + + // + // Check to see if an VGA related attributes are being set. + // + if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) { + + if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) { + EnableBridge |= EFI_PCI_BRIDGE_CONTROL_VGA; + } else { + DisableBridge |= EFI_PCI_BRIDGE_CONTROL_VGA; + } + } + + // + // Check to see if an VGA related attributes are being set. + // If ISA Enable on the PPB is set, the PPB will block the + // 0x100-0x3FF for each 1KB block in the first 64K I/O block + // + if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO)) { + + if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) { + DisableBridge |= EFI_PCI_BRIDGE_CONTROL_ISA; + } else { + EnableBridge |= EFI_PCI_BRIDGE_CONTROL_ISA; + } + } + + // + // Check to see if an VGA related attributes are being set. + // + if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) { + + if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) { + EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; + } else { + DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; + } + } + + } else { + + if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) { + + if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) { + + // + //Check if there have been an active VGA device on the same segment + // + Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice); + + if (Temp && Temp != PciIoDevice) { + return EFI_UNSUPPORTED; + } + } + } + + if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) { + if (IS_PCI_GFX(&PciIoDevice->Pci)) { + + // + //Get the boot VGA on the same segement + // + Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice); + + if (!Temp) { + + // + // If there is no VGA device on the segement, set + // this graphics card to decode the palette range + // + DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; + } else { + + // + // Check these two agents are on the same path + // + if (PciDevicesOnTheSamePath(Temp, PciIoDevice)) { + + // + // Check if they are on the same bus + // + if (Temp->Parent == PciIoDevice->Parent) { + + PciReadCommandRegister (Temp, &Command); + + // + // If they are on the same bus, either one can + // be set to snoop, the other set to decode + // + if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) { + DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; + } else { + EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; + } + } else { + + // + // If they are on the same path but on the different bus + // The first agent is set to snoop, the second one set to + // decode + // + if (Temp->BusNumber > PciIoDevice->BusNumber) { + PciEnableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP); + DisableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; + } else { + PciDisableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP); + EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; + } + } + } else { + + EnableCommand |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; + } + } + } + } + } + + // + // Check to see of the I/O enable is being modified + // + if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_IO)) { + if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) { + EnableCommand |= EFI_PCI_COMMAND_IO_SPACE; + } else { + DisableCommand |= EFI_PCI_COMMAND_IO_SPACE; + } + } + + // + // Check to see of the Memory enable is being modified + // + if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY)) { + if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) { + EnableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE; + } else { + DisableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE; + } + } + + // + // Check to see of the Bus Master enable is being modified + // + if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER)) { + if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) { + EnableCommand |= EFI_PCI_COMMAND_BUS_MASTER; + } else { + DisableCommand |= EFI_PCI_COMMAND_BUS_MASTER; + } + } + + Status = EFI_SUCCESS; + if (EnableCommand) { + Status = PciEnableCommandRegister(PciIoDevice, EnableCommand); + } + + if (DisableCommand) { + Status = PciDisableCommandRegister(PciIoDevice, DisableCommand); + } + + if (EFI_ERROR(Status)) { + return EFI_UNSUPPORTED; + } + + if (EnableBridge) { + Status = PciEnableBridgeControlRegister(PciIoDevice, EnableBridge); + } + + if (DisableBridge) { + Status = PciDisableBridgeControlRegister(PciIoDevice, DisableBridge); + } + + if (EFI_ERROR(Status)) { + return EFI_UNSUPPORTED; + } + + // + // Set the upstream bridge attributes + // + if (Operation != EfiPciIoAttributeOperationGet && Operation != EfiPciIoAttributeOperationSupported) { + + // + // EFI_PCI_IO_ATTRIBUTE_MEMORY, EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_BUS_MASTER + // EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED + // EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE will not effect to upstream bridge + // + NewUpStreamBridgeAttributes = Attributes & \ + (~(EFI_PCI_IO_ATTRIBUTE_IO | \ + EFI_PCI_IO_ATTRIBUTE_MEMORY | \ + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | \ + EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | \ + EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED | \ + EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE)); + + if (NewUpStreamBridgeAttributes){ + UpStreamBridgesAttributes(PciIoDevice, Operation, NewUpStreamBridgeAttributes); + } + } + + PciIoDevice->Attributes = NewAttributes; + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoGetBarAttributes ( + IN EFI_PCI_IO_PROTOCOL * This, + IN UINT8 BarIndex, + OUT UINT64 *Supports, OPTIONAL + OUT VOID **Resources OPTIONAL + ) +/*++ + +Routine Description: + + +Arguments: + +Returns: + + None + +--*/ +{ + + UINT8 *Configuration; + PCI_IO_DEVICE *PciIoDevice; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AddressSpace; + EFI_ACPI_END_TAG_DESCRIPTOR *End; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if (Supports == NULL && Resources == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((BarIndex >= PCI_MAX_BAR) || (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown)) { + return EFI_UNSUPPORTED; + } + + // + // This driver does not support modifications to the WRITE_COMBINE or + // CACHED attributes for BAR ranges. + // + if (Supports != NULL) { + *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE; + } + + if (Resources != NULL) { + Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)); + if (Configuration == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + AddressSpace = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; + + AddressSpace->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + AddressSpace->Len = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3); + + AddressSpace->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress; + AddressSpace->AddrLen = PciIoDevice->PciBar[BarIndex].Length; + AddressSpace->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment; + + switch (PciIoDevice->PciBar[BarIndex].BarType) { + case PciBarTypeIo16: + case PciBarTypeIo32: + // + // Io + // + AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_IO; + break; + + case PciBarTypeMem32: + // + // Mem + // + AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + // + // 32 bit + // + AddressSpace->AddrSpaceGranularity = 32; + break; + + case PciBarTypePMem32: + // + // Mem + // + AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + // + // prefechable + // + AddressSpace->SpecificFlag = 0x6; + // + // 32 bit + // + AddressSpace->AddrSpaceGranularity = 32; + break; + + case PciBarTypeMem64: + // + // Mem + // + AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + // + // 64 bit + // + AddressSpace->AddrSpaceGranularity = 64; + break; + + case PciBarTypePMem64: + // + // Mem + // + AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + // + // prefechable + // + AddressSpace->SpecificFlag = 0x6; + // + // 64 bit + // + AddressSpace->AddrSpaceGranularity = 64; + break; + + default: + break; + } + + // + // put the checksum + // + End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (AddressSpace + 1); + End->Desc = ACPI_END_TAG_DESCRIPTOR; + End->Checksum = 0; + + *Resources = Configuration; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PciIoSetBarAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN UINT8 BarIndex, + IN OUT UINT64 *Offset, + IN OUT UINT64 *Length + ) +/*++ + +Routine Description: + + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + UINT64 NonRelativeOffset; + UINT64 Supports; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + // + // Make sure Offset and Length are not NULL + // + if (Offset == NULL || Length == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) { + return EFI_UNSUPPORTED; + } + // + // This driver does not support setting the WRITE_COMBINE or the CACHED attributes. + // If Attributes is not 0, then return EFI_UNSUPPORTED. + // + Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE; + + if (Attributes != (Attributes & Supports)) { + return EFI_UNSUPPORTED; + } + // + // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and + // Length are valid for this PCI device. + // + NonRelativeOffset = *Offset; + Status = PciIoVerifyBarAccess ( + PciIoDevice, + BarIndex, + PciBarTypeMem, + EfiPciIoWidthUint8, + (UINT32) *Length, + &NonRelativeOffset + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +UpStreamBridgesAttributes ( + IN PCI_IO_DEVICE *PciIoDevice, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + PCI_IO_DEVICE *Parent; + EFI_PCI_IO_PROTOCOL *PciIo; + + Parent = PciIoDevice->Parent; + + while (Parent && IS_PCI_BRIDGE (&Parent->Pci)) { + + // + // Get the PciIo Protocol + // + PciIo = &Parent->PciIo; + + PciIo->Attributes (PciIo, Operation, Attributes, NULL); + + Parent = Parent->Parent; + } + + return EFI_SUCCESS; +} + +BOOLEAN +PciDevicesOnTheSamePath ( + IN PCI_IO_DEVICE *PciDevice1, + IN PCI_IO_DEVICE *PciDevice2 + ) +/*++ + +Routine Description: + +Arguments: + + PciDevice1 - The pointer to the first PCI_IO_DEVICE. + PciDevice2 - The pointer to the second PCI_IO_DEVICE. + +Returns: + + TRUE - The two Pci devices are on the same path. + FALSE - The two Pci devices are not on the same path. + +--*/ +{ + + if (PciDevice1->Parent == PciDevice2->Parent) { + return TRUE; + } + + return (BOOLEAN) ((PciDeviceExisted (PciDevice1->Parent, PciDevice2)|| PciDeviceExisted (PciDevice2->Parent, PciDevice1))); +} diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciIo.h b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciIo.h new file mode 100644 index 0000000000000000000000000000000000000000..b0d465a55a12532dc992c6c54ae732b6be8f93fd --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciIo.h @@ -0,0 +1,48 @@ +/*++ + +Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciIo.h + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_IO_PROTOCOL_H +#define _EFI_PCI_IO_PROTOCOL_H + +EFI_STATUS +InitializePciIoInstance ( + PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciPowerManagement.c b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciPowerManagement.c new file mode 100644 index 0000000000000000000000000000000000000000..0e239cec3c05c9fb8c40dcd66cb81707c6464d02 --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciPowerManagement.c @@ -0,0 +1,100 @@ +/*++ + +Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciPowerManagement.c + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#include "PciBus.h" + +EFI_STATUS +EFIAPI +ResetPowerManagementFeature ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + This function is intended to turn off PWE assertion and + put the device to D0 state if the device supports + PCI Power Management. + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + UINT8 PowerManagementRegBlock; + UINT16 PowerManagementCSR; + + PowerManagementRegBlock = 0; + + Status = LocateCapabilityRegBlock ( + PciIoDevice, + EFI_PCI_CAPABILITY_ID_PMI, + &PowerManagementRegBlock, + NULL + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Turn off the PWE assertion and put the device into D0 State + // + + // + // Read PMCSR + // + Status = PciIoDevice->PciIo.Pci.Read ( + &PciIoDevice->PciIo, + EfiPciIoWidthUint16, + PowerManagementRegBlock + 4, + 1, + &PowerManagementCSR + ); + if (!EFI_ERROR (Status)) { + // + // Clear PME_Status bit + // + PowerManagementCSR |= BIT15; + // + // Clear PME_En bit. PowerState = D0. + // + PowerManagementCSR &= ~(BIT8 | BIT1 | BIT0); + + // + // Write PMCSR + // + Status = PciIoDevice->PciIo.Pci.Write ( + &PciIoDevice->PciIo, + EfiPciIoWidthUint16, + PowerManagementRegBlock + 4, + 1, + &PowerManagementCSR + ); + } + return Status; +} diff --git a/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciPowerManagement.h b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciPowerManagement.h new file mode 100644 index 0000000000000000000000000000000000000000..98738b394b0609e965588dcd5b0529d137c30b13 --- /dev/null +++ b/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciPowerManagement.h @@ -0,0 +1,49 @@ +/*++ + +Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PciPowerManagement.h + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_POWER_MANAGEMENT_H +#define _EFI_PCI_POWER_MANAGEMENT_H + +EFI_STATUS +EFIAPI +ResetPowerManagementFeature ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/Legacy/BootPlatform/PciRootBridgeDxe/DeviceIo.c b/Legacy/BootPlatform/PciRootBridgeDxe/DeviceIo.c new file mode 100644 index 0000000000000000000000000000000000000000..e924b44dcd37e8f54920f58102462826f50753c3 --- /dev/null +++ b/Legacy/BootPlatform/PciRootBridgeDxe/DeviceIo.c @@ -0,0 +1,845 @@ +/*++ + +Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DeviceIo.c + +Abstract: + + EFI PC-AT PCI Device IO driver + +--*/ +#include "PcatPciRootBridge.h" +#include "DeviceIo.h" + +EFI_STATUS +DeviceIoConstructor ( + IN EFI_HANDLE Handle, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN UINT16 PrimaryBus, + IN UINT16 SubordinateBus + ) +/*++ + +Routine Description: + + Initialize and install a Device IO protocol on a empty device path handle. + +Arguments: + + Handle - Handle of PCI RootBridge IO instance + PciRootBridgeIo - PCI RootBridge IO instance + DevicePath - Device Path of PCI RootBridge IO instance + PrimaryBus - Primary Bus + SubordinateBus - Subordinate Bus + +Returns: + + EFI_SUCCESS - This driver is added to ControllerHandle. + EFI_ALREADY_STARTED - This driver is already running on ControllerHandle. + Others - This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + DEVICE_IO_PRIVATE_DATA *Private; + + // + // Initialize the Device IO device instance. + // + Private = AllocateZeroPool (sizeof (DEVICE_IO_PRIVATE_DATA)); + if (Private == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Private->Signature = DEVICE_IO_PRIVATE_DATA_SIGNATURE; + Private->Handle = Handle; + Private->PciRootBridgeIo = PciRootBridgeIo; + Private->DevicePath = DevicePath; + Private->PrimaryBus = PrimaryBus; + Private->SubordinateBus = SubordinateBus; + + Private->DeviceIo.Mem.Read = DeviceIoMemRead; + Private->DeviceIo.Mem.Write = DeviceIoMemWrite; + Private->DeviceIo.Io.Read = DeviceIoIoRead; + Private->DeviceIo.Io.Write = DeviceIoIoWrite; + Private->DeviceIo.Pci.Read = DeviceIoPciRead; + Private->DeviceIo.Pci.Write = DeviceIoPciWrite; + Private->DeviceIo.PciDevicePath = DeviceIoPciDevicePath; + Private->DeviceIo.Map = DeviceIoMap; + Private->DeviceIo.Unmap = DeviceIoUnmap; + Private->DeviceIo.AllocateBuffer = DeviceIoAllocateBuffer; + Private->DeviceIo.Flush = DeviceIoFlush; + Private->DeviceIo.FreeBuffer = DeviceIoFreeBuffer; + + // + // Install protocol interfaces for the Device IO device. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->Handle, + &gEfiDeviceIoProtocolGuid, + &Private->DeviceIo, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +EFI_STATUS +EFIAPI +DeviceIoMemRead ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Perform reading memory mapped I/O space of device. + +Arguments: + + This - A pointer to EFI_DEVICE_IO protocol instance. + Width - Width of I/O operations. + Address - The base address of I/O operations. + Count - The number of I/O operations to perform. + Bytes moves is Width size * Count, starting at Address. + Buffer - The destination buffer to store results. + +Returns: + + EFI_SUCCESS - The data was read from the device. + EFI_INVALID_PARAMETER - Width is invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +{ + EFI_STATUS Status; + DEVICE_IO_PRIVATE_DATA *Private; + + Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This); + + if (Width > MMIO_COPY_UINT64) { + return EFI_INVALID_PARAMETER; + } + if (Width >= MMIO_COPY_UINT8) { + Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8); + Status = Private->PciRootBridgeIo->CopyMem ( + Private->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + (UINT64)(UINTN) Buffer, + Address, + Count + ); + } else { + Status = Private->PciRootBridgeIo->Mem.Read ( + Private->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Address, + Count, + Buffer + ); + } + + return Status; +} + + + +EFI_STATUS +EFIAPI +DeviceIoMemWrite ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Perform writing memory mapped I/O space of device. + +Arguments: + + This - A pointer to EFI_DEVICE_IO protocol instance. + Width - Width of I/O operations. + Address - The base address of I/O operations. + Count - The number of I/O operations to perform. + Bytes moves is Width size * Count, starting at Address. + Buffer - The source buffer of data to be written. + +Returns: + + EFI_SUCCESS - The data was written to the device. + EFI_INVALID_PARAMETER - Width is invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +{ + EFI_STATUS Status; + DEVICE_IO_PRIVATE_DATA *Private; + + Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This); + + if (Width > MMIO_COPY_UINT64) { + return EFI_INVALID_PARAMETER; + } + if (Width >= MMIO_COPY_UINT8) { + Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8); + Status = Private->PciRootBridgeIo->CopyMem ( + Private->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Address, + (UINT64)(UINTN) Buffer, + Count + ); + } else { + Status = Private->PciRootBridgeIo->Mem.Write ( + Private->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Address, + Count, + Buffer + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +DeviceIoIoRead ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Perform reading I/O space of device. + +Arguments: + + This - A pointer to EFI_DEVICE_IO protocol instance. + Width - Width of I/O operations. + Address - The base address of I/O operations. + Count - The number of I/O operations to perform. + Bytes moves is Width size * Count, starting at Address. + Buffer - The destination buffer to store results. + +Returns: + + EFI_SUCCESS - The data was read from the device. + EFI_INVALID_PARAMETER - Width is invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +{ + EFI_STATUS Status; + DEVICE_IO_PRIVATE_DATA *Private; + + Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This); + + if (Width >= MMIO_COPY_UINT8) { + return EFI_INVALID_PARAMETER; + } + + Status = Private->PciRootBridgeIo->Io.Read ( + Private->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Address, + Count, + Buffer + ); + + return Status; +} + +EFI_STATUS +EFIAPI +DeviceIoIoWrite ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Perform writing I/O space of device. + +Arguments: + + This - A pointer to EFI_DEVICE_IO protocol instance. + Width - Width of I/O operations. + Address - The base address of I/O operations. + Count - The number of I/O operations to perform. + Bytes moves is Width size * Count, starting at Address. + Buffer - The source buffer of data to be written. + +Returns: + + EFI_SUCCESS - The data was written to the device. + EFI_INVALID_PARAMETER - Width is invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +{ + EFI_STATUS Status; + DEVICE_IO_PRIVATE_DATA *Private; + + Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This); + + if (Width >= MMIO_COPY_UINT8) { + return EFI_INVALID_PARAMETER; + } + + Status = Private->PciRootBridgeIo->Io.Write ( + Private->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Address, + Count, + Buffer + ); + + return Status; +} + +EFI_STATUS +EFIAPI +DeviceIoPciRead ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Perform reading PCI configuration space of device + +Arguments: + + This - A pointer to EFI_DEVICE_IO protocol instance. + Width - Width of I/O operations. + Address - The base address of I/O operations. + Count - The number of I/O operations to perform. + Bytes moves is Width size * Count, starting at Address. + Buffer - The destination buffer to store results. + +Returns: + + EFI_SUCCESS - The data was read from the device. + EFI_INVALID_PARAMETER - Width is invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +{ + EFI_STATUS Status; + DEVICE_IO_PRIVATE_DATA *Private; + + Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This); + + if ((UINT32)Width >= MMIO_COPY_UINT8) { + return EFI_INVALID_PARAMETER; + } + + Status = Private->PciRootBridgeIo->Pci.Read ( + Private->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Address, + Count, + Buffer + ); + + return Status; +} + +EFI_STATUS +EFIAPI +DeviceIoPciWrite ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Perform writing PCI configuration space of device. + +Arguments: + + This - A pointer to EFI_DEVICE_IO protocol instance. + Width - Width of I/O operations. + Address - The base address of I/O operations. + Count - The number of I/O operations to perform. + Bytes moves is Width size * Count, starting at Address. + Buffer - The source buffer of data to be written. + +Returns: + + EFI_SUCCESS - The data was written to the device. + EFI_INVALID_PARAMETER - Width is invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +{ + EFI_STATUS Status; + DEVICE_IO_PRIVATE_DATA *Private; + + Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This); + + if ((UINT32)Width >= MMIO_COPY_UINT8) { + return EFI_INVALID_PARAMETER; + } + + Status = Private->PciRootBridgeIo->Pci.Write ( + Private->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Address, + Count, + Buffer + ); + + return Status; +} + +EFI_DEVICE_PATH_PROTOCOL * +AppendPciDevicePath ( + IN DEVICE_IO_PRIVATE_DATA *Private, + IN UINT8 Bus, + IN UINT8 Device, + IN UINT8 Function, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN OUT UINT16 *BridgePrimaryBus, + IN OUT UINT16 *BridgeSubordinateBus + ) +/*++ + +Routine Description: + + Append a PCI device path node to another device path. + +Arguments: + + Private - A pointer to DEVICE_IO_PRIVATE_DATA instance. + Bus - PCI bus number of the device. + Device - PCI device number of the device. + Function - PCI function number of the device. + DevicePath - Original device path which will be appended a PCI device path node. + BridgePrimaryBus - Primary bus number of the bridge. + BridgeSubordinateBus - Subordinate bus number of the bridge. + +Returns: + + Pointer to the appended PCI device path. + +--*/ +{ + UINT16 ThisBus; + UINT8 ThisDevice; + UINT8 ThisFunc; + UINT64 Address; + PCI_TYPE01 PciBridge; + PCI_TYPE01 *PciPtr; + EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath; + PCI_DEVICE_PATH PciNode; + + PciPtr = &PciBridge; + for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) { + for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) { + for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) { + Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0); + ZeroMem (PciPtr, sizeof (PCI_TYPE01)); + Private->DeviceIo.Pci.Read ( + &Private->DeviceIo, + IO_UINT32, + Address, + 1, + &(PciPtr->Hdr.VendorId) + ); + if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) { + break; + } + if (PciPtr->Hdr.VendorId == 0xffff) { + continue; + } + + Private->DeviceIo.Pci.Read ( + &Private->DeviceIo, + IO_UINT32, + Address, + sizeof (PCI_TYPE01) / sizeof (UINT32), + PciPtr + ); + if (IS_PCI_BRIDGE (PciPtr)) { + if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) { + + PciNode.Header.Type = HARDWARE_DEVICE_PATH; + PciNode.Header.SubType = HW_PCI_DP; + SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode)); + + PciNode.Device = ThisDevice; + PciNode.Function = ThisFunc; + ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header); + + *BridgePrimaryBus = PciPtr->Bridge.SecondaryBus; + *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus; + return ReturnDevicePath; + } + } + + if ((ThisFunc == 0) && ((PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x0)) { + // + // Skip sub functions, this is not a multi function device + // + break; + } + } + } + } + + ZeroMem (&PciNode, sizeof (PciNode)); + PciNode.Header.Type = HARDWARE_DEVICE_PATH; + PciNode.Header.SubType = HW_PCI_DP; + SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode)); + PciNode.Device = Device; + PciNode.Function = Function; + + ReturnDevicePath = AppendDevicePathNode (DevicePath, &PciNode.Header); + + *BridgePrimaryBus = 0xffff; + *BridgeSubordinateBus = 0xffff; + return ReturnDevicePath; +} + +EFI_STATUS +EFIAPI +DeviceIoPciDevicePath ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN UINT64 Address, + IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath + ) +/*++ + +Routine Description: + + Provides an EFI Device Path for a PCI device with the given PCI configuration space address. + +Arguments: + + This - A pointer to the EFI_DEVICE_IO_INTERFACE instance. + Address - The PCI configuration space address of the device whose Device Path + is going to be returned. + PciDevicePath - A pointer to the pointer for the EFI Device Path for PciAddress. + Memory for the Device Path is allocated from the pool. + +Returns: + + EFI_SUCCESS - The PciDevicePath returns a pointer to a valid EFI Device Path. + EFI_UNSUPPORTED - The PciAddress does not map to a valid EFI Device Path. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. + +--*/ +{ + DEVICE_IO_PRIVATE_DATA *Private; + UINT16 PrimaryBus; + UINT16 SubordinateBus; + UINT8 Bus; + UINT8 Device; + UINT8 Func; + + Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This); + + Bus = (UINT8) (((UINT32) Address >> 24) & 0xff); + Device = (UINT8) (((UINT32) Address >> 16) & 0xff); + Func = (UINT8) (((UINT32) Address >> 8) & 0xff); + + if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) { + return EFI_UNSUPPORTED; + } + + *PciDevicePath = Private->DevicePath; + PrimaryBus = Private->PrimaryBus; + SubordinateBus = Private->SubordinateBus; + do { + *PciDevicePath = AppendPciDevicePath ( + Private, + Bus, + Device, + Func, + *PciDevicePath, + &PrimaryBus, + &SubordinateBus + ); + if (*PciDevicePath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } while (PrimaryBus != 0xffff); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DeviceIoMap ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_OPERATION_TYPE Operation, + IN EFI_PHYSICAL_ADDRESS *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +/*++ + +Routine Description: + + Provides the device-specific addresses needed to access system memory. + +Arguments: + + This - A pointer to the EFI_DEVICE_IO_INTERFACE instance. + Operation - Indicates if the bus master is going to read or write to system memory. + HostAddress - The system memory address to map to the device. + NumberOfBytes - On input the number of bytes to map. On output the number of bytes + that were mapped. + DeviceAddress - The resulting map address for the bus master device to use to access the + hosts HostAddress. + Mapping - A resulting value to pass to Unmap(). + +Returns: + + EFI_SUCCESS - The range was mapped for the returned NumberOfBytes. + EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined. + EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common buffer. + EFI_DEVICE_ERROR - The system hardware could not map the requested address. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. + +--*/ +{ + EFI_STATUS Status; + DEVICE_IO_PRIVATE_DATA *Private; + + Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This); + + if ((UINT32)Operation > EfiBusMasterCommonBuffer) { + return EFI_INVALID_PARAMETER; + } + + if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) { + return EFI_UNSUPPORTED; + } + + Status = Private->PciRootBridgeIo->Map ( + Private->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation, + (VOID *) (UINTN) (*HostAddress), + NumberOfBytes, + DeviceAddress, + Mapping + ); + + return Status; +} + +EFI_STATUS +EFIAPI +DeviceIoUnmap ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN VOID *Mapping + ) +/*++ + +Routine Description: + + Completes the Map() operation and releases any corresponding resources. + +Arguments: + + This - A pointer to the EFI_DEVICE_IO_INTERFACE instance. + Mapping - The mapping value returned from Map(). + +Returns: + + EFI_SUCCESS - The range was unmapped. + EFI_DEVICE_ERROR - The data was not committed to the target system memory. + +--*/ +{ + EFI_STATUS Status; + DEVICE_IO_PRIVATE_DATA *Private; + + Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This); + + Status = Private->PciRootBridgeIo->Unmap ( + Private->PciRootBridgeIo, + Mapping + ); + + return Status; +} + +EFI_STATUS +EFIAPI +DeviceIoAllocateBuffer ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS *PhysicalAddress + ) +/*++ + +Routine Description: + + Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping. + +Arguments: + + This - A pointer to the EFI_DEVICE_IO_INTERFACE instance. + Type - The type allocation to perform. + MemoryType - The type of memory to allocate, EfiBootServicesData or + EfiRuntimeServicesData. + Pages - The number of pages to allocate. + PhysicalAddress - A pointer to store the base address of the allocated range. + +Returns: + + EFI_SUCCESS - The requested memory pages were allocated. + EFI_OUT_OF_RESOURCES - The memory pages could not be allocated. + EFI_INVALID_PARAMETER - The requested memory type is invalid. + EFI_UNSUPPORTED - The requested PhysicalAddress is not supported on + this platform. + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS HostAddress; + + HostAddress = *PhysicalAddress; + + if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) { + return EFI_INVALID_PARAMETER; + } + + if ((UINT32)Type >= MaxAllocateType) { + return EFI_INVALID_PARAMETER; + } + + if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) { + return EFI_UNSUPPORTED; + } + + if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) { + Type = AllocateMaxAddress; + HostAddress = MAX_COMMON_BUFFER; + } + + Status = gBS->AllocatePages ( + Type, + MemoryType, + Pages, + &HostAddress + ); + if (EFI_ERROR (Status)) { + return Status; + } + + + *PhysicalAddress = HostAddress; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DeviceIoFlush ( + IN EFI_DEVICE_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + Flushes any posted write data to the device. + +Arguments: + + This - A pointer to the EFI_DEVICE_IO_INTERFACE instance. + +Returns: + + EFI_SUCCESS - The buffers were flushed. + EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error. + +--*/ +{ + EFI_STATUS Status; + DEVICE_IO_PRIVATE_DATA *Private; + + Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This); + + Status = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo); + + return Status; +} + +EFI_STATUS +EFIAPI +DeviceIoFreeBuffer ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN UINTN Pages, + IN EFI_PHYSICAL_ADDRESS HostAddress + ) +/*++ + +Routine Description: + + Frees pages that were allocated with AllocateBuffer(). + +Arguments: + + This - A pointer to the EFI_DEVICE_IO_INTERFACE instance. + Pages - The number of pages to free. + HostAddress - The base address of the range to free. + +Returns: + + EFI_SUCCESS - The requested memory pages were freed. + EFI_NOT_FOUND - The requested memory pages were not allocated with + AllocateBuffer(). + EFI_INVALID_PARAMETER - HostAddress is not page aligned or Pages is invalid. + +--*/ +{ + if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) { + return EFI_INVALID_PARAMETER; + } + + return gBS->FreePages (HostAddress, Pages); +} diff --git a/Legacy/BootPlatform/PciRootBridgeDxe/DeviceIo.h b/Legacy/BootPlatform/PciRootBridgeDxe/DeviceIo.h new file mode 100644 index 0000000000000000000000000000000000000000..9b483743da63252460a9d1a8b1a7c099f17c9b72 --- /dev/null +++ b/Legacy/BootPlatform/PciRootBridgeDxe/DeviceIo.h @@ -0,0 +1,449 @@ +/*++ + +Copyright (c) 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DeviceIo.h + +Abstract: + + Private Data definition for Device IO driver + +--*/ + +#ifndef _DEVICE_IO_H +#define _DEVICE_IO_H + + + +#define DEVICE_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('d', 'e', 'v', 'I') + +#define MAX_COMMON_BUFFER 0x00000000FFFFFFFF + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + EFI_DEVICE_IO_PROTOCOL DeviceIo; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINT16 PrimaryBus; + UINT16 SubordinateBus; +} DEVICE_IO_PRIVATE_DATA; + +#define DEVICE_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DEVICE_IO_PRIVATE_DATA, DeviceIo, DEVICE_IO_PRIVATE_DATA_SIGNATURE) + +EFI_STATUS +DeviceIoConstructor ( + IN EFI_HANDLE Handle, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN UINT16 PrimaryBus, + IN UINT16 SubordinateBus + ) +/*++ + +Routine Description: + + Initialize and install a Device IO protocol on a empty device path handle. + +Arguments: + + Handle - Handle of PCI RootBridge IO instance + PciRootBridgeIo - PCI RootBridge IO instance + DevicePath - Device Path of PCI RootBridge IO instance + PrimaryBus - Primary Bus + SubordinateBus - Subordinate Bus + +Returns: + + EFI_SUCCESS - This driver is added to ControllerHandle. + EFI_ALREADY_STARTED - This driver is already running on ControllerHandle. + Others - This driver does not support this device. + +--*/ +; + +EFI_STATUS +EFIAPI +DeviceIoMemRead ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Perform reading memory mapped I/O space of device. + +Arguments: + + This - A pointer to EFI_DEVICE_IO protocol instance. + Width - Width of I/O operations. + Address - The base address of I/O operations. + Count - The number of I/O operations to perform. + Bytes moves is Width size * Count, starting at Address. + Buffer - The destination buffer to store results. + +Returns: + + EFI_SUCCESS - The data was read from the device. + EFI_INVALID_PARAMETER - Width is invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +; + +EFI_STATUS +EFIAPI +DeviceIoMemWrite ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Perform writing memory mapped I/O space of device. + +Arguments: + + This - A pointer to EFI_DEVICE_IO protocol instance. + Width - Width of I/O operations. + Address - The base address of I/O operations. + Count - The number of I/O operations to perform. + Bytes moves is Width size * Count, starting at Address. + Buffer - The source buffer of data to be written. + +Returns: + + EFI_SUCCESS - The data was written to the device. + EFI_INVALID_PARAMETER - Width is invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +; + +EFI_STATUS +EFIAPI +DeviceIoIoRead ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Perform reading I/O space of device. + +Arguments: + + This - A pointer to EFI_DEVICE_IO protocol instance. + Width - Width of I/O operations. + Address - The base address of I/O operations. + Count - The number of I/O operations to perform. + Bytes moves is Width size * Count, starting at Address. + Buffer - The destination buffer to store results. + +Returns: + + EFI_SUCCESS - The data was read from the device. + EFI_INVALID_PARAMETER - Width is invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +; + +EFI_STATUS +EFIAPI +DeviceIoIoWrite ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Perform writing I/O space of device. + +Arguments: + + This - A pointer to EFI_DEVICE_IO protocol instance. + Width - Width of I/O operations. + Address - The base address of I/O operations. + Count - The number of I/O operations to perform. + Bytes moves is Width size * Count, starting at Address. + Buffer - The source buffer of data to be written. + +Returns: + + EFI_SUCCESS - The data was written to the device. + EFI_INVALID_PARAMETER - Width is invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +; + +EFI_STATUS +EFIAPI +DeviceIoPciRead ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Perform reading PCI configuration space of device + +Arguments: + + This - A pointer to EFI_DEVICE_IO protocol instance. + Width - Width of I/O operations. + Address - The base address of I/O operations. + Count - The number of I/O operations to perform. + Bytes moves is Width size * Count, starting at Address. + Buffer - The destination buffer to store results. + +Returns: + + EFI_SUCCESS - The data was read from the device. + EFI_INVALID_PARAMETER - Width is invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +; + +EFI_STATUS +EFIAPI +DeviceIoPciWrite ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Perform writing PCI configuration space of device. + +Arguments: + + This - A pointer to EFI_DEVICE_IO protocol instance. + Width - Width of I/O operations. + Address - The base address of I/O operations. + Count - The number of I/O operations to perform. + Bytes moves is Width size * Count, starting at Address. + Buffer - The source buffer of data to be written. + +Returns: + + EFI_SUCCESS - The data was written to the device. + EFI_INVALID_PARAMETER - Width is invalid. + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +; + +EFI_STATUS +EFIAPI +DeviceIoPciDevicePath ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN UINT64 Address, + IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath + ) +/*++ + +Routine Description: + + Append a PCI device path node to another device path. + +Arguments: + + This - A pointer to EFI_DEVICE_IO_PROTOCOL. + Address - PCI bus,device, function. + PciDevicePath - PCI device path. + +Returns: + + Pointer to the appended PCI device path. + +--*/ +; + +EFI_STATUS +EFIAPI +DeviceIoMap ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_OPERATION_TYPE Operation, + IN EFI_PHYSICAL_ADDRESS *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +/*++ + +Routine Description: + + Provides the device-specific addresses needed to access system memory. + +Arguments: + + This - A pointer to the EFI_DEVICE_IO_INTERFACE instance. + Operation - Indicates if the bus master is going to read or write to system memory. + HostAddress - The system memory address to map to the device. + NumberOfBytes - On input the number of bytes to map. On output the number of bytes + that were mapped. + DeviceAddress - The resulting map address for the bus master device to use to access the + hosts HostAddress. + Mapping - A resulting value to pass to Unmap(). + +Returns: + + EFI_SUCCESS - The range was mapped for the returned NumberOfBytes. + EFI_INVALID_PARAMETER - The Operation or HostAddress is undefined. + EFI_UNSUPPORTED - The HostAddress cannot be mapped as a common buffer. + EFI_DEVICE_ERROR - The system hardware could not map the requested address. + EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. + +--*/ +; + +EFI_STATUS +EFIAPI +DeviceIoUnmap ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN VOID *Mapping + ) +/*++ + +Routine Description: + + Completes the Map() operation and releases any corresponding resources. + +Arguments: + + This - A pointer to the EFI_DEVICE_IO_INTERFACE instance. + Mapping - The mapping value returned from Map(). + +Returns: + + EFI_SUCCESS - The range was unmapped. + EFI_DEVICE_ERROR - The data was not committed to the target system memory. + +--*/ +; + +EFI_STATUS +EFIAPI +DeviceIoAllocateBuffer ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS *HostAddress + ) +/*++ + +Routine Description: + + Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping. + +Arguments: + + This - A pointer to the EFI_DEVICE_IO_INTERFACE instance. + Type - The type allocation to perform. + MemoryType - The type of memory to allocate, EfiBootServicesData or + EfiRuntimeServicesData. + Pages - The number of pages to allocate. + HostAddress - A pointer to store the base address of the allocated range. + +Returns: + + EFI_SUCCESS - The requested memory pages were allocated. + EFI_OUT_OF_RESOURCES - The memory pages could not be allocated. + EFI_INVALID_PARAMETER - The requested memory type is invalid. + EFI_UNSUPPORTED - The requested PhysicalAddress is not supported on + this platform. + +--*/ +; + +EFI_STATUS +EFIAPI +DeviceIoFlush ( + IN EFI_DEVICE_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + Flushes any posted write data to the device. + +Arguments: + + This - A pointer to the EFI_DEVICE_IO_INTERFACE instance. + +Returns: + + EFI_SUCCESS - The buffers were flushed. + EFI_DEVICE_ERROR - The buffers were not flushed due to a hardware error. + +--*/ +; + +EFI_STATUS +EFIAPI +DeviceIoFreeBuffer ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN UINTN Pages, + IN EFI_PHYSICAL_ADDRESS HostAddress + ) +/*++ + +Routine Description: + + Frees pages that were allocated with AllocateBuffer(). + +Arguments: + + This - A pointer to the EFI_DEVICE_IO_INTERFACE instance. + Pages - The number of pages to free. + HostAddress - The base address of the range to free. + +Returns: + + EFI_SUCCESS - The requested memory pages were freed. + EFI_NOT_FOUND - The requested memory pages were not allocated with + AllocateBuffer(). + EFI_INVALID_PARAMETER - HostAddress is not page aligned or Pages is invalid. + +--*/ +; + +#endif + diff --git a/Legacy/BootPlatform/PciRootBridgeDxe/PcatIo.c b/Legacy/BootPlatform/PciRootBridgeDxe/PcatIo.c new file mode 100644 index 0000000000000000000000000000000000000000..96a39bb49d7f9e65b3a0cc5cfa73afc995c9801a --- /dev/null +++ b/Legacy/BootPlatform/PciRootBridgeDxe/PcatIo.c @@ -0,0 +1,212 @@ +/*++ + +Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + PcatPciRootBridgeIo.c + +Abstract: + + EFI PC AT PCI Root Bridge Io Protocol + +Revision History + +--*/ + +#include "PcatPciRootBridge.h" + +BOOLEAN mPciOptionRomTableInstalled = FALSE; +EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable = {0, NULL}; + +EFI_STATUS +EFIAPI +PcatRootBridgeIoIoRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + IN OUT VOID *UserBuffer + ) +{ + return gCpuIo->Io.Read ( + gCpuIo, + (EFI_CPU_IO_PROTOCOL_WIDTH) Width, + UserAddress, + Count, + UserBuffer + ); +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoIoWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + IN OUT VOID *UserBuffer + ) +{ + return gCpuIo->Io.Write ( + gCpuIo, + (EFI_CPU_IO_PROTOCOL_WIDTH) Width, + UserAddress, + Count, + UserBuffer + ); + +} + +EFI_STATUS +PcatRootBridgeIoGetIoPortMapping ( + OUT EFI_PHYSICAL_ADDRESS *IoPortMapping, + OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping + ) +/*++ + + Get the IO Port Mapping. For IA-32 it is always 0. + +--*/ +{ + *IoPortMapping = 0; + *MemoryPortMapping = 0; + + return EFI_SUCCESS; +} + +EFI_STATUS +PcatRootBridgeIoPciRW ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN BOOLEAN Write, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + IN OUT VOID *UserBuffer + ) +{ + PCI_CONFIG_ACCESS_CF8 Pci; + PCI_CONFIG_ACCESS_CF8 PciAligned; + UINT32 InStride; + UINT32 OutStride; + UINTN PciData; + UINTN PciDataStride; + PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress; + UINT64 PciExpressRegAddr; + BOOLEAN UsePciExpressAccess; + + if ((UINT32)Width >= EfiPciWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + if ((Width & 0x03) >= EfiPciWidthUint64) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); + + InStride = 1 << (Width & 0x03); + OutStride = InStride; + if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) { + InStride = 0; + } + + if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) { + OutStride = 0; + } + + UsePciExpressAccess = FALSE; + + CopyMem (&PciAddress, &UserAddress, sizeof(UINT64)); + + if (PciAddress.ExtendedRegister > 0xFF) { + // + // Check PciExpressBaseAddress + // + if ((PrivateData->PciExpressBaseAddress == 0) || + (PrivateData->PciExpressBaseAddress >= MAX_ADDRESS)) { + return EFI_UNSUPPORTED; + } else { + UsePciExpressAccess = TRUE; + } + } else { + if (PciAddress.ExtendedRegister != 0) { + Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF; + } else { + Pci.Bits.Reg = PciAddress.Register; + } + // + // Note: We can also use PciExpress access here, if wanted. + // + } + + if (!UsePciExpressAccess) { + Pci.Bits.Func = PciAddress.Function; + Pci.Bits.Dev = PciAddress.Device; + Pci.Bits.Bus = PciAddress.Bus; + Pci.Bits.Reserved = 0; + Pci.Bits.Enable = 1; + + // + // PCI Config access are all 32-bit alligned, but by accessing the + // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types + // are possible on PCI. + // + // To read a byte of PCI config space you load 0xcf8 and + // read 0xcfc, 0xcfd, 0xcfe, 0xcff + // + PciDataStride = Pci.Bits.Reg & 0x03; + + while (Count) { + PciAligned = Pci; + PciAligned.Bits.Reg &= 0xfc; + PciData = (UINTN)PrivateData->PciData + PciDataStride; + EfiAcquireLock(&PrivateData->PciLock); + This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned); + if (Write) { + This->Io.Write (This, Width, PciData, 1, UserBuffer); + } else { + This->Io.Read (This, Width, PciData, 1, UserBuffer); + } + EfiReleaseLock(&PrivateData->PciLock); + UserBuffer = ((UINT8 *)UserBuffer) + OutStride; + PciDataStride = (PciDataStride + InStride) % 4; + Pci.Bits.Reg += InStride; + Count -= 1; + } + } else { + // + // Access PCI-Express space by using memory mapped method. + // + PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) | + (PciAddress.Bus << 20) | + (PciAddress.Device << 15) | + (PciAddress.Function << 12); + if (PciAddress.ExtendedRegister != 0) { + PciExpressRegAddr += PciAddress.ExtendedRegister; + } else { + PciExpressRegAddr += PciAddress.Register; + } + while (Count) { + if (Write) { + This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer); + } else { + This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer); + } + + UserBuffer = ((UINT8 *) UserBuffer) + OutStride; + PciExpressRegAddr += InStride; + Count -= 1; + } + } + + return EFI_SUCCESS; +} + diff --git a/Legacy/BootPlatform/PciRootBridgeDxe/PcatPciRootBridge.c b/Legacy/BootPlatform/PciRootBridgeDxe/PcatPciRootBridge.c new file mode 100644 index 0000000000000000000000000000000000000000..7dca504b427b3405be3f6a2e9f1c488ddfab358e --- /dev/null +++ b/Legacy/BootPlatform/PciRootBridgeDxe/PcatPciRootBridge.c @@ -0,0 +1,1067 @@ +/*++ + +Copyright (c) 2005 - 2009, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + PcatPciRootBridge.c + +Abstract: + + EFI PC-AT PCI Root Bridge Controller + +--*/ + +#include "PcatPciRootBridge.h" +#include "DeviceIo.h" + +EFI_CPU_IO2_PROTOCOL *gCpuIo; + + +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Hdr; + union { + PCI_CARDBUS_CONTROL_REGISTER CardBridge; + PCI_BRIDGE_CONTROL_REGISTER P2PBridge; + } Bridge; +} PCI_TYPE02; + +EFI_STATUS +EFIAPI +InitializePcatPciRootBridge ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Initializes the PCI Root Bridge Controller + +Arguments: + ImageHandle - + SystemTable - + +Returns: + None + +--*/ +{ + EFI_STATUS Status; + PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + UINTN PciSegmentIndex; + UINTN PciRootBridgeIndex; + UINTN PrimaryBusIndex; + UINTN NumberOfPciRootBridges; + UINTN NumberOfPciDevices; + UINTN Device; + UINTN Function; + UINT16 VendorId; + PCI_TYPE02 PciConfigurationHeader; + UINT64 Address; + UINT64 Value; + UINT64 Base; + UINT64 Limit; + + // + // Initialize gCpuIo now since the chipset init code requires it. + // + Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&gCpuIo); + ASSERT_EFI_ERROR (Status); + + // + // Initialize variables required to search all PCI segments for PCI devices + // + PciSegmentIndex = 0; + PciRootBridgeIndex = 0; + NumberOfPciRootBridges = 0; + PrimaryBusIndex = 0; + + while (PciSegmentIndex <= PCI_MAX_SEGMENT) { + + PrivateData = NULL; + Status = gBS->AllocatePool( + EfiBootServicesData, + sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE), + (VOID **)&PrivateData + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + ZeroMem (PrivateData, sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE)); + + // + // Initialize the signature of the private data structure + // + PrivateData->Signature = PCAT_PCI_ROOT_BRIDGE_SIGNATURE; + PrivateData->Handle = NULL; + PrivateData->DevicePath = NULL; + InitializeListHead (&PrivateData->MapInfo); + + // + // Initialize the PCI root bridge number and the bus range for that root bridge + // + PrivateData->RootBridgeNumber = (UINT32)PciRootBridgeIndex; + PrivateData->PrimaryBus = (UINT32)PrimaryBusIndex; + PrivateData->SubordinateBus = (UINT32)PrimaryBusIndex; + + PrivateData->IoBase = 0xffffffff; + PrivateData->MemBase = 0xffffffff; + PrivateData->Mem32Base = 0xffffffffffffffffULL; + PrivateData->Pmem32Base = 0xffffffffffffffffULL; + PrivateData->Mem64Base = 0xffffffffffffffffULL; + PrivateData->Pmem64Base = 0xffffffffffffffffULL; + + // + // The default mechanism for performing PCI Configuration cycles is to + // use the I/O ports at 0xCF8 and 0xCFC. This is only used for IA-32. + // IPF uses SAL calls to perform PCI COnfiguration cycles + // + PrivateData->PciAddress = 0xCF8; + PrivateData->PciData = 0xCFC; + + // + // Get the physical I/O base for performing PCI I/O cycles + // For IA-32, this is always 0, because IA-32 has IN and OUT instructions + // For IPF, a SAL call is made to retrieve the base address for PCI I/O cycles + // + Status = PcatRootBridgeIoGetIoPortMapping ( + &PrivateData->PhysicalIoBase, + &PrivateData->PhysicalMemoryBase + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Get PCI Express Base Address + // + PrivateData->PciExpressBaseAddress = GetPciExpressBaseAddressForRootBridge (PciSegmentIndex, PciRootBridgeIndex); + + // + // Create a lock for performing PCI Configuration cycles + // + EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL); + + // + // Initialize the attributes for this PCI root bridge + // + PrivateData->Attributes = 0; + + // + // Build the EFI Device Path Protocol instance for this PCI Root Bridge + // + Status = PcatRootBridgeDevicePathConstructor (&PrivateData->DevicePath, PciRootBridgeIndex, (BOOLEAN)((PrivateData->PciExpressBaseAddress != 0) ? TRUE : FALSE)); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Build the PCI Root Bridge I/O Protocol instance for this PCI Root Bridge + // + Status = PcatRootBridgeIoConstructor (&PrivateData->Io, PciSegmentIndex); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Scan all the PCI devices on the primary bus of the PCI root bridge + // + for (Device = 0, NumberOfPciDevices = 0; Device <= PCI_MAX_DEVICE; Device++) { + + for (Function = 0; Function <= PCI_MAX_FUNC; Function++) { + + // + // Compute the PCI configuration address of the PCI device to probe + // + Address = EFI_PCI_ADDRESS (PrimaryBusIndex, Device, Function, 0); + + // + // Read the Vendor ID from the PCI Configuration Header + // + Status = PrivateData->Io.Pci.Read ( + &PrivateData->Io, + EfiPciWidthUint16, + Address, + sizeof (VendorId) / sizeof (UINT16), + &VendorId + ); + if ((EFI_ERROR (Status)) || ((VendorId == 0xffff) && (Function == 0))) { + // + // If the PCI Configuration Read fails, or a PCI device does not exist, then + // skip this entire PCI device + // + break; + } + if (VendorId == 0xffff) { + // + // If PCI function != 0, VendorId == 0xFFFF, we continue to search PCI function. + // + continue; + } + + // + // Read the entire PCI Configuration Header + // + Status = PrivateData->Io.Pci.Read ( + &PrivateData->Io, + EfiPciWidthUint16, + Address, + sizeof (PciConfigurationHeader) / sizeof (UINT16), + &PciConfigurationHeader + ); + if (EFI_ERROR (Status)) { + // + // If the entire PCI Configuration Header can not be read, then skip this entire PCI device + // + break; + } + + + // + // Increment the number of PCI device found on the primary bus of the PCI root bridge + // + NumberOfPciDevices++; + + // + // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header + // + if (PciConfigurationHeader.Hdr.Command & 0x20) { + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO; + } + + // + // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number + // + if (IS_PCI_BRIDGE(&PciConfigurationHeader)) { + // + // Get the Bus range that the PPB is decoding + // + if (PciConfigurationHeader.Bridge.P2PBridge.SubordinateBus > PrivateData->SubordinateBus) { + // + // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's + // current subordinate bus number, then update the PCI root bridge's subordinate bus number + // + PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.P2PBridge.SubordinateBus; + } + + // + // Get the I/O range that the PPB is decoding + // + Value = PciConfigurationHeader.Bridge.P2PBridge.IoBase & 0x0f; + Base = ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.IoBase & 0xf0) << 8; + Limit = (((UINT32)PciConfigurationHeader.Bridge.P2PBridge.IoLimit & 0xf0) << 8) | 0x0fff; + if (Value == 0x01) { + Base |= ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.IoBaseUpper16 << 16); + Limit |= ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.IoLimitUpper16 << 16); + } + if (Base < Limit) { + if (PrivateData->IoBase > Base) { + PrivateData->IoBase = Base; + } + if (PrivateData->IoLimit < Limit) { + PrivateData->IoLimit = Limit; + } + } + + // + // Get the Memory range that the PPB is decoding + // + Base = ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.MemoryBase & 0xfff0) << 16; + Limit = (((UINT32)PciConfigurationHeader.Bridge.P2PBridge.MemoryLimit & 0xfff0) << 16) | 0xfffff; + if (Base < Limit) { + if (PrivateData->MemBase > Base) { + PrivateData->MemBase = Base; + } + if (PrivateData->MemLimit < Limit) { + PrivateData->MemLimit = Limit; + } + if (PrivateData->Mem32Base > Base) { + PrivateData->Mem32Base = Base; + } + if (PrivateData->Mem32Limit < Limit) { + PrivateData->Mem32Limit = Limit; + } + } + + // + // Get the Prefetchable Memory range that the PPB is decoding + // + Value = PciConfigurationHeader.Bridge.P2PBridge.PrefetchableMemoryBase & 0x0f; + Base = ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.PrefetchableMemoryBase & 0xfff0) << 16; + Limit = (((UINT32)PciConfigurationHeader.Bridge.P2PBridge.PrefetchableMemoryLimit & 0xfff0) << 16) | 0xffffff; + if (Value == 0x01) { + Base |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.P2PBridge.PrefetchableBaseUpper32,32); + Limit |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.P2PBridge.PrefetchableLimitUpper32,32); + } + if (Base < Limit) { + if (PrivateData->MemBase > Base) { + PrivateData->MemBase = Base; + } + if (PrivateData->MemLimit < Limit) { + PrivateData->MemLimit = Limit; + } + if (Value == 0x00) { + if (PrivateData->Pmem32Base > Base) { + PrivateData->Pmem32Base = Base; + } + if (PrivateData->Pmem32Limit < Limit) { + PrivateData->Pmem32Limit = Limit; + } + } + if (Value == 0x01) { + if (PrivateData->Pmem64Base > Base) { + PrivateData->Pmem64Base = Base; + } + if (PrivateData->Pmem64Limit < Limit) { + PrivateData->Pmem64Limit = Limit; + } + } + } + + // + // Look at the PPB Configuration for legacy decoding attributes + // + if (PciConfigurationHeader.Bridge.P2PBridge.BridgeControl & 0x04) { + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO; + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO; + } + if (PciConfigurationHeader.Bridge.P2PBridge.BridgeControl & 0x08) { + // + // ** CHANGE ** + // We do not set EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO. + // + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY; + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO; + } + + } else if (IS_CARDBUS_BRIDGE (&PciConfigurationHeader)) { + // + // ** CHANGE START ** + // Added CardBridge support. + // + + // + // Get the Bus range that the PPB is decoding + // + if (PciConfigurationHeader.Bridge.CardBridge.SubordinateBusNumber > PrivateData->SubordinateBus) { + // + // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's + // current subordinate bus number, then update the PCI root bridge's subordinate bus number + // + PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.CardBridge.SubordinateBusNumber; + } + + // + // Get the I/O range that the PPB is decoding + // + Base = PciConfigurationHeader.Bridge.CardBridge.IoBase0; + Limit = PciConfigurationHeader.Bridge.CardBridge.IoLimit0; + if (Base < Limit) { + if (PrivateData->IoBase > Base) { + PrivateData->IoBase = Base; + } + if (PrivateData->IoLimit < Limit) { + PrivateData->IoLimit = Limit; + } + } + + // + // Get the Memory range that the PPB is decoding + // + Base = PciConfigurationHeader.Bridge.CardBridge.MemoryBase0; + Limit = PciConfigurationHeader.Bridge.CardBridge.MemoryLimit0; + if (Base < Limit) { + if (PrivateData->MemBase > Base) { + PrivateData->MemBase = Base; + } + if (PrivateData->MemLimit < Limit) { + PrivateData->MemLimit = Limit; + } + if (PrivateData->Mem32Base > Base) { + PrivateData->Mem32Base = Base; + } + if (PrivateData->Mem32Limit < Limit) { + PrivateData->Mem32Limit = Limit; + } + } + // + // ** CHANGE END ** + // + } else { + // + // Parse the BARs of the PCI device to determine what I/O Ranges, + // Memory Ranges, and Prefetchable Memory Ranges the device is decoding + // + if ((PciConfigurationHeader.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) { + Status = PcatPciRootBridgeParseBars ( + PrivateData, + PciConfigurationHeader.Hdr.Command, + PrimaryBusIndex, + Device, + Function + ); + } + + // + // See if the PCI device is an IDE controller + // + if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 && + PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) { + if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) { + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO; + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO; + } + if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) { + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO; + } + if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) { + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO; + } + } + + // + // See if the PCI device is a legacy VGA controller + // + if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 && + PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) { + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO; + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY; + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO; + } + + // + // See if the PCI device is a standard VGA controller + // + if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 && + PciConfigurationHeader.Hdr.ClassCode[1] == 0x00 ) { + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO; + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY; + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO; + } + + // + // See if the PCI Device is a PCI - ISA or PCI - EISA + // or ISA_POSITIVIE_DECODE Bridge device + // + if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x06) { + if (PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 || + PciConfigurationHeader.Hdr.ClassCode[1] == 0x02 || + PciConfigurationHeader.Hdr.ClassCode[1] == 0x80 ) { + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO; + PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO; + + if (PrivateData->MemBase > 0xa0000) { + PrivateData->MemBase = 0xa0000; + } + if (PrivateData->MemLimit < 0xbffff) { + PrivateData->MemLimit = 0xbffff; + } + } + } + } + + // + // If this device is not a multi function device, then skip the rest of this PCI device + // + if (Function == 0 && !(PciConfigurationHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) { + break; + } + } + } + + // + // After scanning all the PCI devices on the PCI root bridge's primary bus, update the + // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate + // bus number + 1. + // + PrimaryBusIndex = PrivateData->SubordinateBus + 1; + + // + // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge + // exists. + // + if (NumberOfPciDevices > 0) { + + // + // Adjust the I/O range used for bounds checking for the legacy decoding attributed + // + if (PrivateData->Attributes & 0x7f) { + PrivateData->IoBase = 0; + if (PrivateData->IoLimit < 0xffff) { + PrivateData->IoLimit = 0xffff; + } + } + + // + // Adjust the Memory range used for bounds checking for the legacy decoding attributed + // + if (PrivateData->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) { + if (PrivateData->MemBase > 0xa0000) { + PrivateData->MemBase = 0xa0000; + } + if (PrivateData->MemLimit < 0xbffff) { + PrivateData->MemLimit = 0xbffff; + } + } + + // + // Build ACPI descriptors for the resources on the PCI Root Bridge + // + Status = ConstructConfiguration(PrivateData); + ASSERT_EFI_ERROR (Status); + + // + // Create the handle for this PCI Root Bridge + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &PrivateData->Handle, + &gEfiDevicePathProtocolGuid, + PrivateData->DevicePath, + &gEfiPciRootBridgeIoProtocolGuid, + &PrivateData->Io, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Contruct DeviceIoProtocol + // + Status = DeviceIoConstructor ( + PrivateData->Handle, + &PrivateData->Io, + PrivateData->DevicePath, + (UINT16)PrivateData->PrimaryBus, + (UINT16)PrivateData->SubordinateBus + ); + ASSERT_EFI_ERROR (Status); + // + // ** CHANGE ** + // Option ROM support is removed. Patch by nms42. + // + // + // Increment the index for the next PCI Root Bridge + // + PciRootBridgeIndex++; + + } else { + + // + // If no PCI Root Bridges were found on the current PCI segment, then exit + // + if (NumberOfPciRootBridges == 0) { + Status = EFI_SUCCESS; + goto Done; + } + + } + + // + // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then + // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0 + // Otherwise, the search is continued on the next PCI Root Bridge + // + if (PrimaryBusIndex > PCI_MAX_BUS) { + PciSegmentIndex++; + NumberOfPciRootBridges = 0; + PrimaryBusIndex = 0; + } else { + NumberOfPciRootBridges++; + } + + } + + return EFI_SUCCESS; + +Done: + // + // Clean up memory allocated for the PCI Root Bridge that was searched but not created. + // + if (PrivateData) { + if (PrivateData->DevicePath) { + gBS->FreePool(PrivateData->DevicePath); + } + gBS->FreePool (PrivateData); + } + + // + // If no PCI Root Bridges were discovered, then return the error condition from scanning the + // first PCI Root Bridge + // + if (PciRootBridgeIndex == 0) { + return Status; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ConstructConfiguration( + IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ + +{ + EFI_STATUS Status; + UINT8 NumConfig; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration; + EFI_ACPI_END_TAG_DESCRIPTOR *ConfigurationEnd; + + NumConfig = 0; + PrivateData->Configuration = NULL; + + if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) { + NumConfig++; + } + if (PrivateData->IoLimit >= PrivateData->IoBase) { + NumConfig++; + } + if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) { + NumConfig++; + } + if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) { + NumConfig++; + } + if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) { + NumConfig++; + } + if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) { + NumConfig++; + } + + if ( NumConfig == 0 ) { + + // + // If there is no resource request + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR), + (VOID **)&PrivateData->Configuration + ); + if (EFI_ERROR (Status )) { + return Status; + } + + Configuration = PrivateData->Configuration; + + ZeroMem ( + Configuration, + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR) + ); + + Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); + Configuration++; + + ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration); + ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR; + ConfigurationEnd->Checksum = 0; + } + + // + // If there is at least one type of resource request, + // allocate a acpi resource node + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR), + (VOID **)&PrivateData->Configuration + ); + if (EFI_ERROR (Status )) { + return Status; + } + + Configuration = PrivateData->Configuration; + + ZeroMem ( + Configuration, + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR) + ); + + if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) { + Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); + Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS; + Configuration->SpecificFlag = 0; + Configuration->AddrRangeMin = PrivateData->PrimaryBus; + Configuration->AddrRangeMax = PrivateData->SubordinateBus; + Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1; + Configuration++; + } + // + // Deal with io aperture + // + if (PrivateData->IoLimit >= PrivateData->IoBase) { + Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); + Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_IO; + Configuration->SpecificFlag = 1; //non ISA range + Configuration->AddrRangeMin = PrivateData->IoBase; + Configuration->AddrRangeMax = PrivateData->IoLimit; + Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1; + Configuration++; + } + + // + // Deal with mem32 aperture + // + if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) { + Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); + Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + Configuration->SpecificFlag = 0; //Nonprefechable + Configuration->AddrSpaceGranularity = 32; //32 bit + Configuration->AddrRangeMin = PrivateData->Mem32Base; + Configuration->AddrRangeMax = PrivateData->Mem32Limit; + Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1; + Configuration++; + } + + // + // Deal with Pmem32 aperture + // + if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) { + Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); + Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + Configuration->SpecificFlag = 0x6; //prefechable + Configuration->AddrSpaceGranularity = 32; //32 bit + Configuration->AddrRangeMin = PrivateData->Pmem32Base; + Configuration->AddrRangeMax = PrivateData->Pmem32Limit; + Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1; + Configuration++; + } + + // + // Deal with mem64 aperture + // + if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) { + Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); + Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + Configuration->SpecificFlag = 0; //nonprefechable + Configuration->AddrSpaceGranularity = 64; //32 bit + Configuration->AddrRangeMin = PrivateData->Mem64Base; + Configuration->AddrRangeMax = PrivateData->Mem64Limit; + Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1; + Configuration++; + } + + // + // Deal with Pmem64 aperture + // + if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) { + Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); + Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + Configuration->SpecificFlag = 0x06; //prefechable + Configuration->AddrSpaceGranularity = 64; //32 bit + Configuration->AddrRangeMin = PrivateData->Pmem64Base; + Configuration->AddrRangeMax = PrivateData->Pmem64Limit; + Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1; + Configuration++; + } + + // + // put the checksum + // + ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration); + ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR; + ConfigurationEnd->Checksum = 0; + + return EFI_SUCCESS; +} + +EFI_STATUS +PcatPciRootBridgeBarExisted ( + IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData, + IN UINT64 Address, + OUT UINT32 *OriginalValue, + OUT UINT32 *Value + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + UINT32 AllOnes; + EFI_TPL OldTpl; + + // + // Preserve the original value + // + PrivateData->Io.Pci.Read ( + &PrivateData->Io, + EfiPciWidthUint32, + Address, + 1, + OriginalValue + ); + + // + // Raise TPL to high level to disable timer interrupt while the BAR is probed + // + OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + AllOnes = 0xffffffff; + + PrivateData->Io.Pci.Write ( + &PrivateData->Io, + EfiPciWidthUint32, + Address, + 1, + &AllOnes + ); + PrivateData->Io.Pci.Read ( + &PrivateData->Io, + EfiPciWidthUint32, + Address, + 1, + Value + ); + + // + //Write back the original value + // + PrivateData->Io.Pci.Write ( + &PrivateData->Io, + EfiPciWidthUint32, + Address, + 1, + OriginalValue + ); + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if ( *Value == 0 ) { + return EFI_DEVICE_ERROR; + } + return EFI_SUCCESS; +} + +EFI_STATUS +PcatPciRootBridgeParseBars ( + IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData, + IN UINT16 Command, + IN UINTN Bus, + IN UINTN Device, + IN UINTN Function + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + UINT64 Address; + UINT32 OriginalValue; + UINT32 Value; + UINT32 OriginalUpperValue; + UINT32 UpperValue; + UINT64 Mask; + UINTN Offset; + UINT64 Base; + UINT64 Length; + UINT64 Limit; + + for (Offset = 0x10; Offset < 0x28; Offset += 4) { + Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset); + Status = PcatPciRootBridgeBarExisted ( + PrivateData, + Address, + &OriginalValue, + &Value + ); + + if (!EFI_ERROR (Status )) { + if ( Value & 0x01 ) { + if (Command & 0x0001) { + // + //Device I/Os + // + Mask = 0xfffffffc; + Base = OriginalValue & Mask; + Length = ((~(Value & Mask)) & Mask) + 0x04; + if (!(Value & 0xFFFF0000)){ + Length &= 0x0000FFFF; + } + Limit = Base + Length - 1; + + if (Base < Limit) { + if (PrivateData->IoBase > Base) { + PrivateData->IoBase = (UINT32)Base; + } + if (PrivateData->IoLimit < Limit) { + PrivateData->IoLimit = (UINT32)Limit; + } + } + } + + } else { + + if (Command & 0x0002) { + + Mask = 0xfffffff0; + Base = OriginalValue & Mask; + Length = Value & Mask; + + if ((Value & 0x07) != 0x04) { + Length = ((~Length) + 1) & 0xffffffff; + } else { + Offset += 4; + Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset); + + Status = PcatPciRootBridgeBarExisted ( + PrivateData, + Address, + &OriginalUpperValue, + &UpperValue + ); + + Base = Base | LShiftU64((UINT64)OriginalUpperValue,32); + Length = Length | LShiftU64((UINT64)UpperValue,32); + Length = (~Length) + 1; + } + + Limit = Base + Length - 1; + + if (Base < Limit) { + if (PrivateData->MemBase > Base) { + PrivateData->MemBase = Base; + } + if (PrivateData->MemLimit < Limit) { + PrivateData->MemLimit = Limit; + } + + switch (Value &0x07) { + case 0x00: ////memory space; anywhere in 32 bit address space + if (Value & 0x08) { + if (PrivateData->Pmem32Base > Base) { + PrivateData->Pmem32Base = Base; + } + if (PrivateData->Pmem32Limit < Limit) { + PrivateData->Pmem32Limit = Limit; + } + } else { + if (PrivateData->Mem32Base > Base) { + PrivateData->Mem32Base = Base; + } + if (PrivateData->Mem32Limit < Limit) { + PrivateData->Mem32Limit = Limit; + } + } + break; + case 0x04: //memory space; anywhere in 64 bit address space + if (Value & 0x08) { + if (PrivateData->Pmem64Base > Base) { + PrivateData->Pmem64Base = Base; + } + if (PrivateData->Pmem64Limit < Limit) { + PrivateData->Pmem64Limit = Limit; + } + } else { + if (PrivateData->Mem64Base > Base) { + PrivateData->Mem64Base = Base; + } + if (PrivateData->Mem64Limit < Limit) { + PrivateData->Mem64Limit = Limit; + } + } + break; + } + } + } + } + } + } + return EFI_SUCCESS; +} + +UINT64 +GetPciExpressBaseAddressForRootBridge ( + IN UINTN HostBridgeNumber, + IN UINTN RootBridgeNumber + ) +/*++ + +Routine Description: + This routine is to get PciExpress Base Address for this RootBridge + +Arguments: + HostBridgeNumber - The number of HostBridge + RootBridgeNumber - The number of RootBridge + +Returns: + UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge + +--*/ +{ + EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo; + UINTN BufferSize; + UINT32 Index; + UINT32 Number; + EFI_PEI_HOB_POINTERS GuidHob; + + // + // Get PciExpressAddressInfo Hob + // + PciExpressBaseAddressInfo = NULL; + BufferSize = 0; + GuidHob.Raw = GetFirstGuidHob (&gEfiPciExpressBaseAddressGuid); + if (GuidHob.Raw != NULL) { + PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid); + BufferSize = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid); + } else { + return 0; + } + + // + // Search the PciExpress Base Address in the Hob for current RootBridge + // + Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION)); + for (Index = 0; Index < Number; Index++) { + if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) && + (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) { + return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress; + } + } + + // + // Do not find the PciExpress Base Address in the Hob + // + return 0; +} + diff --git a/Legacy/BootPlatform/PciRootBridgeDxe/PcatPciRootBridge.h b/Legacy/BootPlatform/PciRootBridgeDxe/PcatPciRootBridge.h new file mode 100644 index 0000000000000000000000000000000000000000..970b8dba47048bb422fa52092f9f47f498dfeacb --- /dev/null +++ b/Legacy/BootPlatform/PciRootBridgeDxe/PcatPciRootBridge.h @@ -0,0 +1,239 @@ +/*++ + +Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + PcatPciRootBridge.h + +Abstract: + + The driver for the host to pci bridge (root bridge). + +--*/ + +#ifndef _PCAT_PCI_ROOT_BRIDGE_H_ +#define _PCAT_PCI_ROOT_BRIDGE_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define PCI_MAX_SEGMENT 0 +// +// Driver Instance Data Prototypes +// +#define PCAT_PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32('p', 'c', 'r', 'b') + +typedef struct { + UINT32 Signature; + EFI_HANDLE Handle; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io; + EFI_CPU_IO2_PROTOCOL *CpuIo; + + UINT32 RootBridgeNumber; + UINT32 PrimaryBus; + UINT32 SubordinateBus; + + UINT64 MemBase; // Offsets host to bus memory addr. + UINT64 MemLimit; // Max allowable memory access + + UINT64 IoBase; // Offsets host to bus io addr. + UINT64 IoLimit; // Max allowable io access + + UINT64 PciAddress; + UINT64 PciData; + + UINT64 PhysicalMemoryBase; + UINT64 PhysicalIoBase; + + EFI_LOCK PciLock; + + UINT64 Attributes; + + UINT64 Mem32Base; + UINT64 Mem32Limit; + UINT64 Pmem32Base; + UINT64 Pmem32Limit; + UINT64 Mem64Base; + UINT64 Mem64Limit; + UINT64 Pmem64Base; + UINT64 Pmem64Limit; + + UINT64 PciExpressBaseAddress; + + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration; + + LIST_ENTRY MapInfo; +} PCAT_PCI_ROOT_BRIDGE_INSTANCE; + +// +// Driver Instance Data Macros +// +#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) \ + CR(a, PCAT_PCI_ROOT_BRIDGE_INSTANCE, Io, PCAT_PCI_ROOT_BRIDGE_SIGNATURE) + +// +// Private data types +// +typedef union { + UINT8 volatile *buf; + UINT8 volatile *ui8; + UINT16 volatile *ui16; + UINT32 volatile *ui32; + UINT64 volatile *ui64; + UINTN volatile ui; +} PTR; + +typedef struct { + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation; + UINTN NumberOfBytes; + UINTN NumberOfPages; + EFI_PHYSICAL_ADDRESS HostAddress; + EFI_PHYSICAL_ADDRESS MappedHostAddress; +} MAP_INFO; + +typedef struct { + LIST_ENTRY Link; + MAP_INFO * Map; +} MAP_INFO_INSTANCE; + +typedef +VOID +(*EFI_PCI_BUS_SCAN_CALLBACK) ( + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev, + UINT16 MinBus, + UINT16 MaxBus, + UINT16 MinDevice, + UINT16 MaxDevice, + UINT16 MinFunc, + UINT16 MaxFunc, + UINT16 Bus, + UINT16 Device, + UINT16 Func, + IN VOID *Context + ); + +typedef struct { + UINT16 *CommandRegisterBuffer; + UINT32 PpbMemoryWindow; +} PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT; + +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT8 Reserved[4]; +} DEFIO_PCI_ADDR; + +// +// Driver Protocol Constructor Prototypes +// +EFI_STATUS +ConstructConfiguration( + IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData + ); + +EFI_STATUS +PcatPciRootBridgeParseBars ( + IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData, + IN UINT16 Command, + IN UINTN Bus, + IN UINTN Device, + IN UINTN Function + ); + +EFI_STATUS +PcatRootBridgeDevicePathConstructor ( + IN EFI_DEVICE_PATH_PROTOCOL **Protocol, + IN UINTN RootBridgeNumber, + IN BOOLEAN IsPciExpress + ); + +EFI_STATUS +PcatRootBridgeIoConstructor ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol, + IN UINTN SegmentNumber + ); + +EFI_STATUS +PcatRootBridgeIoGetIoPortMapping ( + OUT EFI_PHYSICAL_ADDRESS *IoPortMapping, + OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping + ); + +EFI_STATUS +PcatRootBridgeIoPciRW ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN BOOLEAN Write, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + IN OUT VOID *UserBuffer + ); + +UINT64 +GetPciExpressBaseAddressForRootBridge ( + IN UINTN HostBridgeNumber, + IN UINTN RootBridgeNumber + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoIoRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + IN OUT VOID *UserBuffer + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoIoWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + IN OUT VOID *UserBuffer + ); + +// +// Driver entry point prototype +// +EFI_STATUS +EFIAPI +InitializePcatPciRootBridge ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +extern EFI_CPU_IO2_PROTOCOL *gCpuIo; + +#endif diff --git a/Legacy/BootPlatform/PciRootBridgeDxe/PcatPciRootBridgeDevicePath.c b/Legacy/BootPlatform/PciRootBridgeDxe/PcatPciRootBridgeDevicePath.c new file mode 100644 index 0000000000000000000000000000000000000000..cc30967558c90e1efa7bfd611fcf7ba8336fbac9 --- /dev/null +++ b/Legacy/BootPlatform/PciRootBridgeDxe/PcatPciRootBridgeDevicePath.c @@ -0,0 +1,100 @@ +/*++ + +Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + PcatPciRootBridgeDevicePath.c + +Abstract: + + EFI PCAT PCI Root Bridge Device Path Protocol + +Revision History + +--*/ + +#include "PcatPciRootBridge.h" + +// +// Static device path declarations for this driver. +// + +typedef struct { + ACPI_HID_DEVICE_PATH AcpiDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH; + +EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = { + { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)), + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8), + } + }, + EISA_PNP_ID(0x0A03), + 0 + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +EFI_STATUS +PcatRootBridgeDevicePathConstructor ( + IN EFI_DEVICE_PATH_PROTOCOL **Protocol, + IN UINTN RootBridgeNumber, + IN BOOLEAN IsPciExpress + ) +/*++ + +Routine Description: + + Construct the device path protocol + +Arguments: + + Protocol - protocol to initialize + +Returns: + + None + +--*/ +{ + ACPI_HID_DEVICE_PATH *AcpiDevicePath; + + *Protocol = DuplicateDevicePath((EFI_DEVICE_PATH_PROTOCOL *)(&mEfiPciRootBridgeDevicePath)); + + AcpiDevicePath = (ACPI_HID_DEVICE_PATH *)(*Protocol); + + AcpiDevicePath->UID = (UINT32)RootBridgeNumber; + + if (IsPciExpress) { + // + // ** CHANGE START ** + // Force general PCI as normal firmwares and macOS do. + // + // AcpiDevicePath->HID = EISA_PNP_ID (0x0A08); + // + // ** CHANGE END ** + // + } + + return EFI_SUCCESS; +} + diff --git a/Legacy/BootPlatform/PciRootBridgeDxe/PcatPciRootBridgeIo.c b/Legacy/BootPlatform/PciRootBridgeDxe/PcatPciRootBridgeIo.c new file mode 100644 index 0000000000000000000000000000000000000000..a3ee4782e59f6d5a850ccadb9882ef7ee42701ec --- /dev/null +++ b/Legacy/BootPlatform/PciRootBridgeDxe/PcatPciRootBridgeIo.c @@ -0,0 +1,1036 @@ +/*++ + +Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + PcatPciRootBridgeIo.c + +Abstract: + + EFI PC AT PCI Root Bridge Io Protocol + +Revision History + +--*/ + +#include "PcatPciRootBridge.h" + +// +// Protocol Member Function Prototypes +// +EFI_STATUS +EFIAPI +PcatRootBridgeIoPollMem ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoPollIo ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoMemRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoMemWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoCopyMem ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 DestAddress, + IN UINT64 SrcAddress, + IN UINTN Count + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoPciRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoPciWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoMap ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoUnmap ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoAllocateBuffer ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoFreeBuffer ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINTN Pages, + OUT VOID *HostAddress + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoFlush ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoGetAttributes ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT UINT64 *Supported, + OUT UINT64 *Attributes + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoSetAttributes ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN OUT UINT64 *ResourceBase, + IN OUT UINT64 *ResourceLength + ); + +EFI_STATUS +EFIAPI +PcatRootBridgeIoConfiguration ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT VOID **Resources + ); + +// +// Private Function Prototypes +// +EFI_STATUS +EFIAPI +PcatRootBridgeIoMemRW ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN BOOLEAN InStrideFlag, + IN PTR In, + IN BOOLEAN OutStrideFlag, + OUT PTR Out + ); + +EFI_STATUS +PcatRootBridgeIoConstructor ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol, + IN UINTN SegmentNumber + ) +/*++ + +Routine Description: + + Contruct the Pci Root Bridge Io protocol + +Arguments: + + Protocol - protocol to initialize + +Returns: + + None + +--*/ +{ + Protocol->ParentHandle = NULL; + + Protocol->PollMem = PcatRootBridgeIoPollMem; + Protocol->PollIo = PcatRootBridgeIoPollIo; + + Protocol->Mem.Read = PcatRootBridgeIoMemRead; + Protocol->Mem.Write = PcatRootBridgeIoMemWrite; + + Protocol->Io.Read = PcatRootBridgeIoIoRead; + Protocol->Io.Write = PcatRootBridgeIoIoWrite; + + Protocol->CopyMem = PcatRootBridgeIoCopyMem; + + Protocol->Pci.Read = PcatRootBridgeIoPciRead; + Protocol->Pci.Write = PcatRootBridgeIoPciWrite; + + Protocol->Map = PcatRootBridgeIoMap; + Protocol->Unmap = PcatRootBridgeIoUnmap; + + Protocol->AllocateBuffer = PcatRootBridgeIoAllocateBuffer; + Protocol->FreeBuffer = PcatRootBridgeIoFreeBuffer; + + Protocol->Flush = PcatRootBridgeIoFlush; + + Protocol->GetAttributes = PcatRootBridgeIoGetAttributes; + Protocol->SetAttributes = PcatRootBridgeIoSetAttributes; + + Protocol->Configuration = PcatRootBridgeIoConfiguration; + + Protocol->SegmentNumber = (UINT32)SegmentNumber; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoPollMem ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +{ + EFI_STATUS Status; + UINT64 NumberOfTicks; + UINT32 Remainder; + + if (Result == NULL) { + return EFI_INVALID_PARAMETER; + } + + + if ((UINT32)Width > EfiPciWidthUint64) { + return EFI_INVALID_PARAMETER; + } + // + // No matter what, always do a single poll. + // + Status = This->Mem.Read (This, Width, Address, 1, Result); + if ( EFI_ERROR(Status) ) { + return Status; + } + if ( (*Result & Mask) == Value ) { + return EFI_SUCCESS; + } + + if (Delay == 0) { + return EFI_SUCCESS; + } else { + + NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder); + if ( Remainder !=0 ) { + NumberOfTicks += 1; + } + NumberOfTicks += 1; + + while ( NumberOfTicks ) { + + gBS->Stall (10); + + Status = This->Mem.Read (This, Width, Address, 1, Result); + if ( EFI_ERROR(Status) ) { + return Status; + } + + if ( (*Result & Mask) == Value ) { + return EFI_SUCCESS; + } + + NumberOfTicks -= 1; + } + } + return EFI_TIMEOUT; +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoPollIo ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +{ + EFI_STATUS Status; + UINT64 NumberOfTicks; + UINT32 Remainder; + + if (Result == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((UINT32)Width > EfiPciWidthUint64) { + return EFI_INVALID_PARAMETER; + } + // + // No matter what, always do a single poll. + // + Status = This->Io.Read (This, Width, Address, 1, Result); + if ( EFI_ERROR(Status) ) { + return Status; + } + if ( (*Result & Mask) == Value ) { + return EFI_SUCCESS; + } + + if (Delay == 0) { + return EFI_SUCCESS; + } else { + + NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder); + if ( Remainder !=0 ) { + NumberOfTicks += 1; + } + NumberOfTicks += 1; + + while ( NumberOfTicks ) { + + gBS->Stall(10); + + Status = This->Io.Read (This, Width, Address, 1, Result); + if ( EFI_ERROR(Status) ) { + return Status; + } + + if ( (*Result & Mask) == Value ) { + return EFI_SUCCESS; + } + + NumberOfTicks -= 1; + } + } + return EFI_TIMEOUT; +} + +BOOLEAN +PcatRootBridgeMemAddressValid ( + IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData, + IN UINT64 Address + ) +{ + if ((Address >= PrivateData->PciExpressBaseAddress) && (Address < PrivateData->PciExpressBaseAddress + 0x10000000)) { + return TRUE; + } + if ((Address >= PrivateData->MemBase) && (Address < PrivateData->MemLimit)) { + return TRUE; + } + + return FALSE; +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoMemRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + UINTN AlignMask; + PTR In; + PTR Out; + + if ( Buffer == NULL ) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); + + if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) { + return EFI_INVALID_PARAMETER; + } + + AlignMask = (1 << (Width & 0x03)) - 1; + if (Address & AlignMask) { + return EFI_INVALID_PARAMETER; + } + + Address += PrivateData->PhysicalMemoryBase; + + In.buf = Buffer; + Out.buf = (VOID *)(UINTN) Address; + if ((UINT32)Width <= EfiPciWidthUint64) { + return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out); + } + if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) { + return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out); + } + if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) { + return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out); + } + + return EFI_INVALID_PARAMETER; +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoMemWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + UINTN AlignMask; + PTR In; + PTR Out; + + if ( Buffer == NULL ) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); + + if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) { + return EFI_INVALID_PARAMETER; + } + + AlignMask = (1 << (Width & 0x03)) - 1; + if (Address & AlignMask) { + return EFI_INVALID_PARAMETER; + } + + Address += PrivateData->PhysicalMemoryBase; + + In.buf = (VOID *)(UINTN) Address; + Out.buf = Buffer; + if ((UINT32)Width <= EfiPciWidthUint64) { + return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out); + } + if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) { + return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out); + } + if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) { + return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out); + } + + return EFI_INVALID_PARAMETER; +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoCopyMem ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 DestAddress, + IN UINT64 SrcAddress, + IN UINTN Count + ) + +{ + EFI_STATUS Status; + BOOLEAN Direction; + UINTN Stride; + UINTN Index; + UINT64 Result; + + if ((UINT32)Width > EfiPciWidthUint64) { + return EFI_INVALID_PARAMETER; + } + + if (DestAddress == SrcAddress) { + return EFI_SUCCESS; + } + + Stride = (UINTN)1 << Width; + + Direction = TRUE; + if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) { + Direction = FALSE; + SrcAddress = SrcAddress + (Count-1) * Stride; + DestAddress = DestAddress + (Count-1) * Stride; + } + + for (Index = 0;Index < Count;Index++) { + Status = PcatRootBridgeIoMemRead ( + This, + Width, + SrcAddress, + 1, + &Result + ); + if (EFI_ERROR (Status)) { + return Status; + } + Status = PcatRootBridgeIoMemWrite ( + This, + Width, + DestAddress, + 1, + &Result + ); + if (EFI_ERROR (Status)) { + return Status; + } + if (Direction) { + SrcAddress += Stride; + DestAddress += Stride; + } else { + SrcAddress -= Stride; + DestAddress -= Stride; + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoPciRead ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + return PcatRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer); +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoPciWrite ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + return PcatRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer); +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoMap ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) + +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + MAP_INFO *MapInfo; + MAP_INFO_INSTANCE *MapInstance; + PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + + if ( HostAddress == NULL || NumberOfBytes == NULL || + DeviceAddress == NULL || Mapping == NULL ) { + + return EFI_INVALID_PARAMETER; + } + + // + // Perform a fence operation to make sure all memory operations are flushed + // + MemoryFence(); + + // + // Initialize the return values to their defaults + // + *Mapping = NULL; + + // + // Make sure that Operation is valid + // + if ((UINT32)Operation >= EfiPciOperationMaximum) { + return EFI_INVALID_PARAMETER; + } + + // + // Most PCAT like chipsets can not handle performing DMA above 4GB. + // If any part of the DMA transfer being mapped is above 4GB, then + // map the DMA transfer to a buffer below 4GB. + // + PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; + if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) { + + // + // Common Buffer operations can not be remapped. If the common buffer + // if above 4GB, then it is not possible to generate a mapping, so return + // an error. + // + if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) { + return EFI_UNSUPPORTED; + } + + // + // Allocate a MAP_INFO structure to remember the mapping when Unmap() is + // called later. + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof(MAP_INFO), + (VOID **)&MapInfo + ); + if (EFI_ERROR (Status)) { + *NumberOfBytes = 0; + return Status; + } + + // + // Return a pointer to the MAP_INFO structure in Mapping + // + *Mapping = MapInfo; + + // + // Initialize the MAP_INFO structure + // + MapInfo->Operation = Operation; + MapInfo->NumberOfBytes = *NumberOfBytes; + MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES(*NumberOfBytes); + MapInfo->HostAddress = PhysicalAddress; + MapInfo->MappedHostAddress = 0x00000000ffffffff; + + // + // Allocate a buffer below 4GB to map the transfer to. + // + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + MapInfo->NumberOfPages, + &MapInfo->MappedHostAddress + ); + if (EFI_ERROR(Status)) { + gBS->FreePool (MapInfo); + *NumberOfBytes = 0; + return Status; + } + + // + // If this is a read operation from the Bus Master's point of view, + // then copy the contents of the real buffer into the mapped buffer + // so the Bus Master can read the contents of the real buffer. + // + if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) { + CopyMem ( + (VOID *)(UINTN)MapInfo->MappedHostAddress, + (VOID *)(UINTN)MapInfo->HostAddress, + MapInfo->NumberOfBytes + ); + } + + + Status =gBS->AllocatePool ( + EfiBootServicesData, + sizeof(MAP_INFO_INSTANCE), + (VOID **)&MapInstance + ); + if (EFI_ERROR(Status)) { + gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages); + gBS->FreePool (MapInfo); + *NumberOfBytes = 0; + return Status; + } + + MapInstance->Map=MapInfo; + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); + InsertTailList(&PrivateData->MapInfo,&MapInstance->Link); + + // + // The DeviceAddress is the address of the maped buffer below 4GB + // + *DeviceAddress = MapInfo->MappedHostAddress; + } else { + // + // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress + // + *DeviceAddress = PhysicalAddress; + } + + // + // Perform a fence operation to make sure all memory operations are flushed + // + MemoryFence(); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoUnmap ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN VOID *Mapping + ) + +{ + MAP_INFO *MapInfo; + PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + LIST_ENTRY *Link; + + // + // Perform a fence operation to make sure all memory operations are flushed + // + MemoryFence(); + + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); + // + // See if the Map() operation associated with this Unmap() required a mapping buffer. + // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS. + // + if (Mapping != NULL) { + // + // Get the MAP_INFO structure from Mapping + // + MapInfo = (MAP_INFO *)Mapping; + + for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) { + if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo) + break; + } + + if (Link == &PrivateData->MapInfo) { + return EFI_INVALID_PARAMETER; + } + + RemoveEntryList(Link); + ((MAP_INFO_INSTANCE*)Link)->Map = NULL; + gBS->FreePool((MAP_INFO_INSTANCE*)Link); + + // + // If this is a write operation from the Bus Master's point of view, + // then copy the contents of the mapped buffer into the real buffer + // so the processor can read the contents of the real buffer. + // + if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) { + CopyMem ( + (VOID *)(UINTN)MapInfo->HostAddress, + (VOID *)(UINTN)MapInfo->MappedHostAddress, + MapInfo->NumberOfBytes + ); + } + + // + // Free the mapped buffer and the MAP_INFO structure. + // + gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages); + gBS->FreePool (Mapping); + } + + // + // Perform a fence operation to make sure all memory operations are flushed + // + MemoryFence(); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoAllocateBuffer ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + + // + // Validate Attributes + // + if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) { + return EFI_UNSUPPORTED; + } + + // + // Check for invalid inputs + // + if (HostAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData + // + if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) { + return EFI_INVALID_PARAMETER; + } + + // + // Limit allocations to memory below 4GB + // + PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff); + + Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress); + if (EFI_ERROR (Status)) { + return Status; + } + + *HostAddress = (VOID *)(UINTN)PhysicalAddress; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoFreeBuffer ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINTN Pages, + OUT VOID *HostAddress + ) + +{ + + if( HostAddress == NULL ){ + return EFI_INVALID_PARAMETER; + } + return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages); +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoFlush ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This + ) + +{ + // + // Perform a fence operation to make sure all memory operations are flushed + // + MemoryFence(); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoGetAttributes ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT UINT64 *Supported, OPTIONAL + OUT UINT64 *Attributes + ) + +{ + PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); + + if (Attributes == NULL && Supported == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Supported is an OPTIONAL parameter. See if it is NULL + // + if (Supported) { + // + // This is a generic driver for a PC-AT class system. It does not have any + // chipset specific knowlegde, so none of the attributes can be set or + // cleared. Any attempt to set attribute that are already set will succeed, + // and any attempt to set an attribute that is not supported will fail. + // + *Supported = PrivateData->Attributes; + } + + // + // Set Attrbutes to the attributes detected when the PCI Root Bridge was initialized + // + + if (Attributes) { + *Attributes = PrivateData->Attributes; + } + + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoSetAttributes ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN OUT UINT64 *ResourceBase, + IN OUT UINT64 *ResourceLength + ) + +{ + PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); + + // + // This is a generic driver for a PC-AT class system. It does not have any + // chipset specific knowlegde, so none of the attributes can be set or + // cleared. Any attempt to set attribute that are already set will succeed, + // and any attempt to set an attribute that is not supported will fail. + // + if (Attributes & (~PrivateData->Attributes)) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcatRootBridgeIoConfiguration ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT VOID **Resources + ) + +{ + PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; + + PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); + + *Resources = PrivateData->Configuration; + + return EFI_SUCCESS; +} + +// +// Internal function +// + +EFI_STATUS +EFIAPI +PcatRootBridgeIoMemRW ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN BOOLEAN InStrideFlag, + IN PTR In, + IN BOOLEAN OutStrideFlag, + OUT PTR Out + ) +/*++ + +Routine Description: + + Private service to provide the memory read/write + +Arguments: + + Width of the Memory Access + Count of the number of accesses to perform + +Returns: + + Status + + EFI_SUCCESS - Successful transaction + EFI_INVALID_PARAMETER - Unsupported width and address combination + +--*/ +{ + UINTN Stride; + UINTN InStride; + UINTN OutStride; + + + Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03); + Stride = (UINTN)1 << Width; + InStride = InStrideFlag ? Stride : 0; + OutStride = OutStrideFlag ? Stride : 0; + + // + // Loop for each iteration and move the data + // + switch (Width) { + case EfiPciWidthUint8: + for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { + MemoryFence(); + *In.ui8 = *Out.ui8; + MemoryFence(); + } + break; + case EfiPciWidthUint16: + for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { + MemoryFence(); + *In.ui16 = *Out.ui16; + MemoryFence(); + } + break; + case EfiPciWidthUint32: + for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) { + MemoryFence(); + *In.ui32 = *Out.ui32; + MemoryFence(); + } + break; + default: + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + diff --git a/Legacy/BootPlatform/PciRootBridgeDxe/PciRootBridgeNoEnumeration.inf b/Legacy/BootPlatform/PciRootBridgeDxe/PciRootBridgeNoEnumeration.inf new file mode 100644 index 0000000000000000000000000000000000000000..700dab6d770e463efab615cfdd74278c8c52c5a3 --- /dev/null +++ b/Legacy/BootPlatform/PciRootBridgeDxe/PciRootBridgeNoEnumeration.inf @@ -0,0 +1,62 @@ +## @file +# +# Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Abstract: +# +## + + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PcatPciRootBridge + FILE_GUID = 0F7EC77A-1EE1-400f-A99D-7CBD1FEB181E + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = InitializePcatPciRootBridge + +[Packages] + MdePkg/MdePkg.dec + OpenCorePkg/OpenDuetPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiLib + MemoryAllocationLib + UefiBootServicesTableLib + DebugLib + BaseMemoryLib + DevicePathLib + HobLib + +[Sources] + PcatPciRootBridge.h + PcatPciRootBridge.c + PcatPciRootBridgeDevicePath.c + PcatPciRootBridgeIo.c + DeviceIo.h + DeviceIo.c + PcatIo.c + +[Protocols] + gEfiPciRootBridgeIoProtocolGuid + gEfiDeviceIoProtocolGuid + gEfiCpuIo2ProtocolGuid + +[Guids] + gEfiPciOptionRomTableGuid + gEfiPciExpressBaseAddressGuid + +[Depex] + gEfiCpuIo2ProtocolGuid + diff --git a/Legacy/BootPlatform/SmbiosGenDxe/SmbiosGen.c b/Legacy/BootPlatform/SmbiosGenDxe/SmbiosGen.c new file mode 100644 index 0000000000000000000000000000000000000000..0d03160b92a279189b37f7e8801680c92a1e6855 --- /dev/null +++ b/Legacy/BootPlatform/SmbiosGenDxe/SmbiosGen.c @@ -0,0 +1,330 @@ +/** @file + +Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + SmbiosGen.c + +Abstract: + +**/ + +#include "SmbiosGen.h" +extern UINT8 SmbiosGenDxeStrings[]; +EFI_SMBIOS_PROTOCOL *gSmbios; +EFI_HII_HANDLE gStringHandle; + +VOID * +GetSmbiosTablesFromHob ( + VOID + ) +{ + EFI_PHYSICAL_ADDRESS *Table; + EFI_PEI_HOB_POINTERS GuidHob; + + GuidHob.Raw = GetFirstGuidHob (&gEfiSmbiosTableGuid); + if (GuidHob.Raw != NULL) { + Table = GET_GUID_HOB_DATA (GuidHob.Guid); + if (Table != NULL) { + return (VOID *)(UINTN)*Table; + } + } + + return NULL; +} + + +VOID +InstallProcessorSmbios ( + IN VOID *Smbios + ) +{ + SMBIOS_STRUCTURE_POINTER SmbiosTable; + CHAR8 *AString; + CHAR16 *UString; + EFI_STRING_ID Token; + + // + // Processor info (TYPE 4) + // + SmbiosTable = GetSmbiosTableFromType ((SMBIOS_TABLE_ENTRY_POINT *)Smbios, 4, 0); + if (SmbiosTable.Raw == NULL) { + DEBUG ((EFI_D_ERROR, "SmbiosTable: Type 4 (Processor Info) not found!\n")); + return ; + } + + // + // Log Smbios Record Type4 + // + LogSmbiosData(gSmbios,(UINT8*)SmbiosTable.Type4); + + // + // Set ProcessorVersion string + // + AString = GetSmbiosString (SmbiosTable, SmbiosTable.Type4->ProcessorVersion); + UString = AllocateZeroPool ((AsciiStrLen(AString) + 1) * sizeof(CHAR16)); + ASSERT (UString != NULL); + AsciiStrToUnicodeStr (AString, UString); + + Token = HiiSetString (gStringHandle, 0, UString, NULL); + if (Token == 0) { + gBS->FreePool (UString); + return ; + } + gBS->FreePool (UString); + return ; +} + +VOID +InstallCacheSmbios ( + IN VOID *Smbios + ) +{ + return ; +} + +VOID +InstallMemorySmbios ( + IN VOID *Smbios + ) +{ + SMBIOS_STRUCTURE_POINTER SmbiosTable; + + // + // Generate Memory Array Mapped Address info (TYPE 19) + // + SmbiosTable = GetSmbiosTableFromType ((SMBIOS_TABLE_ENTRY_POINT *)Smbios, 19, 0); + if (SmbiosTable.Raw == NULL) { + DEBUG ((EFI_D_ERROR, "SmbiosTable: Type 19 (Memory Array Mapped Address Info) not found!\n")); + return ; + } + + // + // Record Smbios Type 19 + // + LogSmbiosData(gSmbios, (UINT8*)SmbiosTable.Type19); + return ; +} + +VOID +InstallMiscSmbios ( + IN VOID *Smbios + ) +{ + SMBIOS_STRUCTURE_POINTER SmbiosTable; + CHAR8 *AString; + CHAR16 *UString; + EFI_STRING_ID Token; + + // + // BIOS information (TYPE 0) + // + SmbiosTable = GetSmbiosTableFromType ((SMBIOS_TABLE_ENTRY_POINT *)Smbios, 0, 0); + if (SmbiosTable.Raw == NULL) { + DEBUG ((EFI_D_ERROR, "SmbiosTable: Type 0 (BIOS Information) not found!\n")); + return ; + } + + // + // Record Type 2 + // + AString = GetSmbiosString (SmbiosTable, SmbiosTable.Type0->BiosVersion); + UString = AllocateZeroPool ((AsciiStrLen(AString) + 1) * sizeof(CHAR16) + sizeof(FIRMWARE_BIOS_VERSIONE)); + ASSERT (UString != NULL); + CopyMem (UString, FIRMWARE_BIOS_VERSIONE, sizeof(FIRMWARE_BIOS_VERSIONE)); + AsciiStrToUnicodeStr (AString, UString + sizeof(FIRMWARE_BIOS_VERSIONE) / sizeof(CHAR16) - 1); + + Token = HiiSetString (gStringHandle, 0, UString, NULL); + if (Token == 0) { + gBS->FreePool (UString); + return ; + } + gBS->FreePool (UString); + + // + // Log Smios Type 0 + // + LogSmbiosData(gSmbios, (UINT8*)SmbiosTable.Type0); + + // + // System information (TYPE 1) + // + SmbiosTable = GetSmbiosTableFromType ((SMBIOS_TABLE_ENTRY_POINT *)Smbios, 1, 0); + if (SmbiosTable.Raw == NULL) { + DEBUG ((EFI_D_ERROR, "SmbiosTable: Type 1 (System Information) not found!\n")); + return ; + } + + // + // Record Type 3 + // + AString = GetSmbiosString (SmbiosTable, SmbiosTable.Type1->ProductName); + UString = AllocateZeroPool ((AsciiStrLen(AString) + 1) * sizeof(CHAR16) + sizeof(FIRMWARE_PRODUCT_NAME)); + ASSERT (UString != NULL); + CopyMem (UString, FIRMWARE_PRODUCT_NAME, sizeof(FIRMWARE_PRODUCT_NAME)); + AsciiStrToUnicodeStr (AString, UString + sizeof(FIRMWARE_PRODUCT_NAME) / sizeof(CHAR16) - 1); + + Token = HiiSetString (gStringHandle, 0, UString, NULL); + if (Token == 0) { + gBS->FreePool (UString); + return ; + } + gBS->FreePool (UString); + + // + // Log Smbios Type 1 + // + LogSmbiosData(gSmbios, (UINT8*)SmbiosTable.Type1); + + return ; +} + +EFI_STATUS +EFIAPI +SmbiosGenEntrypoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + VOID *Smbios; + + Smbios = GetSmbiosTablesFromHob (); + if (Smbios == NULL) { + return EFI_NOT_FOUND; + } + + Status = gBS->LocateProtocol ( + &gEfiSmbiosProtocolGuid, + NULL, + (VOID**)&gSmbios + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gStringHandle = HiiAddPackages ( + &gEfiCallerIdGuid, + NULL, + SmbiosGenDxeStrings, + NULL + ); + ASSERT (gStringHandle != NULL); + + InstallProcessorSmbios (Smbios); + InstallCacheSmbios (Smbios); + InstallMemorySmbios (Smbios); + InstallMiscSmbios (Smbios); + + return EFI_SUCCESS; +} + +// +// Internal function +// + +UINTN +SmbiosTableLength ( + IN SMBIOS_STRUCTURE_POINTER SmbiosTable + ) +{ + CHAR8 *AChar; + UINTN Length; + + AChar = (CHAR8 *)(SmbiosTable.Raw + SmbiosTable.Hdr->Length); + while ((*AChar != 0) || (*(AChar + 1) != 0)) { + AChar ++; + } + Length = ((UINTN)AChar - (UINTN)SmbiosTable.Raw + 2); + + return Length; +} + +SMBIOS_STRUCTURE_POINTER +GetSmbiosTableFromType ( + IN SMBIOS_TABLE_ENTRY_POINT *Smbios, + IN UINT8 Type, + IN UINTN Index + ) +{ + SMBIOS_STRUCTURE_POINTER SmbiosTable; + UINTN SmbiosTypeIndex; + + SmbiosTypeIndex = 0; + SmbiosTable.Raw = (UINT8 *)(UINTN)Smbios->TableAddress; + if (SmbiosTable.Raw == NULL) { + return SmbiosTable; + } + while ((SmbiosTypeIndex != Index) || (SmbiosTable.Hdr->Type != Type)) { + if (SmbiosTable.Hdr->Type == 127) { + SmbiosTable.Raw = NULL; + return SmbiosTable; + } + if (SmbiosTable.Hdr->Type == Type) { + SmbiosTypeIndex ++; + } + SmbiosTable.Raw = (UINT8 *)(SmbiosTable.Raw + SmbiosTableLength (SmbiosTable)); + } + + return SmbiosTable; +} + +CHAR8 * +GetSmbiosString ( + IN SMBIOS_STRUCTURE_POINTER SmbiosTable, + IN SMBIOS_TABLE_STRING String + ) +{ + CHAR8 *AString; + UINT8 Index; + + Index = 1; + AString = (CHAR8 *)(SmbiosTable.Raw + SmbiosTable.Hdr->Length); + while (Index != String) { + while (*AString != 0) { + AString ++; + } + AString ++; + if (*AString == 0) { + return AString; + } + Index ++; + } + + return AString; +} + + +/** + Logs SMBIOS record. + + @param Smbios Pointer to SMBIOS protocol instance. + @param Buffer Pointer to the data buffer. + +**/ +VOID +LogSmbiosData ( + IN EFI_SMBIOS_PROTOCOL *Smbios, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = Smbios->Add ( + Smbios, + NULL, + &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER*)Buffer + ); + ASSERT_EFI_ERROR (Status); +} diff --git a/Legacy/BootPlatform/SmbiosGenDxe/SmbiosGen.h b/Legacy/BootPlatform/SmbiosGenDxe/SmbiosGen.h new file mode 100644 index 0000000000000000000000000000000000000000..c36f2e4c87dd512cf5f70a093e0af527dc9affe1 --- /dev/null +++ b/Legacy/BootPlatform/SmbiosGenDxe/SmbiosGen.h @@ -0,0 +1,77 @@ +/** @file + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DataHubGen.h + +Abstract: + +**/ + +#ifndef _SMBIOS_GEN_H_ +#define _SMBIOS_GEN_H_ + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PRODUCT_NAME L"DUET" +#define PRODUCT_VERSION L"Release" + +#define FIRMWARE_PRODUCT_NAME (PRODUCT_NAME L": ") +#ifdef EFI32 +#define FIRMWARE_BIOS_VERSIONE (PRODUCT_NAME L"(IA32.UEFI)" PRODUCT_VERSION L": ") +#else // EFIX64 +#define FIRMWARE_BIOS_VERSIONE (PRODUCT_NAME L"(X64.UEFI)" PRODUCT_VERSION L": ") +#endif + +SMBIOS_STRUCTURE_POINTER +GetSmbiosTableFromType ( + IN SMBIOS_TABLE_ENTRY_POINT *Smbios, + IN UINT8 Type, + IN UINTN Index + ); + +CHAR8 * +GetSmbiosString ( + IN SMBIOS_STRUCTURE_POINTER SmbiosTable, + IN SMBIOS_TABLE_STRING String + ); + +/** + Logs SMBIOS record. + + @param Smbios Pointer to SMBIOS protocol instance. + @param Buffer Pointer to the data buffer. + +**/ +VOID +LogSmbiosData ( + IN EFI_SMBIOS_PROTOCOL *Smbios, + IN UINT8 *Buffer + ); + +#endif diff --git a/Legacy/BootPlatform/SmbiosGenDxe/SmbiosGen.inf b/Legacy/BootPlatform/SmbiosGenDxe/SmbiosGen.inf new file mode 100644 index 0000000000000000000000000000000000000000..025c4692e94750831b01cb842d840f6951c7112f --- /dev/null +++ b/Legacy/BootPlatform/SmbiosGenDxe/SmbiosGen.inf @@ -0,0 +1,60 @@ +## @file +# +# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# SmbiosGen.inf +# +# Abstract: +# +# Component description file for SmbiosGen module. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmbiosGenDxe + FILE_GUID = A17F4A89-5F19-444f-B7BE-48195E0575DB + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = SmbiosGenEntrypoint + +[Packages] + OpenCorePkg/OpenDuetPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiLib + HobLib + UefiBootServicesTableLib + BaseMemoryLib + MemoryAllocationLib + UefiDriverEntryPoint + BaseLib + HiiLib + UefiHiiServicesLib + +[Sources] + SmbiosGen.c + SmbiosGen.h + SmbiosGenStrings.uni + +[Guids] + gEfiSmbiosTableGuid + +[Protocols] + gEfiHiiDatabaseProtocolGuid + gEfiSmbiosProtocolGuid + +[Depex] + gEfiSmbiosProtocolGuid AND gEfiHiiDatabaseProtocolGuid + diff --git a/Legacy/BootPlatform/SmbiosGenDxe/SmbiosGenStrings.uni b/Legacy/BootPlatform/SmbiosGenDxe/SmbiosGenStrings.uni new file mode 100644 index 0000000000000000000000000000000000000000..84e072bfe7e939bbb174ef3fa4cf92c0d2c02568 --- /dev/null +++ b/Legacy/BootPlatform/SmbiosGenDxe/SmbiosGenStrings.uni @@ -0,0 +1,32 @@ +// *++ +// +// Copyright (c) 2006, Intel Corporation. All rights reserved.
+// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// DataHubGenStrings.uni +// +// Abstract: +// +// String definitions for DataHubGen file. +// +// Revision History: +// +// --*/ + +/=# + +#langdef en-US "English" + +#string STR_UNKNOWN #language en-US "Unknown" + + + + diff --git a/Legacy/BootSector/Makefile b/Legacy/BootSector/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a98f0ed03b611b0ae5dbfd497a22da1cc37a2500 --- /dev/null +++ b/Legacy/BootSector/Makefile @@ -0,0 +1,29 @@ +NASM ?= nasm +MKDIR ?= mkdir +RM ?= /bin/rm +PAGE_TABLE ?= 0x60000 + +BINDIR=bin +PRODUCTS32=$(BINDIR)/StartIA32.com $(BINDIR)/EfiIA32.com +PRODUCTS64=$(BINDIR)/StartX64_$(PAGE_TABLE).com $(BINDIR)/EfiX64.com + +all: $(PRODUCTS32) $(PRODUCTS64) + +clean: + $(RM) -f $(BINDIR)/*.com + +$(BINDIR)/StartIA32.com: start.nasm + @$(MKDIR) -p bin + $(NASM) -f bin -o $@ $< + +$(BINDIR)/EfiIA32.com: efi32.nasm + @$(MKDIR) -p bin + $(NASM) -f bin -o $@ $< + +$(BINDIR)/StartX64_$(PAGE_TABLE).com: start.nasm + @$(MKDIR) -p bin + $(NASM) -DX64 -DPAGE_TABLE=$(PAGE_TABLE) -f bin -o $@ $< + +$(BINDIR)/EfiX64.com: efi64.nasm + @$(MKDIR) -p bin + $(NASM) -f bin -o $@ $< diff --git a/Legacy/BootSector/efi32.nasm b/Legacy/BootSector/efi32.nasm new file mode 100644 index 0000000000000000000000000000000000000000..bbbdc1eeadb0bc29b9cb0407268ee6dd9eb57d87 --- /dev/null +++ b/Legacy/BootSector/efi32.nasm @@ -0,0 +1,408 @@ + +DEFAULT_HANDLER_SIZE: equ 9 ; size of exception/interrupt stub +SYS_CODE_SEL: equ 0x20 ; 32-bit code selector in GDT +PE_OFFSET_IN_MZ_STUB: equ 0x3c ; place in MsDos stub for offset to PE Header +VGA_FB: equ 0x000b8000 ; VGA framebuffer for 80x25 mono mode +VGA_LINE: equ 80 * 2 ; # bytes in one line +BASE_ADDR_32: equ 0x00021000 +STACK_TOP: equ 0x001ffff0 +SIZE: equ 0x1000 + +struc EFILDR_IMAGE +.CheckSum: resd 1 +.Offset: resd 1 +.Length: resd 1 +.FileName: resb 52 +endstruc + +struc EFILDR_HEADER +.Signature: resd 1 +.HeaderCheckSum: resd 1 +.FileLength: resd 1 +.NumberOfImages: resd 1 +endstruc + +struc PE_HEADER + resb 6 +.NumberOfSections: resw 1 + resb 12 +.SizeOfOptionalHeader: resw 1 + resb 2 +.Magic: resb 16 +.AddressOfEntryPoint: resd 1 + resb 8 +.ImageBase32: resd 1 +endstruc + +struc PE_SECTION_HEADER + resb 12 +.VirtualAddress: resd 1 +.SizeOfRawData: resd 1 +.PointerToRawData: resd 1 + resb 16 +endstruc + +%macro StubWithNoCode 1 + push 0 ; push error code place holder on the stack + push %1 + jmp strict dword commonIdtEntry +%endmacro + +%macro StubWithACode 1 + times 2 nop + push %1 + jmp strict dword commonIdtEntry +%endmacro + +%macro PrintReg 2 + mov esi, %1 + call PrintString + mov eax, [ebp + %2] + call PrintDword +%endmacro + + bits 32 + org BASE_ADDR_32 +global _start +_start: + mov ax, bx + mov ds, eax + mov es, eax + mov fs, eax + mov gs, eax + mov ss, eax + mov esp, STACK_TOP + +; +; Populate IDT with meaningful offsets for exception handlers... +; + sidt [Idtr] + + mov eax, StubTable + mov ebx, eax ; use bx to copy 15..0 to descriptors + shr eax, 16 ; use ax to copy 31..16 to descriptors + mov ecx, 0x78 ; 78h IDT entries to initialize with unique entry points + mov edi, [Idtr + 2] + +.StubLoop: ; loop through all IDT entries exception handlers and initialize to default handler + mov [edi], bx ; write bits 15..0 of offset + mov word [edi + 2], SYS_CODE_SEL ; SYS_CODE_SEL from GDT + mov word [edi + 4], 0x8e00 ; type = 386 interrupt gate, present + mov [edi + 6], ax ; write bits 31..16 of offset + add edi, 8 ; move up to next descriptor + add ebx, DEFAULT_HANDLER_SIZE ; move to next entry point + loop .StubLoop ; loop back through again until all descriptors are initialized + +; +; Load EFILDR +; + mov esi, BlockSignature + 2 + add esi, [esi + EFILDR_HEADER_size + EFILDR_IMAGE.Offset] ; esi = Base of EFILDR.C + mov ebp, [esi + PE_OFFSET_IN_MZ_STUB] + add ebp, esi ; ebp = PE Image Header for EFILDR.C + mov edi, [ebp + PE_HEADER.ImageBase32] ; edi = ImageBase + mov eax, [ebp + PE_HEADER.AddressOfEntryPoint] ; eax = EntryPoint + add eax, edi ; eax = ImageBase + EntryPoint + mov [.EfiLdrOffset], eax ; Modify jump instruction for correct entry point + + movzx ebx, word [ebp + PE_HEADER.NumberOfSections] ; bx = Number of sections + movzx eax, word [ebp + PE_HEADER.SizeOfOptionalHeader]; ax = Optional Header Size + add ebp, eax + add ebp, PE_HEADER.Magic ; ebp = Start of 1st Section + +.SectionLoop: + push esi ; Save Base of EFILDR.C + push edi ; Save ImageBase + add esi, [ebp + PE_SECTION_HEADER.PointerToRawData] ; esi = Base of EFILDR.C + PointerToRawData + add edi, [ebp + PE_SECTION_HEADER.VirtualAddress] ; edi = ImageBase + VirtualAddress + mov ecx, [ebp + PE_SECTION_HEADER.SizeOfRawData] ; ecx = SizeOfRawData + + cld + shr ecx, 2 + rep movsd + + pop edi ; Restore ImageBase + pop esi ; Restore Base of EFILDR.C + + add ebp, PE_SECTION_HEADER_size ; ebp = Pointer to next section record + dec ebx + jnz .SectionLoop + + movzx eax, word [Idtr] ; get size of IDT + inc eax + add eax, [Idtr + 2] ; add to base of IDT to get location of memory map... + push eax ; push memory map location on stack for call to EFILDR... + + push eax ; push return address (useless, just for stack balance) + +.EfiLdrOffset: equ $ + 1 + mov eax, 0x00401000 + jmp eax ; jump to entry point + +StubTable: +%assign i 0 +%rep 8 + StubWithNoCode i +%assign i i+1 +%endrep + StubWithACode 8 ; Double Fault + StubWithNoCode 9 + StubWithACode 10 ; Invalid TSS + StubWithACode 11 ; Segment Not Present + StubWithACode 12 ; Stack Fault + StubWithACode 13 ; GP Fault + StubWithACode 14 ; Page Fault + StubWithNoCode 15 + StubWithNoCode 16 + StubWithACode 17 ; Alignment Check +%assign i 18 +%rep 102 + StubWithNoCode i +%assign i i+1 +%endrep + +commonIdtEntry: + pushad + mov ebp, esp +; +; At this point the stack looks like this: +; +; eflags +; Calling CS +; Calling EIP +; Error code or 0 +; Int num or 0ffh for unknown int num +; eax +; ecx +; edx +; ebx +; esp +; ebp +; esi +; edi <------- ESP, EBP +; + +; call ClearScreen + mov edi, VGA_FB + mov esi, String1 + call PrintString + mov eax, [ebp + 8 * 4] ; move Int number into EAX + cmp eax, 19 + ja .PrintDefaultString + mov esi, [eax * 4 + StringTable] ; get offset from StringTable to actual string address + jmp .PrintTheString +.PrintDefaultString: + mov esi, IntUnknownString +; patch Int number + mov edx, eax + call A2C + mov [esi + 1], al + mov eax, edx + shr eax, 4 + call A2C + mov [esi], al +.PrintTheString: + call PrintString + PrintReg String2, 11 * 4 ; CS + mov byte [edi], ':' + add edi, 2 + mov eax, [ebp + 10 * 4] ; EIP + call PrintDword + mov esi, String3 + call PrintString + + mov edi, VGA_FB + 2 * VGA_LINE + + PrintReg StringEax, 7 * 4 + + PrintReg StringEbx, 4 * 4 + + PrintReg StringEcx, 6 * 4 + + PrintReg StringEdx, 5 * 4 + + PrintReg StringEcode, 9 * 4 + + mov edi, VGA_FB + 3 * VGA_LINE + + PrintReg StringEsp, 3 * 4 + + PrintReg StringEbp, 2 * 4 + + PrintReg StringEsi, 4 + + PrintReg StringEdi, 0 + + PrintReg StringEflags, 12 * 4 + + mov edi, VGA_FB + 5 * VGA_LINE + + mov esi, ebp + add esi, 13 * 4 ; stack beyond eflags + mov ecx, 8 + +.OuterLoop: + push ecx + mov ecx, 8 + mov edx, edi + +.InnerLoop: + mov eax, [esi] + call PrintDword + add esi, 4 + mov byte [edi], ' ' + add edi, 2 + loop .InnerLoop + + pop ecx + add edx, VGA_LINE + mov edi, edx + loop .OuterLoop + + mov edi, VGA_FB + 15 * VGA_LINE + + mov esi, [ebp + 10 * 4] ; EIP + sub esi, 32 * 4 ; code preceding EIP + + mov ecx, 8 + +.OuterLoop1: + push ecx + mov ecx, 8 + mov edx, edi + +.InnerLoop1: + mov eax, [esi] + call PrintDword + add esi, 4 + mov byte [edi], ' ' + add edi, 2 + loop .InnerLoop1 + + pop ecx + add edx, VGA_LINE + mov edi, edx + loop .OuterLoop1 + +.Halt: + hlt + jmp .Halt +; +; Return +; + mov esp, ebp + popad + add esp, 8 ; error code and INT number + iretd + +PrintString: + push eax +.loop: + mov al, [esi] + test al, al + jz .done + mov [edi], al + inc esi + add edi, 2 + jmp .loop +.done: + pop eax + ret + +; EAX contains dword to print +; EDI contains memory location (screen location) to print it to + +PrintDword: + push ecx + push ebx + push eax + mov ecx, 8 +.looptop: + rol eax, 4 + mov bl, al + and bl, 15 + add bl, '0' + cmp bl, '9' + jbe .is_digit + add bl, 7 +.is_digit: + mov [edi], bl + add edi, 2 + loop .looptop + pop eax + pop ebx + pop ecx + ret + +ClearScreen: + push eax + push ecx + mov ax, 0x0c20 + mov edi, VGA_FB + mov ecx, 80 * 25 + rep stosw + mov edi, VGA_FB + pop ecx + pop eax + ret + +A2C: + and al, 15 + add al, '0' + cmp al, '9' + jbe .is_digit + add al, 7 +.is_digit: + ret + +String1: db '*** INT ', 0 + +Int0String: db '00h Divide by 0 -', 0 +Int1String: db '01h Debug exception -', 0 +Int2String: db '02h NMI -', 0 +Int3String: db '03h Breakpoint -', 0 +Int4String: db '04h Overflow -', 0 +Int5String: db '05h Bound -', 0 +Int6String: db '06h Invalid opcode -', 0 +Int7String: db '07h Device not available -', 0 +Int8String: db '08h Double fault -', 0 +Int9String: db '09h Coprocessor seg overrun (reserved) -', 0 +Int10String: db '0Ah Invalid TSS -', 0 +Int11String: db '0Bh Segment not present -', 0 +Int12String: db '0Ch Stack fault -', 0 +Int13String: db '0Dh General protection fault -', 0 +Int14String: db '0Eh Page fault -', 0 +Int15String: db '0Fh (Intel reserved) -', 0 +Int16String: db '10h Floating point error -', 0 +Int17String: db '11h Alignment check -', 0 +Int18String: db '12h Machine check -', 0 +Int19String: db '13h SIMD Floating-Point Exception -', 0 +IntUnknownString: db '??h Unknown interrupt -', 0 + + align 4, db 0 + +StringTable: +%assign i 0 +%rep 20 + dd Int%[i]String +%assign i i+1 +%endrep + +String2: db ' HALT!! *** (', 0 +String3: db ')', 0 +StringEax: db 'EAX=', 0 +StringEbx: db ' EBX=', 0 +StringEcx: db ' ECX=', 0 +StringEdx: db ' EDX=', 0 +StringEcode: db ' ECODE=', 0 +StringEsp: db 'ESP=', 0 +StringEbp: db ' EBP=', 0 +StringEsi: db ' ESI=', 0 +StringEdi: db ' EDI=', 0 +StringEflags: db ' EFLAGS=', 0 + + align 2, db 0 +Idtr: + times SIZE - 2 - $ + $$ db 0 +BlockSignature: + dw 0xaa55 diff --git a/Legacy/BootSector/efi64.nasm b/Legacy/BootSector/efi64.nasm new file mode 100644 index 0000000000000000000000000000000000000000..01e735b64036d9edd22b74460712769b969c7167 --- /dev/null +++ b/Legacy/BootSector/efi64.nasm @@ -0,0 +1,483 @@ + +DEFAULT_HANDLER_SIZE: equ 9 ; size of exception/interrupt stub +SYS_CODE_SEL64: equ 0x38 ; 64-bit code selector in GDT +PE_OFFSET_IN_MZ_STUB: equ 0x3c ; place in MsDos stub for offset to PE Header +VGA_FB: equ 0x000b8000 ; VGA framebuffer for 80x25 mono mode +VGA_LINE: equ 80 * 2 ; # bytes in one line +BASE_ADDR_64: equ 0x00021000 +STACK_TOP: equ 0x001fffe8 +SIZE: equ 0x1000 + +struc EFILDR_IMAGE +.CheckSum: resd 1 +.Offset: resd 1 +.Length: resd 1 +.FileName: resb 52 +endstruc + +struc EFILDR_HEADER +.Signature: resd 1 +.HeaderCheckSum: resd 1 +.FileLength: resd 1 +.NumberOfImages: resd 1 +endstruc + +struc PE_HEADER + resb 6 +.NumberOfSections: resw 1 + resb 12 +.SizeOfOptionalHeader: resw 1 + resb 2 +.Magic: resb 16 +.AddressOfEntryPoint: resd 1 + resb 4 +.ImageBase64: resd 1 +endstruc + +struc PE_SECTION_HEADER + resb 12 +.VirtualAddress: resd 1 +.SizeOfRawData: resd 1 +.PointerToRawData: resd 1 + resb 16 +endstruc + +%macro StubWithNoCode 1 + push 0 ; push error code place holder on the stack + push %1 + jmp strict qword commonIdtEntry +%endmacro + +%macro StubWithACode 1 + times 2 nop + push %1 + jmp strict qword commonIdtEntry +%endmacro + +%macro PrintReg 2 + mov esi, %1 + call PrintString + mov rax, [rbp + %2] + call PrintQword +%endmacro + + bits 64 + org BASE_ADDR_64 +global _start +_start: + mov esp, STACK_TOP +; +; set OSFXSR and OSXMMEXCPT because some code will use XMM registers +; + mov rax, cr4 + or rax, 0x600 + mov cr4, rax + +; +; Populate IDT with meaningful offsets for exception handlers... +; + sidt [REL Idtr] + + mov eax, StubTable + mov ebx, eax ; use bx to copy 15..0 to descriptors + shr eax, 16 ; use ax to copy 31..16 to descriptors + ; 63..32 of descriptors is 0 + mov ecx, 0x78 ; 78h IDT entries to initialize with unique entry points + mov edi, [REL Idtr + 2] + +.StubLoop: ; loop through all IDT entries exception handlers and initialize to default handler + mov [rdi], bx ; write bits 15..0 of offset + mov word [rdi + 2], SYS_CODE_SEL64 ; SYS_CODE_SEL64 from GDT + mov word [rdi + 4], 0x8e00 ; type = 386 interrupt gate, present + mov [rdi + 6], ax ; write bits 31..16 of offset + mov dword [rdi + 8], 0 ; write bits 63..32 of offset + add edi, 16 ; move up to next descriptor + add ebx, DEFAULT_HANDLER_SIZE ; move to next entry point + loop .StubLoop ; loop back through again until all descriptors are initialized + +; +; Load EFILDR +; + mov esi, BlockSignature + 2 + add esi, [rsi + EFILDR_HEADER_size + EFILDR_IMAGE.Offset] ; esi = Base of EFILDR.C + mov ebp, [rsi + PE_OFFSET_IN_MZ_STUB] + add ebp, esi ; ebp = PE Image Header for EFILDR.C + mov edi, [rbp + PE_HEADER.ImageBase64] ; edi = ImageBase (63..32 is zero, ignore) + mov eax, [rbp + PE_HEADER.AddressOfEntryPoint] ; eax = EntryPoint + add eax, edi ; eax = ImageBase + EntryPoint + mov [REL .EfiLdrOffset], eax ; Modify jump instruction for correct entry point + + movzx ebx, word [rbp + PE_HEADER.NumberOfSections] ; bx = Number of sections + movzx eax, word [rbp + PE_HEADER.SizeOfOptionalHeader]; ax = Optional Header Size + add ebp, eax + add ebp, PE_HEADER.Magic ; ebp = Start of 1st Section + +.SectionLoop: + push rsi ; Save Base of EFILDR.C + push rdi ; Save ImageBase + add esi, [rbp + PE_SECTION_HEADER.PointerToRawData] ; esi = Base of EFILDR.C + PointerToRawData + add edi, [rbp + PE_SECTION_HEADER.VirtualAddress] ; edi = ImageBase + VirtualAddress + mov ecx, [rbp + PE_SECTION_HEADER.SizeOfRawData] ; ecx = SizeOfRawData + + cld + shr ecx, 2 + rep movsd + + pop rdi ; Restore ImageBase + pop rsi ; Restore Base of EFILDR.C + + add ebp, PE_SECTION_HEADER_size ; ebp = Pointer to next section record + dec ebx + jnz .SectionLoop + + movzx ecx, word [REL Idtr] ; get size of IDT + inc ecx + add ecx, [REL Idtr + 2] ; add to base of IDT to get location of memory map... + ; argument in RCX +.EfiLdrOffset: equ $ + 1 + mov eax, 0x00401000 + jmp rax ; jump to entry point + +StubTable: +%assign i 0 +%rep 8 + StubWithNoCode i +%assign i i+1 +%endrep + StubWithACode 8 ; Double Fault + StubWithNoCode 9 + StubWithACode 10 ; Invalid TSS + StubWithACode 11 ; Segment Not Present + StubWithACode 12 ; Stack Fault + StubWithACode 13 ; GP Fault + StubWithACode 14 ; Page Fault + StubWithNoCode 15 + StubWithNoCode 16 + StubWithACode 17 ; Alignment Check +%assign i 18 +%rep 102 + StubWithNoCode i +%assign i i+1 +%endrep + +commonIdtEntry: + push rax + push rcx + push rdx + push rbx + push rsp + push rbp + push rsi + push rdi + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + mov rbp, rsp +; +; At this point the stack looks like this: +; +; Calling SS +; Calling RSP +; rflags +; Calling CS +; Calling RIP +; Error code or 0 +; Int num or 0ffh for unknown int num +; rax +; rcx +; rdx +; rbx +; rsp +; rbp +; rsi +; rdi +; r8 +; r9 +; r10 +; r11 +; r12 +; r13 +; r14 +; r15 <------- RSP, RBP +; + + call ClearScreen + mov esi, String1 + call PrintString + mov eax, [rbp + 16 * 8] ; move Int number into EAX + cmp eax, 19 + ja .PrintDefaultString + mov esi, [rax * 8 + StringTable] ; get offset from StringTable to actual string address + jmp .PrintTheString +.PrintDefaultString: + mov esi, IntUnknownString +; patch Int number + mov edx, eax + call A2C + mov [rsi + 1], al + mov eax, edx + shr eax, 4 + call A2C + mov [rsi], al +.PrintTheString: + call PrintString + PrintReg String2, 19 * 8 ; CS + mov byte [rdi], ':' + add edi, 2 + mov rax, [rbp + 18 * 8] ; RIP + call PrintQword + mov esi, String3 + call PrintString + + mov edi, VGA_FB + 2 * VGA_LINE + + PrintReg StringRax, 15 * 8 + + PrintReg StringRcx, 14 * 8 + + PrintReg StringRdx, 13 * 8 + + mov edi, VGA_FB + 3 * VGA_LINE + + PrintReg StringRbx, 12 * 8 + + PrintReg StringRsp, 21 * 8 + + PrintReg StringRbp, 10 * 8 + + mov edi, VGA_FB + 4 * VGA_LINE + + PrintReg StringRsi, 9 * 8 + + PrintReg StringRdi, 8 * 8 + + PrintReg StringEcode, 17 * 8 + + mov edi, VGA_FB + 5 * VGA_LINE + + PrintReg StringR8, 7 * 8 + + PrintReg StringR9, 6 * 8 + + PrintReg StringR10, 5 * 8 + + mov edi, VGA_FB + 6 * VGA_LINE + + PrintReg StringR11, 4 * 8 + + PrintReg StringR12, 3 * 8 + + PrintReg StringR13, 2 * 8 + + mov edi, VGA_FB + 7 * VGA_LINE + + PrintReg StringR14, 8 + + PrintReg StringR15, 0 + + PrintReg StringSs, 22 * 8 + + mov edi, VGA_FB + 8 * VGA_LINE + + PrintReg StringRflags, 20 * 8 + + mov edi, VGA_FB + 10 * VGA_LINE + + mov rsi, rbp + add rsi, 23 * 8 ; stack beyond SS + mov ecx, 4 + +.OuterLoop: + push rcx + mov ecx, 4 + mov edx, edi + +.InnerLoop: + mov rax, [rsi] + call PrintQword + add rsi, 8 + mov byte [rdi], ' ' + add edi, 2 + loop .InnerLoop + + pop rcx + add edx, VGA_LINE + mov edi, edx + loop .OuterLoop + + mov edi, VGA_FB + 15 * VGA_LINE + + mov rsi, [rbp + 18 * 8] ; RIP + sub rsi, 8 * 8 ; code preceding RIP + + mov ecx, 4 + +.OuterLoop1: + push rcx + mov ecx, 4 + mov edx, edi + +.InnerLoop1: + mov rax, [rsi] + call PrintQword + add rsi, 8 + mov byte [rdi], ' ' + add edi, 2 + loop .InnerLoop1 + + pop rcx + add edx, VGA_LINE + mov edi, edx + loop .OuterLoop1 + +.Halt: + hlt + jmp .Halt +; +; Return +; + mov rsp, rbp + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + pop rbp + pop rax ; rsp + pop rbx + pop rdx + pop rcx + pop rax + add rsp, 16 ; error code and INT number + iretq + +PrintString: + push rax +.loop: + mov al, [rsi] + test al, al + jz .done + mov [rdi], al + inc esi + add edi, 2 + jmp .loop +.done: + pop rax + ret + +; RAX contains qword to print +; RDI contains memory location (screen location) to print it to + +PrintQword: + push rcx + push rbx + push rax + mov ecx, 16 +.looptop: + rol rax, 4 + mov bl, al + and bl, 15 + add bl, '0' + cmp bl, '9' + jbe .is_digit + add bl, 7 +.is_digit: + mov [rdi], bl + add edi, 2 + loop .looptop + pop rax + pop rbx + pop rcx + ret + +ClearScreen: + push rax + push rcx + mov ax, 0x0c20 + mov edi, VGA_FB + mov ecx, 80 * 25 + rep stosw + mov edi, VGA_FB + pop rcx + pop rax + ret + +A2C: + and al, 15 + add al, '0' + cmp al, '9' + jbe .is_digit + add al, 7 +.is_digit: + ret + +String1: db '*** INT ', 0 + +Int0String: db '00h Divide by 0 -', 0 +Int1String: db '01h Debug exception -', 0 +Int2String: db '02h NMI -', 0 +Int3String: db '03h Breakpoint -', 0 +Int4String: db '04h Overflow -', 0 +Int5String: db '05h Bound -', 0 +Int6String: db '06h Invalid opcode -', 0 +Int7String: db '07h Device not available -', 0 +Int8String: db '08h Double fault -', 0 +Int9String: db '09h Coprocessor seg overrun (reserved) -', 0 +Int10String: db '0Ah Invalid TSS -', 0 +Int11String: db '0Bh Segment not present -', 0 +Int12String: db '0Ch Stack fault -', 0 +Int13String: db '0Dh General protection fault -', 0 +Int14String: db '0Eh Page fault -', 0 +Int15String: db '0Fh (Intel reserved) -', 0 +Int16String: db '10h Floating point error -', 0 +Int17String: db '11h Alignment check -', 0 +Int18String: db '12h Machine check -', 0 +Int19String: db '13h SIMD Floating-Point Exception -', 0 +IntUnknownString: db '??h Unknown interrupt -', 0 + + align 8, db 0 + +StringTable: +%assign i 0 +%rep 20 + dq Int%[i]String +%assign i i+1 +%endrep + +String2: db ' HALT!! *** (', 0 +String3: db ')', 0 +StringRax: db 'RAX=', 0 +StringRcx: db ' RCX=', 0 +StringRdx: db ' RDX=', 0 +StringRbx: db 'RBX=', 0 +StringRsp: db ' RSP=', 0 +StringRbp: db ' RBP=', 0 +StringRsi: db 'RSI=', 0 +StringRdi: db ' RDI=', 0 +StringEcode: db ' ECODE=', 0 +StringR8: db 'R8 =', 0 +StringR9: db ' R9 =', 0 +StringR10: db ' R10=', 0 +StringR11: db 'R11=', 0 +StringR12: db ' R12=', 0 +StringR13: db ' R13=', 0 +StringR14: db 'R14=', 0 +StringR15: db ' R15=', 0 +StringSs: db ' SS =', 0 +StringRflags: db 'RFLAGS=', 0 + + align 2, db 0 +Idtr: + times SIZE - 2 - $ + $$ db 0 +BlockSignature: + dw 0xaa55 diff --git a/Legacy/BootSector/start.nasm b/Legacy/BootSector/start.nasm new file mode 100644 index 0000000000000000000000000000000000000000..1af4cb9a438f247a72ed80a8d70ae3af30311796 --- /dev/null +++ b/Legacy/BootSector/start.nasm @@ -0,0 +1,519 @@ + +; +; Parameters +; X64 - 64 bit target +; LEGACY_A20 - use slow A20 Gate +; CHARACTER_TO_SHOW - character to display +; FORCE_TEXT_MODE - switch to 80x25 mono mode +; USB_LOW_EBDA - low-ebda mode +; GENPAGE - genpage mode +; + +%ifdef LEGACY_A20 +DELAY_PORT: equ 0xed ; Port to use for 1uS delay +KBD_CONTROL_PORT: equ 0x60 ; 8042 control port +KBD_STATUS_PORT: equ 0x64 ; 8042 status port +WRITE_DATA_PORT_CMD: equ 0xd1 ; 8042 command to write the data port +ENABLE_A20_CMD: equ 0xdf ; 8042 command to enable A20 +%else +FAST_ENABLE_A20_PORT: equ 0x92 +FAST_ENABLE_A20_MASK: equ 2 +%endif +BASE_ADR_16: equ 0x0200 +SIZE_TO_STACK_16: equ 0x0fe0 - BASE_ADR_16 +IA32_EFER: equ 0xC0000080 + +%assign GDT_DESC_SIZE 8 +%macro GDT_DESC 2 + dw 0xFFFF, 0 + db 0, %1, %2, 0 +%endmacro + +%ifdef X64 + %assign IDT_DESC_SIZE 16 + %macro IDT_DESC 0 + dw 0, SYS_CODE64_SEL + db 0, 0x8e + dw 0 + dd 0, 0 + %endmacro +%else + %assign IDT_DESC_SIZE 8 + %macro IDT_DESC 0 + dw 0, SYS_CODE_SEL + db 0, 0x8e + dw 0 + %endmacro +%endif + +%ifdef X64 + %ifndef GENPAGE + section .pagezero start=0 + times BASE_ADR_16 db 0 + + %ifndef PAGE_TABLE + %error "PAGE_TABLE is not defined!" + %endif + %endif +%else + %undef GENPAGE +%endif + + bits 16 + + section .text start=BASE_ADR_16 + +global _start +_start: + jmp .SkipLabel +%ifdef X64 + db 'DUETX64 ' ; Bootloader Label +%else + db 'DUETIA32 ' ; Bootloader Label +%endif +.SkipLabel: + mov ax, cs + mov ds, ax + mov es, ax + mov ss, ax + mov sp, MyStack + +; +; Retrieve Bios Memory Map +; + xor ebx, ebx + lea edi, [MemoryMap] +.MemMapLoop: + mov eax, 0xe820 + mov ecx, 20 + mov edx, 0x534d4150 ; SMAP + int 0x15 + jc .MemMapDone + add di, 20 + test ebx, ebx + jnz .MemMapLoop +.MemMapDone: + sub di, MemoryMap ; Get the address of the memory map + mov [MemoryMapSize], edi ; Save the size of the memory map + +; +; Rebase Self +; + xor ebx, ebx + mov bx, cs + shl ebx, 4 + add [gdtr + 2], ebx + add [idtr + 2], ebx + add [.JumpTo32BitProtectedMode], ebx +%ifdef X64 + add [.JumpToLongMode], ebx +%endif + +; +; Enable A20 Gate +; + mov ax, 0x2401 + int 0x15 + jnc .A20GateEnabled + +; +; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually. +; + +%ifdef LEGACY_A20 +; +; Legacy A20gate +; + call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller + jnz .Timeout8042 ; Jump if the 8042 timed out + out DELAY_PORT, ax ; Delay 1 uS + mov al, WRITE_DATA_PORT_CMD ; 8042 cmd to write output port + out KBD_STATUS_PORT, al ; Send command to the 8042 + call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller + jnz .Timeout8042 ; Jump if the 8042 timed out + mov al, ENABLE_A20_CMD ; gate address bit 20 on + out KBD_CONTROL_PORT,al ; Send command to thre 8042 + call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller + mov cx, 25 ; Delay 25 uS for the command to complete on the 8042 +.Delay25uS: + out DELAY_PORT, ax ; Delay 1 uS + loop .Delay25uS +.Timeout8042: + +%else +; +; WIKI - fast A20gate +; + in al, FAST_ENABLE_A20_PORT + or al, FAST_ENABLE_A20_MASK + out FAST_ENABLE_A20_PORT, al + +%endif + +.A20GateEnabled: + +%ifdef GENPAGE +; +; Create Page Table +; + call CreatePageTable +%endif + +%ifdef FORCE_TEXT_MODE +; +; Switch to 80x25 mono text mode (2) +; + mov ax, 2 + int 0x10 +%endif + +%ifdef CHARACTER_TO_SHOW + +; +; Display CHARACTER_TO_SHOW +; + mov bx, 0x000F + mov ax, 0x0E00 | (CHARACTER_TO_SHOW & 255) + int 0x10 + +%endif + +%ifndef X64 + mov bx, LINEAR_SEL ; Flat data descriptor +%endif + +; +; DISABLE INTERRUPTS - Entering Protected Mode +; + cli + +%ifdef GENPAGE +; +; Ready Address of Page Table in EDX +; + movzx edx, word [PageTableSegment] + shl edx, 4 +%endif + +; +; load GDT +; + lgdt [gdtr] + +%ifndef X64 +; +; load IDT +; + lidt [idtr] +%endif + +; +; Enable Protected Mode (set CR0.PE=1) +; + mov eax, cr0 + or al, 1 + mov cr0, eax + +.JumpTo32BitProtectedMode: equ $ + 2 +%ifndef X64 + jmp dword LINEAR_CODE_SEL:(BlockSignature + 2) +%else + jmp dword LINEAR_CODE_SEL:.In32BitProtectedMode +.In32BitProtectedMode: + + bits 32 +; +; Entering Long Mode +; + mov ax, LINEAR_SEL + mov ds, eax + mov es, eax + mov ss, eax +; WARNING: esp invalid here + +; +; Enable the 64-bit page-translation-table entries by +; setting CR4.PAE=1 (this is _required_ before activating +; long mode). Paging is not enabled until after long mode +; is enabled. +; + mov eax, cr4 + or al, 0x20 + mov cr4, eax + +; +; This is the Trapolean Page Tables that are guarenteed +; under 4GB. +; +; Address Map: +; 10000 ~ 12000 - efildr (loaded) +; 20000 ~ 21000 - start64.com +; 21000 ~ 22000 - efi64.com +; 22000 ~ 90000 - efildr +; 90000 ~ 96000 - 4G pagetable (will be reload later) +; +%ifdef GENPAGE + mov cr3, edx +%else + mov eax, PAGE_TABLE + mov cr3, eax +%endif + +; +; Enable long mode (set EFER.LME=1). +; + mov ecx, IA32_EFER + rdmsr + or ax, 0x100 + wrmsr + +; +; Enable Paging to activate long mode (set CR0.PG=1) +; + mov eax, cr0 + bts eax, 31 + mov cr0, eax + +.JumpToLongMode: equ $ + 1 + jmp SYS_CODE64_SEL:.InLongMode +.InLongMode: + + bits 64 + + mov ax, SYS_DATA_SEL + mov ds, eax + mov es, eax + mov ss, eax + lea rsp, [REL MyStack] + +; +; load IDT +; + lidt [REL idtr] + + jmp BlockSignature + 2 + +%endif + + bits 16 + +%ifdef LEGACY_A20 +Empty8042InputBuffer: + xor cx, cx +.Empty8042Loop: + out DELAY_PORT, ax ; Delay 1us + in al, KBD_STATUS_PORT ; Read the 8042 Status Port + and al, 2 ; Check the Input Buffer Full Flag + loopnz .Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS + ret +%endif + +%ifdef GENPAGE +; +; Find place for page table and create it +; + +EFILDR_BASE: equ 0x2000 ; Offset to start of EFILDR block +EFILDR_FILE_LENGTH equ 8 ; Dword in EFILDR_HEADER holding size of block +EBDA_SEG: equ 0x40 ; Segment:Offset for finding the EBDA +EBDA_OFFSET: equ 0xE + +CreatePageTable: + mov edx, [EFILDR_BASE + EFILDR_FILE_LENGTH] ; Size of EFILDR block -> EDX + add edx, EFILDR_BASE + 15 ; Add base + shr edx, 4 ; And round up to multiple of 16 + mov ax, ds + add dx, ax ; Add in linear base + add dx, 255 + xor dl, dl ; And round up to page size +; DX holds 16-bit segment of page table + + mov cx, ds ; Save DS + mov ax, EBDA_SEG + add dh, 6 ; Need 6 pages for table + mov ds, ax + mov ax, [EBDA_OFFSET] ; EBDA 16-bit segment now in AX + mov ds, cx ; Restore DS + cmp ax, dx ; Does page table fit under EBDA? + jae .continue ; Yes, continue + jmp PageTableError ; No, abort +.continue: + sub dh, 6 ; Restore DX to start segment of page table + mov [PageTableSegment], dx ; Stash it for client + push es + push di ; Save ES:DI used to build page table + + mov es, dx + xor di, di ; ES:DI points to start of page table + inc dh ; Bump DX to next page + +; +; Set up page table root page (only 1 entry) +; + xor eax, eax + mov ax, dx + inc dh ; Bump DX to next page + shl eax, 4 + or al, 3 + stosd + xor eax, eax + mov cx, 2046 + rep stosw ; Wipe rest of 1st page + +; +; Set up page table 2nd page (depth 1 - 4 entries) +; + mov cx, 4 +.loop1: + mov ax, dx + inc dh ; Bump DX to next page + shl eax, 4 + or al, 3 + stosd + xor eax, eax + stosd + loop .loop1 + mov cx, 2032 ; Wipe rest of 2nd page + rep stosw + +; +; Set up pages 3 - 6 (depth 2 - 2048 entries) +; + xor edx, edx ; Start at base of memory + mov dl, 0x83 ; Flags at leaf nodes mark large pages (2MB each) + mov cx, 2048 +.loop2: + mov eax, edx + add edx, 0x200000 ; Bump EDX to next large page + stosd + xor eax, eax + stosd + loop .loop2 + +; +; Done - restore ES:DI and return +; + pop di + pop es + ret + +; +; Get here if not enough space between boot file +; and bottom of the EBDA - print error and halt +; +PageTableError: + add sp, 2 ; Clear return address of CreatePageTable + mov bx, 15 + mov si, PageErrorMsg +.loop: + lodsb + test al, al + jz .halt + mov ah, 14 + int 16 + jmp .loop +.halt: + hlt + jmp .halt + + align 2, db 0 + +PageTableSegment: dw 0 +PageErrorMsg: db 'Unable to Allocate Memory for Page Table', 0 + +%endif + +; +; Data +; + + align 2, db 0 + +gdtr: + dw GDT_END - GDT_BASE - 1 + dd GDT_BASE + +; +; global descriptor table (GDT) +; + + align GDT_DESC_SIZE, db 0 + +GDT_BASE: +NULL_SEL: equ $ - GDT_BASE + times GDT_DESC_SIZE db 0 +LINEAR_SEL: equ $ - GDT_BASE + GDT_DESC 0x92, 0xCF +LINEAR_CODE_SEL: equ $ - GDT_BASE + GDT_DESC 0x9A, 0xCF +SYS_DATA_SEL: equ $ - GDT_BASE + GDT_DESC 0x92, 0xCF +SYS_CODE_SEL: equ $ - GDT_BASE + GDT_DESC 0x9A, 0xCF + times GDT_DESC_SIZE db 0 +%ifdef X64 +SYS_DATA64_SEL: equ $ - GDT_BASE + GDT_DESC 0x92, 0xCF +SYS_CODE64_SEL: equ $ - GDT_BASE + GDT_DESC 0x9A, 0xAF +%else + times GDT_DESC_SIZE db 0 +%endif + times GDT_DESC_SIZE db 0 +GDT_END: + + align 2, db 0 + +idtr: + dw IDT_END - IDT_BASE - 1 + dd IDT_BASE +%ifdef X64 + dd 0 +%endif + +; +; interrupt descriptor table (IDT) +; +; +; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ +; mappings. This implementation only uses the system timer and all other +; IRQs will remain masked. +; + + align IDT_DESC_SIZE, db 0 + +IDT_BASE: +%rep 20 ; Exceptions 0 - 19 + IDT_DESC +%endrep + times 84 * IDT_DESC_SIZE db 0 +%rep 16 ; Interrupts IRQ0 - IRQ15 mapped to vectors 0x68 - 0x77 + IDT_DESC +%endrep + times IDT_DESC_SIZE db 0 ; padding +IDT_END: + + align 4, db 0 + +MemoryMapSize: + dd 0 +MemoryMap: + + times SIZE_TO_STACK_16 - $ + $$ db 0 + +MyStack: +; below is the pieces of the IVT that is used to redirect INT 68h - 6fh +; back to INT 08h - 0fh when in real mode... It is 'org'ed to a +; known low address (20f00) so it can be set up by PlMapIrqToVect in +; 8259.c + +%assign i 8 +%rep 8 + int i + iret +%assign i i+1 +%endrep + + times 0x1e - $ + MyStack db 0 +BlockSignature: + dw 0xaa55 diff --git a/Legacy/README.md b/Legacy/README.md new file mode 100644 index 0000000000000000000000000000000000000000..607a769a4dd7421176089e32c4c113376cac9c6c --- /dev/null +++ b/Legacy/README.md @@ -0,0 +1,66 @@ +OpenDuetPkg +=========== + +Acidanthera variant of DuetPkg. Specialties: + +- Significantly improved boot performance. +- BDS is simplified to load `EFI/OC/OpenCore.efi`. +- EDID support removed for performance and compatibility. +- PCI option ROM support removed for security and performance. +- Setup and graphical interface removed. +- Resolved PCIe device path instead of PCI. +- Increased variable storage size to 64 KB. +- Always loads from bootstrapped volume first. +- Some changes inherited from Clover EFI bootloader. + +## Simplified bootstrap process + +1. `boot0` is loaded by BIOS from MBR at `7C00h`. +2. `boot0` finds active MBR or ESP GPT partition. +3. `boot0` loads `boot1` from found partition at `9000h`. +4. `boot1` finds `boot` file at partition root. +5. `boot1` loads `boot` at `20000h` (begins with `StartX64` or `StartIA32`). +6. `Start` enables paging (prebuilt for `X64` or generated for `IA32`). +7. `Start` switches to native CPU mode (`X64` or `IA32`) with paging. +8. `Start` jumps to concatentated `EfiXX` at `21000h` (`Efi64` or `Efi32`). +9. `EfiXX` loads `EfiLdr` (concatenated after `EfiXX`) at `10000h`. +10. `EfiLdr` decompresses and maps `DUETFV`, `DxeIpl`, `DxeCore`. +11. `EfiLdr` jumps to `DxeIpl`, which starts `DxeCore` from `DUETFV`. +12. `DxeCore` starts BDS, which loads `EFI/OC/OpenCore.efi`. + +| Name | PHYS | VIRT | +|:----------|:------------|:------------| +| `boot0` | `7C00h` | | +| `boot1` | `9000h` | | +| `Start` | `20000h` | `20000h` | +| `EfiXX` | `21000h` | `21000h` | +| `EfiLdr` | `22000h` | `10000h` | +| `DxeIpl`+ | `22000h+` | `???` | + +## Error codes + +- `BOOT MISMATCH!` - Bootstrap partition signature identification failed. + BDS code will try to lookup `EFI/OC/OpenCore.efi` on any partition in 3 seconds. +- `BOOT FAIL!` - No bootable `EFI/OC/OpenCore.efi` file found on any partition. + BDS code will dead-loop CPU in 3 seconds. + +## Compilation + +By default [ocbuild](https://github.com/acidanthera/ocbuild)-like compilation is used via `macbuild.tool`. +As an alternative it is possible to perform in-tree compilation by using `INTREE=1` environment variable: + +``` +TARGETARCH=X64 TARGET=RELEASE INTREE=1 DuetPkg/macbuild.tool +``` + +*Note*: 32-bit version may not work properly when compiled with older Xcode version (tested 11.4.1). + +## Configuration + +Builtin available drivers are set in `OpenDuetPkg.fdf` (included drivers) and `OpenDuetPkg.dsc` +(compiled drivers, may not be included). Adding more drivers may result in the need to +change firmware volume size. To do this update `NumBlocks` in `DuetPkg.fdf` +(number of 64 KB blocks in the firmware). + +*Note*: OHCI driver is not bundled with DuetPkg (and EDK II) and can be found in +`edk2-platforms/Silicon/Intel/QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe`. diff --git a/Library/DuetBdsLib/BdsConnect.c b/Library/DuetBdsLib/BdsConnect.c new file mode 100644 index 0000000000000000000000000000000000000000..e56a2de78670ae5d2469c724ccfe302294952dfd --- /dev/null +++ b/Library/DuetBdsLib/BdsConnect.c @@ -0,0 +1,444 @@ +/** @file + BDS Lib functions which relate with connect the device + +Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/** + This function will connect all the system driver to controller + first, and then special connect the default console, this make + sure all the system controller available and the platform default + console connected. + +**/ +VOID +EFIAPI +BdsLibConnectAll ( + VOID + ) +{ + // + // Connect the platform console first + // + BdsLibConnectAllDefaultConsoles (); + + // + // Generic way to connect all the drivers + // + BdsLibConnectAllDriversToAllControllers (); + + // + // Here we have the assumption that we have already had + // platform default console + // + BdsLibConnectAllDefaultConsoles (); +} + + +/** + This function will connect all the system drivers to all controllers + first, and then connect all the console devices the system current + have. After this we should get all the device work and console available + if the system have console device. + +**/ +VOID +BdsLibGenericConnectAll ( + VOID + ) +{ + // + // Most generic way to connect all the drivers + // + BdsLibConnectAllDriversToAllControllers (); + BdsLibConnectAllConsoles (); +} + +/** + This function will create all handles associate with every device + path node. If the handle associate with one device path node can not + be created successfully, then still give chance to do the dispatch, + which load the missing drivers if possible. + + @param DevicePathToConnect The device path which will be connected, it can be + a multi-instance device path + + @retval EFI_SUCCESS All handles associate with every device path node + have been created + @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles + @retval EFI_NOT_FOUND Create the handle associate with one device path + node failed + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath; + EFI_DEVICE_PATH_PROTOCOL *Instance; + EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; + EFI_DEVICE_PATH_PROTOCOL *Next; + EFI_HANDLE Handle; + EFI_HANDLE PreviousHandle; + UINTN Size; + EFI_TPL CurrentTpl; + + if (DevicePathToConnect == NULL) { + return EFI_SUCCESS; + } + + CurrentTpl = EfiGetCurrentTpl (); + + DevicePath = DuplicateDevicePath (DevicePathToConnect); + if (DevicePath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyOfDevicePath = DevicePath; + + do { + // + // The outer loop handles multi instance device paths. + // Only console variables contain multiple instance device paths. + // + // After this call DevicePath points to the next Instance + // + Instance = GetNextDevicePathInstance (&DevicePath, &Size); + if (Instance == NULL) { + FreePool (CopyOfDevicePath); + return EFI_OUT_OF_RESOURCES; + } + + Next = Instance; + while (!IsDevicePathEndType (Next)) { + Next = NextDevicePathNode (Next); + } + + SetDevicePathEndNode (Next); + + // + // Start the real work of connect with RemainingDevicePath + // + PreviousHandle = NULL; + do { + // + // Find the handle that best matches the Device Path. If it is only a + // partial match the remaining part of the device path is returned in + // RemainingDevicePath. + // + RemainingDevicePath = Instance; + Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle); + + if (!EFI_ERROR (Status)) { + if (Handle == PreviousHandle) { + // + // If no forward progress is made try invoking the Dispatcher. + // A new FV may have been added to the system an new drivers + // may now be found. + // Status == EFI_SUCCESS means a driver was dispatched + // Status == EFI_NOT_FOUND means no new drivers were dispatched + // + if (CurrentTpl == TPL_APPLICATION) { + // + // Dispatch calls LoadImage/StartImage which cannot run at TPL > TPL_APPLICATION + // + Status = gDS->Dispatch (); + } else { + // + // Always return EFI_NOT_FOUND here + // to prevent dead loop when control handle is found but connection failded case + // + Status = EFI_NOT_FOUND; + } + } + + if (!EFI_ERROR (Status)) { + PreviousHandle = Handle; + // + // Connect all drivers that apply to Handle and RemainingDevicePath, + // the Recursive flag is FALSE so only one level will be expanded. + // + // Do not check the connect status here, if the connect controller fail, + // then still give the chance to do dispatch, because partial + // RemainingDevicepath may be in the new FV + // + // 1. If the connect fail, RemainingDevicepath and handle will not + // change, so next time will do the dispatch, then dispatch's status + // will take effect + // 2. If the connect success, the RemainingDevicepath and handle will + // change, then avoid the dispatch, we have chance to continue the + // next connection + // + gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE); + } + } + // + // Loop until RemainingDevicePath is an empty device path + // + } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath)); + + } while (DevicePath != NULL); + + if (CopyOfDevicePath != NULL) { + FreePool (CopyOfDevicePath); + } + // + // All handle with DevicePath exists in the handle database + // + return Status; +} + +/** + This function will connect all current system handles recursively. + + gBS->ConnectController() service is invoked for each handle exist in system handler buffer. + If the handle is bus type handler, all childrens also will be connected recursively + by gBS->ConnectController(). + + @retval EFI_SUCCESS All handles and it's child handle have been connected + @retval EFI_STATUS Error status returned by of gBS->LocateHandleBuffer(). + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectAllEfi ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; +} + +/** + This function will disconnect all current system handles. + + gBS->DisconnectController() is invoked for each handle exists in system handle buffer. + If handle is a bus type handle, all childrens also are disconnected recursively by + gBS->DisconnectController(). + + @retval EFI_SUCCESS All handles have been disconnected + @retval EFI_STATUS Error status returned by of gBS->LocateHandleBuffer(). + +**/ +EFI_STATUS +EFIAPI +BdsLibDisconnectAllEfi ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + + // + // Disconnect all + // + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + gBS->DisconnectController (HandleBuffer[Index], NULL, NULL); + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; +} + +/** + Connects all drivers to all controllers. + This function make sure all the current system driver will manage + the corresponding controllers if have. And at the same time, make + sure all the system controllers have driver to manage it if have. + +**/ +VOID +EFIAPI +BdsLibConnectAllDriversToAllControllers ( + VOID + ) +{ + EFI_STATUS Status; + + do { + // + // Connect All EFI 1.10 drivers following EFI 1.10 algorithm + // + BdsLibConnectAllEfi (); + // + // Check to see if it's possible to dispatch an more DXE drivers. + // The BdsLibConnectAllEfi () may have made new DXE drivers show up. + // If anything is Dispatched Status == EFI_SUCCESS and we will try + // the connect again. + // + Status = gDS->Dispatch (); + + } while (!EFI_ERROR (Status)); +} + + +/** + Connect the specific Usb device which match the short form device path, + and whose bus is determined by Host Controller (Uhci or Ehci). + + @param HostControllerPI Uhci (0x00) or Ehci (0x20) or Both uhci and ehci + (0xFF) + @param RemainingDevicePath a short-form device path that starts with the first + element being a USB WWID or a USB Class device + path + + @return EFI_INVALID_PARAMETER RemainingDevicePath is NULL pointer. + RemainingDevicePath is not a USB device path. + Invalid HostControllerPI type. + @return EFI_SUCCESS Success to connect USB device + @return EFI_NOT_FOUND Fail to find handle for USB controller to connect. + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectUsbDevByShortFormDP( + IN UINT8 HostControllerPI, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleArray; + UINTN HandleArrayCount; + UINTN Index; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Class[3]; + BOOLEAN AtLeastOneConnected; + + // + // Check the passed in parameters + // + if (RemainingDevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((DevicePathType (RemainingDevicePath) != MESSAGING_DEVICE_PATH) || + ((DevicePathSubType (RemainingDevicePath) != MSG_USB_CLASS_DP) + && (DevicePathSubType (RemainingDevicePath) != MSG_USB_WWID_DP) + )) { + return EFI_INVALID_PARAMETER; + } + + if (HostControllerPI != 0xFF && + HostControllerPI != 0x00 && + HostControllerPI != 0x10 && + HostControllerPI != 0x20 && + HostControllerPI != 0x30) { + return EFI_INVALID_PARAMETER; + } + + // + // Find the usb host controller firstly, then connect with the remaining device path + // + AtLeastOneConnected = FALSE; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleArrayCount, + &HandleArray + ); + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < HandleArrayCount; Index++) { + Status = gBS->HandleProtocol ( + HandleArray[Index], + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo + ); + if (!EFI_ERROR (Status)) { + // + // Check whether the Pci device is the wanted usb host controller + // + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class); + if (!EFI_ERROR (Status)) { + if ((PCI_CLASS_SERIAL == Class[2]) && + (PCI_CLASS_SERIAL_USB == Class[1])) { + if (HostControllerPI == Class[0] || HostControllerPI == 0xFF) { + Status = gBS->ConnectController ( + HandleArray[Index], + NULL, + RemainingDevicePath, + FALSE + ); + if (!EFI_ERROR(Status)) { + AtLeastOneConnected = TRUE; + } + } + } + } + } + } + + if (HandleArray != NULL) { + FreePool (HandleArray); + } + + if (AtLeastOneConnected) { + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} diff --git a/Library/DuetBdsLib/BdsConsole.c b/Library/DuetBdsLib/BdsConsole.c new file mode 100644 index 0000000000000000000000000000000000000000..4a7201d07a129b6c7b56d4f2ea281b1caa89e3e5 --- /dev/null +++ b/Library/DuetBdsLib/BdsConsole.c @@ -0,0 +1,562 @@ +/** @file + BDS Lib functions which contain all the code to connect console device + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include + +#include +#include +#include +#include +#include +#include + +/** + Check if we need to save the EFI variable with "ConVarName" as name + as NV type + If ConVarName is NULL, then ASSERT(). + + @param ConVarName The name of the EFI variable. + + @retval TRUE Set the EFI variable as NV type. + @retval FALSE EFI variable as NV type can be set NonNV. +**/ +BOOLEAN +IsNvNeed ( + IN CHAR16 *ConVarName + ) +{ + CHAR16 *Ptr; + + ASSERT (ConVarName != NULL); + + Ptr = ConVarName; + + // + // If the variable includes "Dev" at last, we consider + // it does not support NV attribute. + // + while (*Ptr != L'\0') { + Ptr++; + } + + if (((INTN)((UINTN)Ptr - (UINTN)ConVarName) / sizeof (CHAR16)) <= 3) { + return TRUE; + } + + if ((*(Ptr - 3) == 'D') && (*(Ptr - 2) == 'e') && (*(Ptr - 1) == 'v')) { + return FALSE; + } + return TRUE; +} + +/** + Fill console handle in System Table if there are no valid console handle in. + + Firstly, check the validation of console handle in System Table. If it is invalid, + update it by the first console device handle from EFI console variable. + + @param VarName The name of the EFI console variable. + @param ConsoleGuid Specified Console protocol GUID. + @param ConsoleHandle On IN, console handle in System Table to be checked. + On OUT, new console handle in system table. + @param ProtocolInterface On IN, console protocol on console handle in System Table to be checked. + On OUT, new console protocol on new console handle in system table. + + @retval TRUE System Table has been updated. + @retval FALSE System Table hasn't been updated. + +**/ +BOOLEAN +UpdateSystemTableConsole ( + IN CHAR16 *VarName, + IN EFI_GUID *ConsoleGuid, + IN OUT EFI_HANDLE *ConsoleHandle, + IN OUT VOID **ProtocolInterface + ) +{ + EFI_STATUS Status; + UINTN DevicePathSize; + EFI_DEVICE_PATH_PROTOCOL *FullDevicePath; + EFI_DEVICE_PATH_PROTOCOL *VarConsole; + EFI_DEVICE_PATH_PROTOCOL *Instance; + VOID *Interface; + EFI_HANDLE NewHandle; + + ASSERT (VarName != NULL); + ASSERT (ConsoleHandle != NULL); + ASSERT (ConsoleGuid != NULL); + ASSERT (ProtocolInterface != NULL); + + if (*ConsoleHandle != NULL) { + Status = gBS->HandleProtocol ( + *ConsoleHandle, + ConsoleGuid, + &Interface + ); + if (Status == EFI_SUCCESS && Interface == *ProtocolInterface) { + // + // If ConsoleHandle is valid and console protocol on this handle also + // also matched, just return. + // + return FALSE; + } + } + + // + // Get all possible consoles device path from EFI variable + // + VarConsole = BdsLibGetVariableAndSize ( + VarName, + &gEfiGlobalVariableGuid, + &DevicePathSize + ); + if (VarConsole == NULL) { + // + // If there is no any console device, just return. + // + return FALSE; + } + + FullDevicePath = VarConsole; + + do { + // + // Check every instance of the console variable + // + Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize); + if (Instance == NULL) { + FreePool (FullDevicePath); + return FALSE; + } + + // + // Find console device handle by device path instance + // + Status = gBS->LocateDevicePath ( + ConsoleGuid, + &Instance, + &NewHandle + ); + if (!EFI_ERROR (Status)) { + // + // Get the console protocol on this console device handle + // + Status = gBS->HandleProtocol ( + NewHandle, + ConsoleGuid, + &Interface + ); + if (!EFI_ERROR (Status)) { + // + // Update new console handle in System Table. + // + *ConsoleHandle = NewHandle; + *ProtocolInterface = Interface; + return TRUE; + } + } + + } while (Instance != NULL); + + // + // No any available console device found. + // + return FALSE; +} + +/** + This function update console variable based on ConVarName, it can + add or remove one specific console device path from the variable + + @param ConVarName Console related variable name, ConIn, ConOut, + ErrOut. + @param CustomizedConDevicePath The console device path which will be added to + the console variable ConVarName, this parameter + can not be multi-instance. + @param ExclusiveDevicePath The console device path which will be removed + from the console variable ConVarName, this + parameter can not be multi-instance. + + @retval EFI_UNSUPPORTED The added device path is same to the removed one. + @retval EFI_SUCCESS Success add or remove the device path from the + console variable. + +**/ +EFI_STATUS +EFIAPI +BdsLibUpdateConsoleVariable ( + IN CHAR16 *ConVarName, + IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *VarConsole; + UINTN DevicePathSize; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath; + UINT32 Attributes; + + VarConsole = NULL; + DevicePathSize = 0; + + // + // Notes: check the device path point, here should check + // with compare memory + // + if (CustomizedConDevicePath == ExclusiveDevicePath) { + return EFI_UNSUPPORTED; + } + // + // Delete the ExclusiveDevicePath from current default console + // + VarConsole = BdsLibGetVariableAndSize ( + ConVarName, + &gEfiGlobalVariableGuid, + &DevicePathSize + ); + + // + // Initialize NewDevicePath + // + NewDevicePath = VarConsole; + + // + // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it. + // In the end, NewDevicePath is the final device path. + // + if (ExclusiveDevicePath != NULL && VarConsole != NULL) { + NewDevicePath = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath); + } + // + // Try to append customized device path to NewDevicePath. + // + if (CustomizedConDevicePath != NULL) { + if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) { + // + // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it. + // + NewDevicePath = BdsLibDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath); + // + // In the first check, the default console variable will be _ModuleEntryPoint, + // just append current customized device path + // + TempNewDevicePath = NewDevicePath; + NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath); + if (TempNewDevicePath != NULL) { + FreePool(TempNewDevicePath); + } + } + } + + // + // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV. + // + if (IsNvNeed (ConVarName)) { + // + // ConVarName has NV attribute. + // + Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE; + } else { + // + // ConVarName does not have NV attribute. + // + Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; + } + + // + // Finally, Update the variable of the default console by NewDevicePath + // + DevicePathSize = GetDevicePathSize (NewDevicePath); + Status = gRT->SetVariable ( + ConVarName, + &gEfiGlobalVariableGuid, + Attributes, + DevicePathSize, + NewDevicePath + ); + if ((DevicePathSize == 0) && (Status == EFI_NOT_FOUND)) { + Status = EFI_SUCCESS; + } + ASSERT_EFI_ERROR (Status); + + if (VarConsole == NewDevicePath) { + if (VarConsole != NULL) { + FreePool(VarConsole); + } + } else { + if (VarConsole != NULL) { + FreePool(VarConsole); + } + if (NewDevicePath != NULL) { + FreePool(NewDevicePath); + } + } + + return Status; + +} + + +/** + Connect the console device base on the variable ConVarName, if + device path of the ConVarName is multi-instance device path and + anyone of the instances is connected success, then this function + will return success. + If the handle associate with one device path node can not + be created successfully, then still give chance to do the dispatch, + which load the missing drivers if possible.. + + @param ConVarName Console related variable name, ConIn, ConOut, + ErrOut. + + @retval EFI_NOT_FOUND There is not any console devices connected + success + @retval EFI_SUCCESS Success connect any one instance of the console + device path base on the variable ConVarName. + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectConsoleVariable ( + IN CHAR16 *ConVarName + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *StartDevicePath; + UINTN VariableSize; + EFI_DEVICE_PATH_PROTOCOL *Instance; + EFI_DEVICE_PATH_PROTOCOL *Next; + EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath; + UINTN Size; + BOOLEAN DeviceExist; + + Status = EFI_SUCCESS; + DeviceExist = FALSE; + + // + // Check if the console variable exist + // + StartDevicePath = BdsLibGetVariableAndSize ( + ConVarName, + &gEfiGlobalVariableGuid, + &VariableSize + ); + if (StartDevicePath == NULL) { + return EFI_UNSUPPORTED; + } + + CopyOfDevicePath = StartDevicePath; + do { + // + // Check every instance of the console variable + // + Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size); + if (Instance == NULL) { + FreePool (StartDevicePath); + return EFI_UNSUPPORTED; + } + + Next = Instance; + while (!IsDevicePathEndType (Next)) { + Next = NextDevicePathNode (Next); + } + + SetDevicePathEndNode (Next); + // + // Connect the USB console + // USB console device path is a short-form device path that + // starts with the first element being a USB WWID + // or a USB Class device path + // + if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) && + ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) + || (DevicePathSubType (Instance) == MSG_USB_WWID_DP) + )) { + Status = BdsLibConnectUsbDevByShortFormDP (0xFF, Instance); + if (!EFI_ERROR (Status)) { + DeviceExist = TRUE; + } + } else { + // + // Connect the instance device path + // + Status = BdsLibConnectDevicePath (Instance); + + if (EFI_ERROR (Status)) { + // + // Delete the instance from the console variable + // + BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance); + } else { + DeviceExist = TRUE; + } + } + FreePool(Instance); + } while (CopyOfDevicePath != NULL); + + FreePool (StartDevicePath); + + if (!DeviceExist) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + This function will search every simpletext device in current system, + and make every simpletext device as a potential console device. + +**/ +VOID +EFIAPI +BdsLibConnectAllConsoles ( + VOID + ) +{ + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *ConDevicePath; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + + Index = 0; + HandleCount = 0; + HandleBuffer = NULL; + ConDevicePath = NULL; + + // + // Update all the console variables + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleTextInProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + + for (Index = 0; Index < HandleCount; Index++) { + gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + (VOID **) &ConDevicePath + ); + BdsLibUpdateConsoleVariable (L"ConIn", ConDevicePath, NULL); + } + + if (HandleBuffer != NULL) { + FreePool(HandleBuffer); + HandleBuffer = NULL; + } + + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleTextOutProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + for (Index = 0; Index < HandleCount; Index++) { + gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + (VOID **) &ConDevicePath + ); + BdsLibUpdateConsoleVariable (L"ConOut", ConDevicePath, NULL); + BdsLibUpdateConsoleVariable (L"ErrOut", ConDevicePath, NULL); + } + + if (HandleBuffer != NULL) { + FreePool(HandleBuffer); + } + + // + // Connect all console variables + // + BdsLibConnectAllDefaultConsoles (); + +} + +/** + This function will connect console device base on the console + device variable ConIn, ConOut and ErrOut. + + @retval EFI_SUCCESS At least one of the ConIn and ConOut device have + been connected success. + @retval EFI_STATUS Return the status of BdsLibConnectConsoleVariable (). + +**/ +EFI_STATUS +EFIAPI +BdsLibConnectAllDefaultConsoles ( + VOID + ) +{ + EFI_STATUS Status; + BOOLEAN SystemTableUpdated; + + // + // Connect all default console variables + // + + // + // It seems impossible not to have any ConOut device on platform, + // so we check the status here. + // + Status = BdsLibConnectConsoleVariable (L"ConOut"); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Because possibly the platform is legacy free, in such case, + // ConIn devices (Serial Port and PS2 Keyboard ) does not exist, + // so we need not check the status. + // + BdsLibConnectConsoleVariable (L"ConIn"); + + // + // The _ModuleEntryPoint err out var is legal. + // + BdsLibConnectConsoleVariable (L"ErrOut"); + + SystemTableUpdated = FALSE; + // + // Fill console handles in System Table if no console device assignd. + // + if (UpdateSystemTableConsole (L"ConIn", &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **) &gST->ConIn)) { + SystemTableUpdated = TRUE; + } + if (UpdateSystemTableConsole (L"ConOut", &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **) &gST->ConOut)) { + SystemTableUpdated = TRUE; + } + if (UpdateSystemTableConsole (L"ErrOut", &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **) &gST->StdErr)) { + SystemTableUpdated = TRUE; + } + + if (SystemTableUpdated) { + // + // Update the CRC32 in the EFI System Table header + // + gST->Hdr.CRC32 = 0; + gBS->CalculateCrc32 ( + (UINT8 *) &gST->Hdr, + gST->Hdr.HeaderSize, + &gST->Hdr.CRC32 + ); + } + + return EFI_SUCCESS; +} diff --git a/Library/DuetBdsLib/BdsMisc.c b/Library/DuetBdsLib/BdsMisc.c new file mode 100644 index 0000000000000000000000000000000000000000..f36e591be1404f197f5369719e5d52064fe52269 --- /dev/null +++ b/Library/DuetBdsLib/BdsMisc.c @@ -0,0 +1,187 @@ +/** @file + Misc BDS library function + +Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include + + +/** + Read the EFI variable (VendorGuid/Name) and return a dynamically allocated + buffer, and the size of the buffer. If failure return NULL. + + @param Name String part of EFI variable name + @param VendorGuid GUID part of EFI variable name + @param VariableSize Returns the size of the EFI variable that was read + + @return Dynamically allocated memory that contains a copy of the EFI variable + Caller is responsible freeing the buffer. + @retval NULL Variable was not read + +**/ +VOID * +EFIAPI +BdsLibGetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VariableSize + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + VOID *Buffer; + + Buffer = NULL; + + // + // Pass in a zero size buffer to find the required buffer size. + // + BufferSize = 0; + Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Allocate the buffer to return + // + Buffer = AllocateZeroPool (BufferSize); + if (Buffer == NULL) { + *VariableSize = 0; + return NULL; + } + // + // Read variable into the allocated buffer. + // + Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer); + if (EFI_ERROR (Status)) { + FreePool (Buffer); + BufferSize = 0; + Buffer = NULL; + } + } + + *VariableSize = BufferSize; + return Buffer; +} + +/** + Delete the instance in Multi which matches partly with Single instance + + @param Multi A pointer to a multi-instance device path data + structure. + @param Single A pointer to a single-instance device path data + structure. + + @return This function will remove the device path instances in Multi which partly + match with the Single, and return the result device path. If there is no + remaining device path as a result, this function will return NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +BdsLibDelPartMatchInstance ( + IN EFI_DEVICE_PATH_PROTOCOL *Multi, + IN EFI_DEVICE_PATH_PROTOCOL *Single + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Instance; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath; + UINTN InstanceSize; + UINTN SingleDpSize; + UINTN Size; + + NewDevicePath = NULL; + TempNewDevicePath = NULL; + + if (Multi == NULL || Single == NULL) { + return Multi; + } + + Instance = GetNextDevicePathInstance (&Multi, &InstanceSize); + SingleDpSize = GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH; + InstanceSize -= END_DEVICE_PATH_LENGTH; + + while (Instance != NULL) { + + Size = (SingleDpSize < InstanceSize) ? SingleDpSize : InstanceSize; + + if ((CompareMem (Instance, Single, Size) != 0)) { + // + // Append the device path instance which does not match with Single + // + TempNewDevicePath = NewDevicePath; + NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance); + if (TempNewDevicePath != NULL) { + FreePool(TempNewDevicePath); + } + } + FreePool(Instance); + Instance = GetNextDevicePathInstance (&Multi, &InstanceSize); + InstanceSize -= END_DEVICE_PATH_LENGTH; + } + + return NewDevicePath; +} + +/** + Function compares a device path data structure to that of all the nodes of a + second device path instance. + + @param Multi A pointer to a multi-instance device path data + structure. + @param Single A pointer to a single-instance device path data + structure. + + @retval TRUE If the Single device path is contained within Multi device path. + @retval FALSE The Single device path is not match within Multi device path. + +**/ +BOOLEAN +EFIAPI +BdsLibMatchDevicePaths ( + IN EFI_DEVICE_PATH_PROTOCOL *Multi, + IN EFI_DEVICE_PATH_PROTOCOL *Single + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; + UINTN Size; + + if (Multi == NULL || Single == NULL) { + return FALSE; + } + + DevicePath = Multi; + DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size); + + // + // Search for the match of 'Single' in 'Multi' + // + while (DevicePathInst != NULL) { + // + // If the single device path is found in multiple device paths, + // return success + // + if (CompareMem (Single, DevicePathInst, Size) == 0) { + FreePool (DevicePathInst); + return TRUE; + } + + FreePool (DevicePathInst); + DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size); + } + + return FALSE; +} diff --git a/Library/DuetBdsLib/BdsPlatform.c b/Library/DuetBdsLib/BdsPlatform.c new file mode 100644 index 0000000000000000000000000000000000000000..1774e1bc10f18e587a4a048e3161d6801e61bd16 --- /dev/null +++ b/Library/DuetBdsLib/BdsPlatform.c @@ -0,0 +1,1110 @@ +/*++ + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + BdsPlatform.c + +Abstract: + + This file include all platform action which can be customized + by IBV/OEM. +--*/ + +#include "BdsPlatform.h" + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +EFI_GUID *gTableGuidArray[] = { + &gEfiAcpi10TableGuid, + &gEfiAcpiTableGuid, + &gEfiSmbiosTableGuid, + &gEfiSmbios3TableGuid +}; + +// +// BDS Platform Functions +// + +STATIC +EFI_STATUS +ConvertAcpiTable ( + IN UINTN TableLen, + IN OUT VOID **Table + ) +/*++ + +Routine Description: + Convert RSDP of ACPI Table if its location is lower than Address:0x100000 + Assumption here: + As in legacy Bios, ACPI table is required to place in E/F Seg, + So here we just check if the range is E/F seg, + and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS + +Arguments: + TableLen - Acpi RSDP length + Table - pointer to the table + +Returns: + EFI_SUCEESS - Convert Table successfully + Other - Failed + +--*/ +{ + VOID *AcpiTableOri; + VOID *AcpiTableNew; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS BufferPtr; + + AcpiTableOri = (VOID *)(UINTN)(*(UINT64*)(*Table)); + if (((UINTN)AcpiTableOri < 0x100000) && ((UINTN)AcpiTableOri > 0xE0000)) { + BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + EFI_SIZE_TO_PAGES (TableLen), + &BufferPtr + ); + ASSERT_EFI_ERROR (Status); + + AcpiTableNew = (VOID *)(UINTN) BufferPtr; + CopyMem (AcpiTableNew, AcpiTableOri, TableLen); + } else { + AcpiTableNew = AcpiTableOri; + } + + // + // Change configuration table Pointer + // + *Table = AcpiTableNew; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ConvertSmbiosTable ( + IN OUT VOID **Table + ) +/*++ + +Routine Description: + + Convert Smbios Table if the Location of the SMBios Table is lower than Addres 0x100000 + Assumption here: + As in legacy Bios, Smbios table is required to place in E/F Seg, + So here we just check if the range is F seg, + and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData +Arguments: + Table - pointer to the table + +Returns: + EFI_SUCEESS - Convert Table successfully + Other - Failed + +--*/ +{ + SMBIOS_TABLE_ENTRY_POINT *SmbiosTableNew; + SMBIOS_TABLE_ENTRY_POINT *SmbiosTableOri; + EFI_STATUS Status; + UINT32 SmbiosEntryLen; + UINT32 BufferLen; + EFI_PHYSICAL_ADDRESS BufferPtr; + + SmbiosTableNew = NULL; + + // + // Get Smibos configuration Table + // + SmbiosTableOri = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)(*(UINT64*)(*Table)); + + if ((SmbiosTableOri == NULL) || + ((UINTN)SmbiosTableOri > 0x100000) || + ((UINTN)SmbiosTableOri < 0xF0000)){ + return EFI_SUCCESS; + } + // + // Relocate the Smibos memory + // + BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS; + if (SmbiosTableOri->SmbiosBcdRevision != 0x21) { + SmbiosEntryLen = SmbiosTableOri->EntryPointLength; + } else { + // + // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1 + // + SmbiosEntryLen = 0x1F; + } + BufferLen = SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen) + SmbiosTableOri->TableLength; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiACPIMemoryNVS, + EFI_SIZE_TO_PAGES(BufferLen), + &BufferPtr + ); + ASSERT_EFI_ERROR (Status); + + SmbiosTableNew = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)BufferPtr; + CopyMem ( + SmbiosTableNew, + SmbiosTableOri, + SmbiosEntryLen + ); + // + // Get Smbios Structure table address, and make sure the start address is 32-bit align + // + BufferPtr += SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen); + CopyMem ( + (VOID *)(UINTN)BufferPtr, + (VOID *)(UINTN)(SmbiosTableOri->TableAddress), + SmbiosTableOri->TableLength + ); + SmbiosTableNew->TableAddress = (UINT32)BufferPtr; + SmbiosTableNew->SmbiosBcdRevision = 0x26; + SmbiosTableNew->IntermediateChecksum = 0; + SmbiosTableNew->IntermediateChecksum = CalculateCheckSum8 ( + (UINT8*)SmbiosTableNew + 0x10, SmbiosEntryLen - 0x10 + ); + // + // Change the SMBIOS pointer + // + *Table = SmbiosTableNew; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ConvertSystemTable ( + IN EFI_GUID *TableGuid, + IN OUT VOID **Table + ) +/*++ + +Routine Description: + Convert ACPI Table /Smbios Table /MP Table if its location is lower than Address:0x100000 + Assumption here: + As in legacy Bios, ACPI/Smbios/MP table is required to place in E/F Seg, + So here we just check if the range is E/F seg, + and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS + +Arguments: + TableGuid - Guid of the table + Table - pointer to the table + +Returns: + EFI_SUCEESS - Convert Table successfully + Other - Failed + +--*/ +{ + EFI_STATUS Status; + VOID *AcpiHeader; + UINTN AcpiTableLen; + + // + // If match acpi guid (1.0, 2.0, or later), Convert ACPI table according to version. + // + AcpiHeader = (VOID*)(UINTN)(*(UINT64 *)(*Table)); + + if (CompareGuid(TableGuid, &gEfiAcpiTableGuid) || CompareGuid(TableGuid, &gEfiAcpi20TableGuid)){ + if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved == 0x00){ + // + // If Acpi 1.0 Table, then RSDP structure doesn't contain Length field, use structure size + // + AcpiTableLen = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER); + } else if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved >= 0x02){ + // + // If Acpi 2.0 or later, use RSDP Length fied. + // + AcpiTableLen = ((EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Length; + } else { + // + // Invalid Acpi Version, return + // + return EFI_UNSUPPORTED; + } + Status = ConvertAcpiTable (AcpiTableLen, Table); + return Status; + } + + // + // If matches smbios guid, convert Smbios table. + // + if (CompareGuid(TableGuid, &gEfiSmbiosTableGuid) || + CompareGuid(TableGuid, &gEfiSmbios3TableGuid)){ + Status = ConvertSmbiosTable (Table); + return Status; + } + + return EFI_UNSUPPORTED; +} + +STATIC +VOID +GetSystemTablesFromHob ( + VOID + ) +/*++ + +Routine Description: + Find GUID'ed HOBs that contain EFI_PHYSICAL_ADDRESS of ACPI, SMBIOS, MPs tables + +Arguments: + None + +Returns: + None. + +--*/ +{ + EFI_PEI_HOB_POINTERS GuidHob; + EFI_PEI_HOB_POINTERS HobStart; + EFI_PHYSICAL_ADDRESS *Table; + UINTN Index; + + // + // Get Hob List + // + HobStart.Raw = GetHobList (); + // + // Iteratively add ACPI Table, SMBIOS Table, MPS Table to EFI System Table + // + for (Index = 0; Index < sizeof (gTableGuidArray) / sizeof (*gTableGuidArray); ++Index) { + GuidHob.Raw = GetNextGuidHob (gTableGuidArray[Index], HobStart.Raw); + if (GuidHob.Raw != NULL) { + Table = GET_GUID_HOB_DATA (GuidHob.Guid); + if (Table != NULL) { + // + // Check if Mps Table/Smbios Table/Acpi Table exists in E/F seg, + // According to UEFI Spec, we should make sure Smbios table, + // ACPI table and Mps tables kept in memory of specified type + // + ConvertSystemTable (gTableGuidArray[Index], (VOID**)&Table); + gBS->InstallConfigurationTable (gTableGuidArray[Index], (VOID *)Table); + } + } + } +} + +STATIC +VOID +UpdateMemoryMap ( + VOID + ) +{ + EFI_STATUS Status; + UINTN NumberOfDescriptors; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap; + UINT64 Capabilities; + EFI_PEI_HOB_POINTERS GuidHob; + VOID *Table; + MEMORY_DESC_HOB MemoryDescHob; + UINTN Index; + EFI_PHYSICAL_ADDRESS Memory; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + EFI_PHYSICAL_ADDRESS FirstNonConventionalAddr; + + // + // Promote reserved memory to system memory. + // + Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap); + ASSERT_EFI_ERROR (Status); + + for (Index = 0; Index < NumberOfDescriptors; ++Index) { + Capabilities = MemorySpaceMap[Index].Capabilities; + + if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeReserved + && (Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) + == (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)) { + Status = gDS->RemoveMemorySpace ( + MemorySpaceMap[Index].BaseAddress, + MemorySpaceMap[Index].Length + ); + if (!EFI_ERROR (Status)) { + Status = gDS->AddMemorySpace ( + (Capabilities & EFI_MEMORY_MORE_RELIABLE) == EFI_MEMORY_MORE_RELIABLE + ? EfiGcdMemoryTypeMoreReliable : EfiGcdMemoryTypeSystemMemory, + MemorySpaceMap[Index].BaseAddress, + MemorySpaceMap[Index].Length, + Capabilities &~ (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME) + ); + } + + ASSERT_EFI_ERROR (Status); + } + } + + gBS->FreePool (MemorySpaceMap); + + // + // Add ACPINVS, ACPIReclaim, and Reserved memory to MemoryMap. + // + GuidHob.Raw = GetFirstGuidHob (&gLdrMemoryDescriptorGuid); + if (GuidHob.Raw == NULL) { + return; + } + + Table = GET_GUID_HOB_DATA (GuidHob.Guid); + if (Table == NULL) { + return; + } + + MemoryDescHob.MemDescCount = *(UINTN *)Table; + MemoryDescHob.MemDesc = *(EFI_MEMORY_DESCRIPTOR **)((UINTN)Table + sizeof(UINTN)); + + FirstNonConventionalAddr = 0xFFFFFFFF; + for (Index = 0; Index < MemoryDescHob.MemDescCount; Index++) { + if (MemoryDescHob.MemDesc[Index].PhysicalStart < 0x100000) { + continue; + } + if (MemoryDescHob.MemDesc[Index].PhysicalStart >= 0x100000000ULL) { + continue; + } + if ((MemoryDescHob.MemDesc[Index].Type == EfiReservedMemoryType) + || (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) + || (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode) + || (MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) + || (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) { + + if (MemoryDescHob.MemDesc[Index].PhysicalStart < FirstNonConventionalAddr) { + FirstNonConventionalAddr = MemoryDescHob.MemDesc[Index].PhysicalStart; + } + + if ((MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) + || (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode)) { + // + // For RuntimeSevicesData and RuntimeServicesCode, they are BFV or DxeCore. + // The memory type is assigned in EfiLdr + // + Status = gDS->GetMemorySpaceDescriptor (MemoryDescHob.MemDesc[Index].PhysicalStart, &Descriptor); + if (EFI_ERROR (Status)) { + continue; + } + + if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) { + // + // BFV or tested DXE core + // + continue; + } + + // + // Untested DXE Core region, free and remove + // + Status = gDS->FreeMemorySpace ( + MemoryDescHob.MemDesc[Index].PhysicalStart, + LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT) + ); + + if (EFI_ERROR (Status)) { + continue; + } + + Status = gDS->RemoveMemorySpace ( + MemoryDescHob.MemDesc[Index].PhysicalStart, + LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT) + ); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Convert Runtime type to BootTime type + // + if (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) { + MemoryDescHob.MemDesc[Index].Type = EfiBootServicesData; + } else { + MemoryDescHob.MemDesc[Index].Type = EfiBootServicesCode; + } + + // + // PassThrough, let below code add and allocate. + // + } + // + // ACPI or reserved memory + // + Status = gDS->AddMemorySpace ( + EfiGcdMemoryTypeSystemMemory, + MemoryDescHob.MemDesc[Index].PhysicalStart, + LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT), + MemoryDescHob.MemDesc[Index].Attribute + ); + if (EFI_ERROR (Status)) { + continue; + } + + Memory = MemoryDescHob.MemDesc[Index].PhysicalStart; + Status = gBS->AllocatePages ( + AllocateAddress, + (EFI_MEMORY_TYPE)MemoryDescHob.MemDesc[Index].Type, + (UINTN)MemoryDescHob.MemDesc[Index].NumberOfPages, + &Memory + ); + if (EFI_ERROR (Status)) { + continue; + } + } + } + + // + // dmazar: Part of mem fix when "available" memory regions are marked as "reserved" + // if they were above first non-avaialable region in BIOS mem map. + // We have left those regions as EfiConventionalMemory in EfiLdr/Support.c GenMemoryMap() + // and now we will add them to GCD and UEFI mem map + // + for (Index = 0; Index < MemoryDescHob.MemDescCount; Index++) { + if (MemoryDescHob.MemDesc[Index].PhysicalStart < 0x100000) { + continue; + } + if (MemoryDescHob.MemDesc[Index].Type != EfiConventionalMemory) { + continue; + } + if (MemoryDescHob.MemDesc[Index].PhysicalStart < FirstNonConventionalAddr) { + continue; + } + // + // This is our candidate - add it. + // + gDS->AddMemorySpace ( + EfiGcdMemoryTypeSystemMemory, + MemoryDescHob.MemDesc[Index].PhysicalStart, + LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT), + MemoryDescHob.MemDesc[Index].Attribute + ); + } +} + +STATIC +EFI_STATUS +DisableUsbLegacySupport ( + VOID + ) +/*++ + +Routine Description: + Disable the USB legacy Support in all Ehci and Uhci. + This function assume all PciIo handles have been created in system. + +Arguments: + None + +Returns: + EFI_SUCCESS + EFI_NOT_FOUND +--*/ +{ + EFI_STATUS Status; + EFI_HANDLE *HandleArray = NULL; + UINTN HandleArrayCount; + UINTN Index; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Class[3]; + UINT16 Command; + UINT32 HcCapParams; + UINT32 ExtendCap; + UINT32 Value, mSaveValue; + INT32 TimeOut; + + // + // Find the usb host controller + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleArrayCount, + &HandleArray + ); + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < HandleArrayCount; Index++) { + Status = gBS->HandleProtocol ( + HandleArray[Index], + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo + ); + if (!EFI_ERROR (Status)) { + // + // Find the USB host controller controller + // + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class); + if (!EFI_ERROR (Status)) { + if ((PCI_CLASS_SERIAL == Class[2]) && + (PCI_CLASS_SERIAL_USB == Class[1])) { + if (PCI_IF_UHCI == Class[0]) { + // + // Found the UHCI, then disable the legacy support + // + Command = 0; + Status = PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0xC0, 1, &Command); + } else if (PCI_IF_EHCI == Class[0]) { + + // + // Found the EHCI, then disable the legacy support + // + Status = PciIo->Mem.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, ///< EHC_BAR_INDEX + (UINT64) 0x08, ///< EHC_HCCPARAMS_OFFSET + 1, + &HcCapParams + ); + + ExtendCap = (HcCapParams >> 8) & 0xFF; + // + // Disable the SMI in USBLEGCTLSTS firstly + // + // PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &mSaveValue); + // Value = mSaveValue & 0xFFFF0000; + // PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value); + + // + // Get EHCI Ownership from legacy bios + // + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value); + Value |= (0x1 << 24); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value); + + TimeOut = 40; + while (TimeOut--) { + gBS->Stall (500); + + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value); + + if ((Value & 0x01010000) == 0x01000000) { + break; + } + } + if (TimeOut < 0) { + // + // Disable the SMI in USBLEGCTLSTS if BIOS doesn't respond + // + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &mSaveValue); + Value = mSaveValue & 0xFFFF0000; + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value); + } + } + } + } + } + } + } else { + return Status; + } + + if (HandleArray) { + gBS->FreePool (HandleArray); + } + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ConnectRootBridge ( + VOID + ) +/*++ + +Routine Description: + + Connect RootBridge + +Arguments: + + None. + +Returns: + + EFI_SUCCESS - Connect RootBridge successfully. + EFI_STATUS - Connect RootBridge fail. + +--*/ +{ + EFI_STATUS Status; + EFI_HANDLE RootHandle; + + // + // Make all the PCI_IO protocols on PCI Seg 0 show up + // + BdsLibConnectDevicePath (gPlatformRootBridges[0]); + + Status = gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &gPlatformRootBridges[0], + &RootHandle + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +PrepareLpcBridgeDevicePath ( + IN EFI_HANDLE DeviceHandle + ) +/*++ + +Routine Description: + + Add IsaKeyboard to ConIn, + add IsaSerial to ConOut, ConIn, ErrOut. + LPC Bridge: 06 01 00 + +Arguments: + + DeviceHandle - Handle of PCIIO protocol. + +Returns: + + EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut. + EFI_STATUS - No LPC bridge is added. + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath = NULL; + Status = gBS->HandleProtocol ( + DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID*)&DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Register Keyboard + // + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode); + + BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +GetGopDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath, + OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath + ) +{ + UINTN Index; + EFI_STATUS Status; + EFI_HANDLE PciDeviceHandle; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath; + UINTN GopHandleCount; + EFI_HANDLE *GopHandleBuffer; + + if (PciDevicePath == NULL || GopDevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialize the GopDevicePath to be PciDevicePath + // + *GopDevicePath = PciDevicePath; + TempPciDevicePath = PciDevicePath; + + Status = gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &TempPciDevicePath, + &PciDeviceHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Try to connect this handle, so that GOP dirver could start on this + // device and create child handles with GraphicsOutput Protocol installed + // on them, then we get device paths of these child handles and select + // them as possible console device. + // + gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE); + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiGraphicsOutputProtocolGuid, + NULL, + &GopHandleCount, + &GopHandleBuffer + ); + if (!EFI_ERROR (Status)) { + // + // Add all the child handles as possible Console Device + // + for (Index = 0; Index < GopHandleCount; Index++) { + Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath); + if (EFI_ERROR (Status)) { + continue; + } + if (CompareMem ( + PciDevicePath, + TempDevicePath, + GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH + ) == 0) { + // + // In current implementation, we only enable one of the child handles + // as console device, i.e. sotre one of the child handle's device + // path to variable "ConOut" + // In future, we could select all child handles to be console device + // + + *GopDevicePath = TempDevicePath; + + // + // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath() + // Add the integrity GOP device path. + // + BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath); + BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL); + } + } + gBS->FreePool (GopHandleBuffer); + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +PreparePciVgaDevicePath ( + IN EFI_HANDLE DeviceHandle + ) +/*++ + +Routine Description: + + Add PCI VGA to ConOut. + PCI VGA: 03 00 00 + +Arguments: + + DeviceHandle - Handle of PCIIO protocol. + +Returns: + + EFI_SUCCESS - PCI VGA is added to ConOut. + EFI_STATUS - No PCI VGA device is added. + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *GopDevicePath; + + DevicePath = NULL; + Status = gBS->HandleProtocol ( + DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID*)&DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + GetGopDevicePath (DevicePath, &GopDevicePath); + DevicePath = GopDevicePath; + + BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +DetectAndPreparePlatformPciDevicePath ( + BOOLEAN DetectVgaOnly + ) +/*++ + +Routine Description: + + Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut + +Arguments: + + DetectVgaOnly - Only detect VGA device if it's TRUE. + +Returns: + + EFI_SUCCESS - PCI Device check and Console variable update successfully. + EFI_STATUS - PCI Device check or Console variable update fail. + +--*/ +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + // + // Start to check all the PciIo to find all possible device + // + HandleCount = 0; + HandleBuffer = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID*)&PciIo); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Check for all PCI device + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + continue; + } + + if (!DetectVgaOnly) { + // + // Here we decide whether it is LPC Bridge + // + if ((IS_PCI_LPC (&Pci)) + || ((IS_PCI_ISA_PDECODE (&Pci)) + && (Pci.Hdr.VendorId == 0x8086) + && (Pci.Hdr.DeviceId == 0x7110))) { + // + // Add IsaKeyboard to ConIn, + // add IsaSerial to ConOut, ConIn, ErrOut + // + PrepareLpcBridgeDevicePath (HandleBuffer[Index]); + continue; + } + } + + // + // Here we decide which VGA device to enable in PCI bus + // + if (IS_PCI_VGA (&Pci)) { + // + // Add them to ConOut. + // + PreparePciVgaDevicePath (HandleBuffer[Index]); + continue; + } + } + + gBS->FreePool (HandleBuffer); + + return EFI_SUCCESS; +} + +VOID +EFIAPI +PlatformBdsInit ( + VOID + ) +/*++ + +Routine Description: + + Platform Bds init. Include the platform firmware vendor, revision + and so crc check. + +Arguments: + +Returns: + + None. + +--*/ +{ + GetSystemTablesFromHob (); + + UpdateMemoryMap (); + + // + // Append Usb Keyboard short form DevicePath into "ConInDev" + // + BdsLibUpdateConsoleVariable ( + VarConsoleInpDev, + (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath, + NULL + ); +} + +EFI_STATUS +BdsConnectConsole ( + IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole + ) +/*++ + +Routine Description: + + Connect the predefined platform default console device. Always try to find + and enable the vga device if have. + +Arguments: + + PlatformConsole - Predfined platform default console device array. + +Returns: + + EFI_SUCCESS - Success connect at least one ConIn and ConOut + device, there must have one ConOut device is + active vga device. + + EFI_STATUS - Return the status of + BdsLibConnectAllDefaultConsoles () + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *VarConout; + EFI_DEVICE_PATH_PROTOCOL *VarConin; + UINTN DevicePathSize; + + // + // Connect RootBridge + // + ConnectRootBridge (); + + VarConout = BdsLibGetVariableAndSize ( + VarConsoleOut, + &gEfiGlobalVariableGuid, + &DevicePathSize + ); + VarConin = BdsLibGetVariableAndSize ( + VarConsoleInp, + &gEfiGlobalVariableGuid, + &DevicePathSize + ); + + if (VarConout == NULL || VarConin == NULL) { + // + // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut + // + DetectAndPreparePlatformPciDevicePath (FALSE); + + // + // Have chance to connect the platform default console, + // the platform default console is the minimue device group + // the platform should support + // + for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) { + // + // Update the console variable with the connect type + // + if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) { + BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL); + } + if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) { + BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL); + } + if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) { + BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL); + } + } + } else { + // + // Only detect VGA device and add them to ConOut + // + DetectAndPreparePlatformPciDevicePath (TRUE); + } + + // + // The ConIn devices connection will start the USB bus, should disable all + // Usb legacy support firstly. + // Caution: Must ensure the PCI bus driver has been started. Since the + // ConnectRootBridge() will create all the PciIo protocol, it's safe here now + // + DisableUsbLegacySupport (); + + // + // Connect the all the default console with current console variable + // + Status = BdsLibConnectAllDefaultConsoles (); + + return Status; +} + +VOID +EFIAPI +PlatformBdsPolicyBehavior ( + VOID + ) +/*++ + +Routine Description: + + The function will excute with as the platform policy, current policy + is driven by boot mode. IBV/OEM can customize this code for their specific + policy action. + +Arguments: + + DriverOptionList - The header of the driver option link list + + BootOptionList - The header of the boot option link list + +Returns: + + None. + +--*/ +{ + BdsConnectConsole (gPlatformConsole); + + BdsLibConnectAll (); +} diff --git a/Library/DuetBdsLib/BdsPlatform.h b/Library/DuetBdsLib/BdsPlatform.h new file mode 100644 index 0000000000000000000000000000000000000000..86953165c935da6e3ec68641466c10bf37a9ba69 --- /dev/null +++ b/Library/DuetBdsLib/BdsPlatform.h @@ -0,0 +1,130 @@ +/*++ + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + BdsPlatform.h + +Abstract: + + Head file for BDS Platform specific code + +--*/ + +#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_ +#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_ + +#include +#include +#include + +extern BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[]; +extern EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[]; +extern EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[]; +extern ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode; + +// +// attributes for reserved memory before it is promoted to system memory +// +#define EFI_MEMORY_PRESENT 0x0100000000000000ULL +#define EFI_MEMORY_INITIALIZED 0x0200000000000000ULL +#define EFI_MEMORY_TESTED 0x0400000000000000ULL + +#define VarConsoleInpDev L"ConInDev" +#define VarConsoleInp L"ConIn" +#define VarConsoleOutDev L"ConOutDev" +#define VarConsoleOut L"ConOut" +#define VarErrorOutDev L"ErrOutDev" +#define VarErrorOut L"ErrOut" + +#define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0) + +#define PCI_DEVICE_PATH_NODE(Func, Dev) \ + { \ + { \ + HARDWARE_DEVICE_PATH, \ + HW_PCI_DP, \ + { \ + (UINT8) (sizeof (PCI_DEVICE_PATH)), \ + (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \ + } \ + }, \ + (Func), \ + (Dev) \ + } + +#define PNPID_DEVICE_PATH_NODE(PnpId) \ + { \ + { \ + ACPI_DEVICE_PATH, \ + ACPI_DP, \ + { \ + (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \ + (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \ + } \ + }, \ + EISA_PNP_ID((PnpId)), \ + 0 \ + } + +#define gPciRootBridge \ + PNPID_DEVICE_PATH_NODE(0x0A03) + +#define gPciIsaBridge \ + PCI_DEVICE_PATH_NODE(0, 0x1f) + +#define gPnpPs2Keyboard \ + PNPID_DEVICE_PATH_NODE(0x0303) + +#define gEndEntire \ + { \ + END_DEVICE_PATH_TYPE, \ + END_ENTIRE_DEVICE_PATH_SUBTYPE, \ + { \ + END_DEVICE_PATH_LENGTH, \ + 0 \ + } \ + } + +#define EFI_SYSTEM_TABLE_MAX_ADDRESS 0xFFFFFFFF +#define SYS_TABLE_PAD(ptr) (((~ptr) +1) & 0x07 ) + +// +// Platform Root Bridge +// +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_ROOT_BRIDGE_DEVICE_PATH; + +typedef struct { + ACPI_HID_DEVICE_PATH PciRootBridge; + PCI_DEVICE_PATH IsaBridge; + ACPI_HID_DEVICE_PATH Keyboard; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_DUMMY_ISA_KEYBOARD_DEVICE_PATH; + +typedef struct { + USB_CLASS_DEVICE_PATH UsbClass; + EFI_DEVICE_PATH_PROTOCOL End; +} USB_CLASS_FORMAT_DEVICE_PATH; + +// +// the short form device path for Usb keyboard +// +#define CLASS_HID 3 +#define SUBCLASS_BOOT 1 +#define PROTOCOL_KEYBOARD 1 + +extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath; +extern PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0; + +#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_ diff --git a/Library/DuetBdsLib/DuetBdsLib.inf b/Library/DuetBdsLib/DuetBdsLib.inf new file mode 100644 index 0000000000000000000000000000000000000000..a04fb6abedd942a3001dc4f91f8d6c546d958514 --- /dev/null +++ b/Library/DuetBdsLib/DuetBdsLib.inf @@ -0,0 +1,73 @@ +## @file +# +# Duet BDS defines library. +# +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DuetBdsLib + FILE_GUID = F90C932F-196F-4AFC-9A10-DD3081DE9F83 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DuetBdsLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + BdsConnect.c + BdsMisc.c + BdsPlatform.c + BdsPlatform.h + BdsConsole.c + PlatformData.c + +[Packages] + OpenCorePkg/OpenCorePkg.dec + OpenCorePkg/OpenDuetPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + DxeServicesTableLib + HobLib + MemoryAllocationLib + PcdLib + PrintLib + TimerLib + UefiBootServicesTableLib + UefiLib + UefiRuntimeServicesTableLib + +[Guids] + gEfiGlobalVariableGuid + gEfiAcpi10TableGuid + gEfiAcpi20TableGuid + gEfiSmbiosTableGuid + gEfiSmbios3TableGuid + gEfiAcpiTableGuid + gLdrMemoryDescriptorGuid + +[Protocols] + gEfiPciIoProtocolGuid # PROTOCOL CONSUMES + gEfiSimpleTextInProtocolGuid # PROTOCOL CONSUMES + gEfiDevicePathProtocolGuid # PROTOCOL CONSUMES + gEfiGraphicsOutputProtocolGuid # PROTOCOL SOMETIMES_CONSUMES diff --git a/Library/DuetBdsLib/PlatformData.c b/Library/DuetBdsLib/PlatformData.c new file mode 100644 index 0000000000000000000000000000000000000000..f8f128c5606500420d6df7439c762ed16923883d --- /dev/null +++ b/Library/DuetBdsLib/PlatformData.c @@ -0,0 +1,103 @@ +/*++ + +Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + PlatformData.c + +Abstract: + + Defined the platform specific device path which will be used by + platform Bbd to perform the platform policy connect. + +--*/ + +#include "BdsPlatform.h" + +ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard; + +// +// Predefined platform root bridge +// +PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0 = { + gPciRootBridge, + gEndEntire +}; + +EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[] = { + (EFI_DEVICE_PATH_PROTOCOL *) &gPlatformRootBridge0, + NULL +}; + +USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = { + { + { + MESSAGING_DEVICE_PATH, + MSG_USB_CLASS_DP, + { + (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)), + (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8) + } + }, + 0xffff, // VendorId + 0xffff, // ProductId + CLASS_HID, // DeviceClass + SUBCLASS_BOOT, // DeviceSubClass + PROTOCOL_KEYBOARD // DeviceProtocol + }, + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + + +// +// Platform specific Dummy ISA keyboard device path +// + +PLATFORM_DUMMY_ISA_KEYBOARD_DEVICE_PATH gDummyIsaKeyboardDevicePath = { + gPciRootBridge, + gPciIsaBridge, + gPnpPs2Keyboard, + gEndEntire +}; + +// +// Predefined platform default console device path +// +BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = { + // + // need update dynamically + // + { + (EFI_DEVICE_PATH_PROTOCOL *) &gDummyIsaKeyboardDevicePath, + (CONSOLE_IN | STD_ERROR) + }, + { + (EFI_DEVICE_PATH_PROTOCOL*) &gUsbClassKeyboardDevicePath, + CONSOLE_IN + }, + { + NULL, + 0 + } +}; + +// +// Predefined platform specific driver option +// +EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[] = { NULL }; diff --git a/Library/DuetTimerLib/DuetTimerLib.inf b/Library/DuetTimerLib/DuetTimerLib.inf new file mode 100644 index 0000000000000000000000000000000000000000..d8c7b24d27aeeacecfbce2e1978cb45af41b76d9 --- /dev/null +++ b/Library/DuetTimerLib/DuetTimerLib.inf @@ -0,0 +1,54 @@ +## @file +# Timer Library implementation for Boot Timer moudles that require timer services. +# +# Timer Library that uses CPU resources to provide calibrated +# delays on IA-32 and x64, and uses ITC on IPF. Note: Because CpuLocalApci +# and ITC could be programmed by OS, it cannot be used by SMM drivers +# and runtime drivers, ACPI timer is recommended for SMM drivers and RUNTIME +# drivers. +# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DuetTimerLib + FILE_GUID = 5F9A01F5-726E-4f59-809D-887F4766734E + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.Ia32] + X86TimerLib.c + +[Sources.X64] + X86TimerLib.c + + +[Packages] + MdePkg/MdePkg.dec + OpenCorePkg/OpenCorePkg.dec + OpenCorePkg/OpenDuetPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + HobLib + IoLib + +[Guids] + gEfiAcpiDescriptionGuid + diff --git a/Library/DuetTimerLib/X86TimerLib.c b/Library/DuetTimerLib/X86TimerLib.c new file mode 100644 index 0000000000000000000000000000000000000000..de645fe1a242112f3489bafebcb0808a29491069 --- /dev/null +++ b/Library/DuetTimerLib/X86TimerLib.c @@ -0,0 +1,281 @@ +/** @file + Timer Library functions built upon ACPI on IA32/x64. + + ACPI power management timer is a 24-bit or 32-bit fixed rate free running count-up + timer that runs off a 3.579545 MHz clock. + When startup, Duet will check the FADT to determine whether the PM timer is a + 32-bit or 24-bit timer. + + Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +EFI_ACPI_DESCRIPTION *gAcpiDesc = NULL; + +/** + Internal function to get Acpi information from HOB. + + @return Pointer to ACPI description structure. +**/ +EFI_ACPI_DESCRIPTION* +InternalGetApciDescrptionTable ( + VOID + ) +{ + EFI_PEI_HOB_POINTERS GuidHob; + + if (gAcpiDesc != NULL) { + return gAcpiDesc; + } + + GuidHob.Raw = GetFirstGuidHob (&gEfiAcpiDescriptionGuid); + if (GuidHob.Raw != NULL) { + gAcpiDesc = GET_GUID_HOB_DATA (GuidHob.Guid); + DEBUG ((EFI_D_INFO, "ACPI Timer: PM_TMR_BLK.RegisterBitWidth = 0x%X\n", gAcpiDesc->PM_TMR_BLK.RegisterBitWidth)); + DEBUG ((EFI_D_INFO, "ACPI Timer: PM_TMR_BLK.Address = 0x%X\n", gAcpiDesc->PM_TMR_BLK.Address)); + return gAcpiDesc; + } else { + DEBUG ((EFI_D_ERROR, "Fail to get Acpi description table from hob\n")); + return NULL; + } +} + +/** + Internal function to read the current tick counter of ACPI. + + @return The tick counter read. + +**/ +STATIC +UINT32 +InternalAcpiGetTimerTick ( + VOID + ) +{ + return IoRead32 ((UINTN)gAcpiDesc->PM_TMR_BLK.Address); +} + +/** + Stalls the CPU for at least the given number of ticks. + + Stalls the CPU for at least the given number of ticks. It's invoked by + MicroSecondDelay() and NanoSecondDelay(). + + @param Delay A period of time to delay in ticks. + +**/ +STATIC +VOID +InternalAcpiDelay ( + IN UINT32 Delay + ) +{ + UINT32 Ticks; + UINT32 Times; + + Times = Delay >> (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2); + Delay &= (1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2)) - 1; + do { + // + // The target timer count is calculated here + // + Ticks = InternalAcpiGetTimerTick () + Delay; + Delay = 1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2); + // + // Wait until time out + // Delay >= 2^23 (if ACPI provide 24-bit timer) or Delay >= 2^31 (if ACPI + // provide 32-bit timer) could not be handled by this function + // Timer wrap-arounds are handled correctly by this function + // + while (((Ticks - InternalAcpiGetTimerTick ()) & (1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 1))) == 0) { + CpuPause (); + } + } while (Times-- > 0); +} + +/** + Stalls the CPU for at least the given number of microseconds. + + Stalls the CPU for the number of microseconds specified by MicroSeconds. + + @param MicroSeconds The minimum number of microseconds to delay. + + @return MicroSeconds + +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + + if (InternalGetApciDescrptionTable() == NULL) { + return MicroSeconds; + } + + InternalAcpiDelay ( + (UINT32)DivU64x32 ( + MultU64x32 ( + MicroSeconds, + 3579545 + ), + 1000000u + ) + ); + return MicroSeconds; +} + +/** + Stalls the CPU for at least the given number of nanoseconds. + + Stalls the CPU for the number of nanoseconds specified by NanoSeconds. + + @param NanoSeconds The minimum number of nanoseconds to delay. + + @return NanoSeconds + +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + if (InternalGetApciDescrptionTable() == NULL) { + return NanoSeconds; + } + + InternalAcpiDelay ( + (UINT32)DivU64x32 ( + MultU64x32 ( + NanoSeconds, + 3579545 + ), + 1000000000u + ) + ); + return NanoSeconds; +} + +/** + Retrieves the current value of a 64-bit free running performance counter. + + Retrieves the current value of a 64-bit free running performance counter. The + counter can either count up by 1 or count down by 1. If the physical + performance counter counts by a larger increment, then the counter values + must be translated. The properties of the counter can be retrieved from + GetPerformanceCounterProperties(). + + @return The current value of the free running performance counter. + +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + if (InternalGetApciDescrptionTable() == NULL) { + return 0; + } + + return (UINT64)InternalAcpiGetTimerTick (); +} + +/** + Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter starts + with immediately after is it rolls over is returned in StartValue. If + EndValue is not NULL, then the value that the performance counter end with + immediately before it rolls over is returned in EndValue. The 64-bit + frequency of the performance counter in Hz is always returned. If StartValue + is less than EndValue, then the performance counter counts up. If StartValue + is greater than EndValue, then the performance counter counts down. For + example, a 64-bit free running counter that counts up would have a StartValue + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter + that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0. + + @param StartValue The value the performance counter starts with when it + rolls over. + @param EndValue The value that the performance counter ends with before + it rolls over. + + @return The frequency in Hz. + +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + OUT UINT64 *StartValue, OPTIONAL + OUT UINT64 *EndValue OPTIONAL + ) +{ + if (InternalGetApciDescrptionTable() == NULL) { + return 0; + } + + if (StartValue != NULL) { + *StartValue = 0; + } + + if (EndValue != NULL) { + *EndValue = (1 << gAcpiDesc->PM_TMR_BLK.RegisterBitWidth) - 1; + } + + return 3579545; +} + +/** + Converts elapsed ticks of performance counter to time in nanoseconds. + + This function converts the elapsed ticks of running performance counter to + time value in unit of nanoseconds. + + @param Ticks The number of elapsed ticks of running performance counter. + + @return The elapsed time in nanoseconds. + +**/ +UINT64 +EFIAPI +GetTimeInNanoSecond ( + IN UINT64 Ticks + ) +{ + UINT64 NanoSeconds; + UINT32 Remainder; + + // + // Ticks + // Time = --------- x 1,000,000,000 + // Frequency + // + NanoSeconds = MultU64x32 (DivU64x32Remainder (Ticks, 3579545, &Remainder), 1000000000u); + + // + // Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000) + // will not overflow 64-bit. + // + NanoSeconds += DivU64x32 (MultU64x32 ((UINT64) Remainder, 1000000000u), 3579545); + + return NanoSeconds; +} diff --git a/OpenCorePkg.dec b/OpenCorePkg.dec index 3bbfa97ad078f1b71bdfc6243455951cba9fb827..1e83353710f8c97b905334014da972b218c50b61 100755 --- a/OpenCorePkg.dec +++ b/OpenCorePkg.dec @@ -513,6 +513,9 @@ ## Include/Intel/Protocol/LegacyRegion.h gEfiLegacyRegionProtocolGuid = { 0x0fc9013a, 0x0568, 0x4ba9, { 0x9b, 0x7e, 0xc9, 0xc3, 0x90, 0xa6, 0x60, 0x9b }} + ## Include/Duet/Protocol/VgaMiniPort.h + gEfiVgaMiniPortProtocolGuid = { 0xc7735a2f, 0x88f5, 0x4882, { 0xae, 0x63, 0xfa, 0xac, 0x8c, 0x8b, 0x86, 0xb3 }} + ## Include/Apple/Protocol/Apple80211.h gApple80211ProtocolGuid = { 0x71B4903C, 0x14EC, 0x42C4, { 0xBD, 0xC6, 0xCE, 0x14, 0x49, 0x93, 0x0E, 0x49 }} diff --git a/OpenDuetPkg.dec b/OpenDuetPkg.dec new file mode 100644 index 0000000000000000000000000000000000000000..27b875600ae1de0b217274efcf55daa30112a022 --- /dev/null +++ b/OpenDuetPkg.dec @@ -0,0 +1,44 @@ +## @file +# +# This Package provides all definitions(including functions, MACROs, structures and library classes) +# and libraries instances, which are only used by Duet platform. +# +# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License which accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = OpenDuetPkg + PACKAGE_GUID = C10BE46B-35C3-4B0B-9B9C-3F02051D782F + PACKAGE_VERSION = 0.4 + +[Includes] + Include/Duet + +[Guids] + ## Include/Duet/Guid/PciExpressBaseAddress.h + gEfiPciExpressBaseAddressGuid = {0x3677d529, 0x326f, 0x4603, {0xa9, 0x26, 0xea, 0xac, 0xe0, 0x1d, 0xcb, 0xb0 }} + + ## Include/Duet/Guid/AcpiDescription.h + gEfiAcpiDescriptionGuid = {0x3c699197, 0x093c, 0x4c69, {0xb0, 0x6b, 0x12, 0x8a, 0xe3, 0x48, 0x1d, 0xc9 }} + + ## Include/Duet/Guid/FlashMapHob.h + gEfiFlashMapHobGuid = {0xb091e7d2, 0x05a0, 0x4198, {0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 }} + + ## Include/Duet/Guid/PciOptionRomTable.h + gEfiPciOptionRomTableGuid = {0x7462660F, 0x1CBD, 0x48DA, {0xAD, 0x11, 0x91, 0x71, 0x79, 0x13, 0x83, 0x1C }} + + ## Include/Duet/Guid/DxeCoreFileName.h + gDxeCoreFileNameGuid = {0xD6A2CB7F, 0x6A18, 0x4e2f, {0xB4, 0x3B, 0x99, 0x20, 0xA7, 0x33, 0x70, 0x0A }} + + ## Include/Duet/Guid/LdrMemoryDescriptor.h + gLdrMemoryDescriptorGuid = {0x7701d7e5, 0x7d1d, 0x4432, {0xa4, 0x68, 0x67, 0x3d, 0xab, 0x8a, 0xde, 0x60 }} diff --git a/OpenDuetPkg.dsc b/OpenDuetPkg.dsc new file mode 100644 index 0000000000000000000000000000000000000000..e24d85034fef9b88556e1feb6dea60487cc6c961 --- /dev/null +++ b/OpenDuetPkg.dsc @@ -0,0 +1,231 @@ +## @file +# An EFI/Framework Emulation Platform with UEFI HII interface supported. +# +# Developer's UEFI Emulation. DUET provides an EFI/UEFI IA32/X64 environment on legacy BIOS, +# to help developing and debugging native EFI/UEFI drivers. +# +# Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + PLATFORM_NAME = OpenDuetPkg + PLATFORM_GUID = 199E24E0-0989-42AA-87F2-611A8C397E72 + PLATFORM_VERSION = 0.92 + DSC_SPECIFICATION = 0x00010006 + OUTPUT_DIRECTORY = Build/OpenDuetPkg + SUPPORTED_ARCHITECTURES = X64|IA32 + BUILD_TARGETS = RELEASE|DEBUG|NOOPT + SKUID_IDENTIFIER = DEFAULT + FLASH_DEFINITION = OpenCorePkg/OpenDuetPkg.fdf + +[LibraryClasses] + # + # Entry point + # + PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf + DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + # + # Basic + # + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + !if $(ARCH) == X64 + BaseMemoryLib|MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf + !else + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + !endif + CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + LzmaDecompressLib|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + # + # UEFI & PI + # + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf + PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf + SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf + SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf + AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf + TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf + VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf + # + # Generic Modules + # + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf + UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf + # + # Platform + # + DuetBdsLib|OpenCorePkg/Library/DuetBdsLib/DuetBdsLib.inf + TimerLib|OpenCorePkg/Library/DuetTimerLib/DuetTimerLib.inf + # + # Misc + # + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + # + # To save size, use NULL library for DebugLib and ReportStatusCodeLib. + # If need status code output, do library instance overriden. + # + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf + +[LibraryClasses.common.DXE_CORE] + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + +[LibraryClasses.common.DXE_DRIVER] + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + +[Components] + OpenCorePkg/Legacy/BootPlatform/DxeIpl/DxeIpl.inf + MdeModulePkg/Core/Dxe/DxeMain.inf { + + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + } + + MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf + + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf { + + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|0 + } + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf { + + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + } + MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + OpenCorePkg/Legacy/BootPlatform/SmbiosGenDxe/SmbiosGen.inf + + OpenCorePkg/Legacy/BootPlatform/EfiLdr/EfiLdr.inf + OpenCorePkg/Legacy/BootPlatform/BdsDxe/BdsDxe.inf { + + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf + OpenCorePkg/Legacy/BootPlatform/CpuDxe/CpuDxe.inf + OvmfPkg/8259InterruptControllerDxe/8259.inf { + + gUefiOvmfPkgTokenSpaceGuid.Pcd8259LegacyModeMask|0xFFFC + } + OpenCorePkg/Legacy/BootPlatform/AcpiResetDxe/Reset.inf + MdeModulePkg/Universal/Metronome/Metronome.inf + + # Chipset + PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf + OvmfPkg/8254TimerDxe/8254Timer.inf + OpenCorePkg/Legacy/BootPlatform/PciRootBridgeDxe/PciRootBridgeNoEnumeration.inf + OpenCorePkg/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf + MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf + + # Foreign file system support + FatPkg/EnhancedFatDxe/Fat.inf + + # IDE/AHCI Support + MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf + MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf + MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf + + # Usb Support + MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf + MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf + MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf + + # ISA Support + OvmfPkg/SioBusDxe/SioBusDxe.inf + MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf + MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf + + # ACPI Support + MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf + + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf { + + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + + # Bios Thunk + OpenCorePkg/Legacy/BootPlatform/LegacyRegion2Dxe/LegacyRegion2Dxe.inf + OpenCorePkg/Legacy/BootPlatform/BiosVideo/BiosVideo.inf + +[PcdsFeatureFlag] + gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathToText|FALSE + gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport|FALSE + +[PcdsFixedAtBuild] + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor|L"Acidanthera" + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision|0x00010010 + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x10000 + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x10000 + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0 + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x0 + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel|0x0 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x0 + +[BuildOptions] + MSFT:NOOPT_*_*_CC_FLAGS = /FAcs -Dinline=__inline + MSFT:DEBUG_*_*_CC_FLAGS = /FAcs -Dinline=__inline -DMDEPKG_NDEBUG + MSFT:RELEASE_*_*_CC_FLAGS = /FAcs -Dinline=__inline -DMDEPKG_NDEBUG + + XCODE:NOOPT_*_*_CC_FLAGS = -fno-unwind-tables -O0 + XCODE:DEBUG_*_*_CC_FLAGS = -fno-unwind-tables -flto -Os -DMDEPKG_NDEBUG + XCODE:RELEASE_*_*_CC_FLAGS = -fno-unwind-tables -flto -Os -DMDEPKG_NDEBUG + + GCC:NOOPT_*_*_CC_FLAGS = -Wno-unused-but-set-variable + GCC:DEBUG_*_*_CC_FLAGS = -DMDEPKG_NDEBUG -Wno-unused-but-set-variable + GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG -Wno-unused-but-set-variable diff --git a/OpenDuetPkg.fdf b/OpenDuetPkg.fdf new file mode 100644 index 0000000000000000000000000000000000000000..be7acaf18751198c2195385b0487297ec9cbd62e --- /dev/null +++ b/OpenDuetPkg.fdf @@ -0,0 +1,152 @@ +## @file +# This is DUET FDF file with UEFI HII features enabled +# +# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] +!if ($(ARCH) == X64) + [FV.DuetEfiMainFvX64] +!else + [FV.DuetEfiMainFvIA32] +!endif + + BlockSize = 0x10000 + NumBlocks = 9 + FvAlignment = 16 #FV alignment and FV attributes setting. + ERASE_POLARITY = 1 + MEMORY_MAPPED = TRUE + STICKY_WRITE = TRUE + LOCK_CAP = TRUE + LOCK_STATUS = TRUE + WRITE_DISABLED_CAP = TRUE + WRITE_ENABLED_CAP = TRUE + WRITE_STATUS = TRUE + WRITE_LOCK_CAP = TRUE + WRITE_LOCK_STATUS = TRUE + READ_DISABLED_CAP = TRUE + READ_ENABLED_CAP = TRUE + READ_STATUS = TRUE + READ_LOCK_CAP = TRUE + READ_LOCK_STATUS = TRUE + + APRIORI DXE { + INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + INF OvmfPkg/8259InterruptControllerDxe/8259.inf + } + + # Core code + INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf + INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + + # Console + INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + + # CPU and interrupts + INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf + INF OpenCorePkg/Legacy/BootPlatform/CpuDxe/CpuDxe.inf + INF OvmfPkg/8259InterruptControllerDxe/8259.inf + INF OpenCorePkg/Legacy/BootPlatform/AcpiResetDxe/Reset.inf + + # Timer + INF MdeModulePkg/Universal/Metronome/Metronome.inf + INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + INF OvmfPkg/8254TimerDxe/8254Timer.inf + INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf + + # PCI + INF OpenCorePkg/Legacy/BootPlatform/PciRootBridgeDxe/PciRootBridgeNoEnumeration.inf + INF OpenCorePkg/Legacy/BootPlatform/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf + + # BIOS Video and CSM + INF OpenCorePkg/Legacy/BootPlatform/BiosVideo/BiosVideo.inf + INF OpenCorePkg/Legacy/BootPlatform/LegacyRegion2Dxe/LegacyRegion2Dxe.inf + + # IDE/AHCI + INF MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf + INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf + INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf + INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf + + # USB (UHCI may be used for input, XHCI cannot be booted from) + INF MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf + INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + + # ISA (e.g. PS/2 devices) + INF OvmfPkg/SioBusDxe/SioBusDxe.inf + + # Keyboard input (OpenCore has custom drivers) + # INF MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf + INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf + + # Mouse input (PS/2 is usually customised for touchpad) + # INF MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf + INF MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf + + # Generic disk I/O (Unicode collation is used by e.g. FAT) + INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + + # ACPI and SMBIOS (convenience protocols are optional) + # INF OpenCorePkg/Legacy/BootPlatform/SmbiosGenDxe/SmbiosGen.inf + # INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + # INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf + + # Filesystems (FAT is mandatory) + INF FatPkg/EnhancedFatDxe/Fat.inf + + # Binary drivers + # INF RuleOverride=BINARY OpenCorePkg/Legacy/BinDrivers/HfsPlus.inf + # INF RuleOverride=BINARY OpenCorePkg/Legacy/BinDrivers/OpenUsbKbDxe.inf + + # Boot management + INF OpenCorePkg/Legacy/BootPlatform/BdsDxe/BdsDxe.inf + +[Rule.Common.DXE_CORE] + FILE DXE_CORE = $(NAMED_GUID) { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + } + +[Rule.Common.UEFI_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + } + +[Rule.Common.UEFI_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + } + +[Rule.Common.DXE_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + } + +[Rule.Common.DXE_RUNTIME_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + } diff --git a/Utilities/BaseTools/EfiLdrImage.c b/Utilities/BaseTools/EfiLdrImage.c new file mode 100644 index 0000000000000000000000000000000000000000..ebd83f19fde35ede853301ae1d506ff121b04a46 --- /dev/null +++ b/Utilities/BaseTools/EfiLdrImage.c @@ -0,0 +1,344 @@ +/** @file +Creates and EFILDR image. +This tool combines several PE Image files together using following format denoted as EBNF: +FILE := EFILDR_HEADER + EFILDR_IMAGE + + + +The order of EFILDR_IMAGE is same as the order of placing PeImageFileContent. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include +#include +#include +#include +#include + +#define MAX_PE_IMAGES 63 +#define FILE_TYPE_FIXED_LOADER 0 +#define FILE_TYPE_RELOCATABLE_PE_IMAGE 1 + +typedef struct { + uint32_t CheckSum; + uint32_t Offset; + uint32_t Length; + uint8_t FileName[52]; +} EFILDR_IMAGE; + +typedef struct { + uint32_t Signature; + uint32_t HeaderCheckSum; + uint32_t FileLength; + uint32_t NumberOfImages; +} EFILDR_HEADER; + +// +// Utility Name +// +#define UTILITY_NAME "EfiLdrImage" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 1 +#define UTILITY_MINOR_VERSION 0 + +void +Error ( + char *FileName, + uint32_t LineNumber, + uint32_t ErrorCode, + char *OffendingText, + char *MsgFmt, + ... + ) +{ + va_list List; + va_start (List, MsgFmt); + vprintf (MsgFmt, List); + va_end (List); + puts(""); +} + +void +Version ( + void + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ("%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); +} + +void +Usage ( + void + ) +{ + printf ("Usage: EfiLdrImage -o OutImage LoaderImage PeImage1 PeImage2 ... PeImageN\n"); + printf ("%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); + printf ("Copyright (c) 1999-2017 Intel Corporation. All rights reserved.\n"); + printf ("\n The EfiLdrImage tool is used to combine PE files into EFILDR image with Efi loader header.\n"); +} + +int +CountVerboseLevel ( + const char* VerboseLevelString, + const uint64_t Length, + uint64_t *ReturnValue +) +{ + uint64_t i = 0; + for (;i < Length; ++i) { + if (VerboseLevelString[i] != 'v' && VerboseLevelString[i] != 'V') { + return -1; + } + ++(*ReturnValue); + } + + return 0; +} + +uint64_t +FCopyFile ( + FILE *in, + FILE *out + ) +/*++ +Routine Description: + Write all the content of input file to output file. + +Arguments: + in - input file pointer + out - output file pointer + +Return: + uint64_t : file size of input file +--*/ +{ + uint32_t filesize, offset, length; + char Buffer[8*1024]; + + fseek (in, 0, SEEK_END); + filesize = ftell(in); + + fseek (in, 0, SEEK_SET); + + offset = 0; + while (offset < filesize) { + length = sizeof(Buffer); + if (filesize-offset < length) { + length = filesize-offset; + } + + int r = fread (Buffer, length, 1, in); + if (r < 0) { + abort(); + } + fwrite (Buffer, length, 1, out); + offset += length; + } + + return filesize; +} + + +int +main ( + int argc, + char *argv[] + ) +/*++ + +Routine Description: + + +Arguments: + + +Returns: + + +--*/ +{ + uint64_t i; + uint64_t filesize; + FILE *fpIn, *fpOut; + EFILDR_HEADER EfiLdrHeader; + EFILDR_IMAGE EfiLdrImage[MAX_PE_IMAGES]; + char* OutputFileName = NULL; + char* InputFileNames[MAX_PE_IMAGES + 1]; + char* InputName; + uint8_t InputFileCount = 0; + uint64_t DebugLevel = 0; + uint64_t VerboseLevel = 0; + int Status = 0; + + if (argc == 1) { + printf ("Usage: EfiLdrImage -o OutImage LoaderImage PeImage1 PeImage2 ... PeImageN\n"); + return EXIT_FAILURE; + } + + argc --; + argv ++; + + if ((strcmp (argv[0], "-h") == 0) || (strcmp (argv[0], "--help") == 0)) { + Usage(); + return EXIT_SUCCESS; + } + + if (strcmp (argv[0], "--version") == 0) { + Version(); + return EXIT_SUCCESS; + } + + while (argc > 0) { + + if ((strcmp (argv[0], "-o") == 0) || (strcmp (argv[0], "--output") == 0)) { + OutputFileName = argv[1]; + if (OutputFileName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Output file can't be null"); + return EXIT_FAILURE; + } + argc -= 2; + argv += 2; + continue; + } + + if ((strcmp (argv[0], "-q") == 0) || (strcmp (argv[0], "--quiet") == 0)) { + argc --; + argv ++; + continue; + } + + if ((strlen(argv[0]) >= 2 && argv[0][0] == '-' && (argv[0][1] == 'v' || argv[0][1] == 'V')) || (strcmp (argv[0], "--verbose") == 0)) { + VerboseLevel = 1; + if (strlen(argv[0]) > 2) { + Status = CountVerboseLevel (&argv[0][2], strlen(argv[0]) - 2, &VerboseLevel); + if (Status != 0) { + Error (NULL, 0, 1003, "Invalid option value", "%s", argv[0]); + return EXIT_FAILURE; + } + } + + argc --; + argv ++; + continue; + } + + if ((strcmp (argv[0], "-d") == 0) || (strcmp (argv[0], "--debug") == 0)) { + DebugLevel = strtoull (argv[1], NULL, 0); + argc -= 2; + argv += 2; + continue; + } + // + // Don't recognize the parameter, should be regarded as the input file name. + // + InputFileNames[InputFileCount] = argv[0]; + InputFileCount++; + argc--; + argv++; + } + + if (InputFileCount == 0) { + Error (NULL, 0, 1001, "Missing option", "No input file"); + return EXIT_FAILURE; + } + // + // Open output file for write + // + if (OutputFileName == NULL) { + Error (NULL, 0, 1001, "Missing option", "No output file"); + return EXIT_FAILURE; + } + + fpOut = fopen (OutputFileName, "w+b"); + if (!fpOut) { + Error (NULL, 0, 0001, "Could not open output file", OutputFileName); + return EXIT_FAILURE; + } + + memset (&EfiLdrHeader, 0, sizeof (EfiLdrHeader)); + memset (&EfiLdrImage, 0, sizeof (EFILDR_IMAGE) * (InputFileCount)); + + memcpy (&EfiLdrHeader.Signature, "EFIL", 4); + EfiLdrHeader.FileLength = sizeof(EFILDR_HEADER) + sizeof(EFILDR_IMAGE)*(InputFileCount); + + // + // Skip the file header first + // + fseek (fpOut, EfiLdrHeader.FileLength, SEEK_SET); + + // + // copy all the input files to the output file + // + for(i=0;i +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include "VirtualMemory.h" + +#define EFI_PAGE_BASE_OFFSET_IN_LDR 0x70000 +#define EFI_PAGE_BASE_ADDRESS (EFI_PAGE_BASE_OFFSET_IN_LDR + 0x20000) + +uint32_t gPageTableBaseAddress = EFI_PAGE_BASE_ADDRESS; +uint32_t gPageTableOffsetInFile = EFI_PAGE_BASE_OFFSET_IN_LDR; + +#define EFI_MAX_ENTRY_NUM 512 + +#define EFI_PML4_ENTRY_NUM 1 +#define EFI_PDPTE_ENTRY_NUM 4 +#define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM + +#define EFI_PML4_PAGE_NUM 1 +#define EFI_PDPTE_PAGE_NUM EFI_PML4_ENTRY_NUM +#define EFI_PDE_PAGE_NUM (EFI_PML4_ENTRY_NUM * EFI_PDPTE_ENTRY_NUM) + +#define EFI_PAGE_NUMBER (EFI_PML4_PAGE_NUM + EFI_PDPTE_PAGE_NUM + EFI_PDE_PAGE_NUM) + +#define EFI_SIZE_OF_PAGE 0x1000 +#define EFI_PAGE_SIZE_2M 0x200000 + +#define CONVERT_BIN_PAGE_ADDRESS(a) ((uint8_t *) a - PageTable + gPageTableBaseAddress) + +// +// Utility Name +// +#define UTILITY_NAME "GenPage" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 2 + +void +Error ( + char *FileName, + uint32_t LineNumber, + uint32_t ErrorCode, + char *OffendingText, + char *MsgFmt, + ... + ) +{ + va_list List; + va_start (List, MsgFmt); + vprintf (MsgFmt, List); + va_end (List); + puts(""); +} + +void +Version ( + void + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ("%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); +} + +void +Usage ( + void + ) +{ + printf ("Usage: GenPage.exe [options] EfiLoaderImageName \n\n\ +Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.\n\n\ + Utility to generate the EfiLoader image containing a page table.\n\n\ +optional arguments:\n\ + -h, --help Show this help message and exit\n\ + --version Show program's version number and exit\n\ + -d [DEBUG], --debug [DEBUG]\n\ + Output DEBUG statements, where DEBUG_LEVEL is 0 (min)\n\ + - 9 (max)\n\ + -v, --verbose Print informational statements\n\ + -q, --quiet Returns the exit code, error messages will be\n\ + displayed\n\ + -s, --silent Returns only the exit code; informational and error\n\ + messages are not displayed\n\ + -o OUTPUT_FILENAME, --output OUTPUT_FILENAME\n\ + Output file contain both the non-page table part and\n\ + the page table\n\ + -b BASE_ADDRESS, --baseaddr BASE_ADDRESS\n\ + The page table location\n\ + -f OFFSET, --offset OFFSET\n\ + The position that the page table will appear in the\n\ + output file\n\ + --sfo Reserved for future use\n"); + +} + +void * +CreateIdentityMappingPageTables ( + void + ) +/*++ + +Routine Description: + To create 4G PAE 2M pagetable + +Return: + void * - buffer containing created pagetable + +--*/ +{ + uint64_t PageAddress; + uint8_t *PageTable; + uint8_t *PageTablePtr; + int PML4Index; + int PDPTEIndex; + int PDEIndex; + X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry; + X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry; + X64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB; + + PageTable = (void *)malloc (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE); + if (PageTable == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return NULL; + } + memset (PageTable, 0, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE)); + PageTablePtr = PageTable; + + PageAddress = 0; + + // + // Page Table structure 3 level 2MB. + // + // Page-Map-Level-4-Table : bits 47-39 + // Page-Directory-Pointer-Table : bits 38-30 + // + // Page Table 2MB : Page-Directory(2M) : bits 29-21 + // + // + + PageMapLevel4Entry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr; + + for (PML4Index = 0; PML4Index < EFI_PML4_ENTRY_NUM; PML4Index++, PageMapLevel4Entry++) { + // + // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry + // + PageTablePtr += EFI_SIZE_OF_PAGE; + PageDirectoryPointerEntry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr; + + // + // Make a Page-Map-Level-4-Table Entry + // + PageMapLevel4Entry->Uint64 = (uint64_t)(uint32_t)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry)); + PageMapLevel4Entry->Bits.ReadWrite = 1; + PageMapLevel4Entry->Bits.Present = 1; + + for (PDPTEIndex = 0; PDPTEIndex < EFI_PDPTE_ENTRY_NUM; PDPTEIndex++, PageDirectoryPointerEntry++) { + // + // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry + // + PageTablePtr += EFI_SIZE_OF_PAGE; + PageDirectoryEntry2MB = (X64_PAGE_TABLE_ENTRY_2M *)PageTablePtr; + + // + // Make a Page-Directory-Pointer-Table Entry + // + PageDirectoryPointerEntry->Uint64 = (uint64_t)(uint32_t)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB)); + PageDirectoryPointerEntry->Bits.ReadWrite = 1; + PageDirectoryPointerEntry->Bits.Present = 1; + + for (PDEIndex = 0; PDEIndex < EFI_PDE_ENTRY_NUM; PDEIndex++, PageDirectoryEntry2MB++) { + // + // Make a Page-Directory Entry + // + PageDirectoryEntry2MB->Uint64 = (uint64_t)PageAddress; + PageDirectoryEntry2MB->Bits.ReadWrite = 1; + PageDirectoryEntry2MB->Bits.Present = 1; + PageDirectoryEntry2MB->Bits.MustBe1 = 1; + + PageAddress += EFI_PAGE_SIZE_2M; + } + } + } + + return PageTable; +} + +int32_t +GenBinPage ( + void *BaseMemory, + char *NoPageFileName, + char *PageFileName + ) +/*++ + +Routine Description: + Write the buffer containing page table to file at a specified offset. + Here the offset is defined as EFI_PAGE_BASE_OFFSET_IN_LDR. + +Arguments: + BaseMemory - buffer containing page table + NoPageFileName - file to write page table + PageFileName - file save to after writing + +return: + 0 : successful + -1 : failed + +--*/ +{ + FILE *PageFile; + FILE *NoPageFile; + uint8_t Data; + unsigned long FileSize; + + // + // Open files + // + PageFile = fopen (PageFileName, "w+b"); + if (PageFile == NULL) { + Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Output File %s open failure", PageFileName); + return -1; + } + + NoPageFile = fopen (NoPageFileName, "r+b"); + if (NoPageFile == NULL) { + Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Input File %s open failure", NoPageFileName); + fclose (PageFile); + return -1; + } + + // + // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR + // + fseek (NoPageFile, 0, SEEK_END); + FileSize = ftell (NoPageFile); + fseek (NoPageFile, 0, SEEK_SET); + if (FileSize > gPageTableOffsetInFile) { + Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Input file size (0x%lx) exceeds the Page Table Offset (0x%x)", FileSize, (unsigned) gPageTableOffsetInFile); + fclose (PageFile); + fclose (NoPageFile); + return -1; + } + + // + // Write data + // + while (fread (&Data, sizeof(uint8_t), 1, NoPageFile)) { + fwrite (&Data, sizeof(uint8_t), 1, PageFile); + } + + // + // Write PageTable + // + fseek (PageFile, gPageTableOffsetInFile, SEEK_SET); + fwrite (BaseMemory, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE), 1, PageFile); + + // + // Close files + // + fclose (PageFile); + fclose (NoPageFile); + + return 0; +} + +int +main ( + int argc, + char **argv + ) +{ + void *BaseMemory; + int32_t result; + char *OutputFile = NULL; + char *InputFile = NULL; + uint64_t TempValue; + + if (argc == 1) { + Usage(); + return EXIT_FAILURE; + } + + argc --; + argv ++; + + if ((strcmp (argv[0], "-h") == 0) || (strcmp (argv[0], "--help") == 0)) { + Usage(); + return 0; + } + + if (strcmp (argv[0], "--version") == 0) { + Version(); + return 0; + } + + while (argc > 0) { + if ((strcmp (argv[0], "-o") == 0) || (strcmp (argv[0], "--output") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option"); + return EXIT_FAILURE; + } + OutputFile = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if ((strcmp (argv[0], "-b") == 0) || (strcmp (argv[0], "--baseaddr") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Base address is missing for -b option"); + return EXIT_FAILURE; + } + TempValue = strtoull (argv[1], NULL, 0); + gPageTableBaseAddress = (uint32_t) TempValue; + argc -= 2; + argv += 2; + continue; + } + + if ((strcmp (argv[0], "-f") == 0) || (strcmp (argv[0], "--offset") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Offset is missing for -f option"); + return EXIT_FAILURE; + } + TempValue = strtoull (argv[1], NULL, 0); + gPageTableOffsetInFile = (uint32_t) TempValue; + argc -= 2; + argv += 2; + continue; + } + + if ((strcmp (argv[0], "-q") == 0) || (strcmp (argv[0], "--quiet") == 0)) { + argc --; + argv ++; + continue; + } + + if ((strcmp (argv[0], "-v") ==0) || (strcmp (argv[0], "--verbose") == 0)) { + argc --; + argv ++; + continue; + } + + if ((strcmp (argv[0], "-d") == 0) || (strcmp (argv[0], "--debug") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level is not specified."); + return EXIT_FAILURE; + } + TempValue = strtoull (argv[1], NULL, 0); + if (TempValue > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) TempValue); + return EXIT_FAILURE; + } + argc -= 2; + argv += 2; + continue; + } + + if (argv[0][0] == '-') { + Error (NULL, 0, 1000, "Unknown option", argv[0]); + return EXIT_FAILURE; + } + + // + // Don't recognize the parameter. + // + InputFile = argv[0]; + argc--; + argv++; + } + + if (InputFile == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Input file is not specified"); + return EXIT_FAILURE; + } + + // + // Create X64 page table + // + BaseMemory = CreateIdentityMappingPageTables (); + if (BaseMemory == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return EXIT_FAILURE; + } + + // + // Add page table to binary file + // + result = GenBinPage (BaseMemory, InputFile, OutputFile); + if (result < 0) { + free (BaseMemory); + return EXIT_FAILURE; + } + + free (BaseMemory); + return 0; +} + diff --git a/Utilities/BaseTools/Makefile b/Utilities/BaseTools/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..ff74e4fbe604c4517065008b2b778a7ba97fc9b4 --- /dev/null +++ b/Utilities/BaseTools/Makefile @@ -0,0 +1,27 @@ +CC ?= gcc +CFLAGS ?= -O3 -s +MKDIR ?= mkdir +RM ?= /bin/rm + +ifneq ($(OS),Windows_NT) + UNAME_S := $(shell uname -s) + ifeq ($(UNAME_S),Darwin) + CFLAGS+=-mmacosx-version-min=10.6 + endif +endif + +BINDIR=bin.$(shell uname) +PRODUCTS=$(BINDIR)/GenPage $(BINDIR)/EfiLdrImage + +all: $(PRODUCTS) + +clean: + $(RM) -f $(PRODUCTS) + +$(BINDIR)/GenPage: GenPage.c VirtualMemory.h + @$(MKDIR) -p $(BINDIR) + $(CC) $(CFLAGS) -o $@ $< + +$(BINDIR)/EfiLdrImage: EfiLdrImage.c + @$(MKDIR) -p $(BINDIR) + $(CC) $(CFLAGS) -o $@ $< diff --git a/Utilities/BaseTools/VirtualMemory.h b/Utilities/BaseTools/VirtualMemory.h new file mode 100644 index 0000000000000000000000000000000000000000..c7ad8132590cd39f0306fb14bb795ea5c3c264cd --- /dev/null +++ b/Utilities/BaseTools/VirtualMemory.h @@ -0,0 +1,122 @@ +/** @file +x64 Long Mode Virtual Memory Management Definitions + + References: + 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel + 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel + 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel + 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _VIRTUAL_MEMORY_H_ +#define _VIRTUAL_MEMORY_H_ + +#include + +#pragma pack(1) + +// +// Page-Map Level-4 Offset (PML4) and +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB +// + +typedef union { + struct { + uint64_t Present:1; // 0 = Not present in memory, 1 = Present in memory + uint64_t ReadWrite:1; // 0 = Read-Only, 1= Read/Write + uint64_t UserSupervisor:1; // 0 = Supervisor, 1=User + uint64_t WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + uint64_t CacheDisabled:1; // 0 = Cached, 1=Non-Cached + uint64_t Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + uint64_t Reserved:1; // Reserved + uint64_t MustBeZero:2; // Must Be Zero + uint64_t Available:3; // Available for use by system software + uint64_t PageTableBaseAddress:40; // Page Table Base Address + uint64_t AvabilableHigh:11; // Available for use by system software + uint64_t Nx:1; // No Execute bit + } Bits; + uint64_t Uint64; +} X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K; + +// +// Page-Directory Offset 4K +// +typedef union { + struct { + uint64_t Present:1; // 0 = Not present in memory, 1 = Present in memory + uint64_t ReadWrite:1; // 0 = Read-Only, 1= Read/Write + uint64_t UserSupervisor:1; // 0 = Supervisor, 1=User + uint64_t WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + uint64_t CacheDisabled:1; // 0 = Cached, 1=Non-Cached + uint64_t Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + uint64_t Reserved:1; // Reserved + uint64_t MustBeZero:1; // Must Be Zero + uint64_t Reserved2:1; // Reserved + uint64_t Available:3; // Available for use by system software + uint64_t PageTableBaseAddress:40; // Page Table Base Address + uint64_t AvabilableHigh:11; // Available for use by system software + uint64_t Nx:1; // No Execute bit + } Bits; + uint64_t Uint64; +} X64_PAGE_DIRECTORY_ENTRY_4K; + +// +// Page Table Entry 4K +// +typedef union { + struct { + uint64_t Present:1; // 0 = Not present in memory, 1 = Present in memory + uint64_t ReadWrite:1; // 0 = Read-Only, 1= Read/Write + uint64_t UserSupervisor:1; // 0 = Supervisor, 1=User + uint64_t WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + uint64_t CacheDisabled:1; // 0 = Cached, 1=Non-Cached + uint64_t Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + uint64_t Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + uint64_t PAT:1; // 0 = Ignore Page Attribute Table + uint64_t Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + uint64_t Available:3; // Available for use by system software + uint64_t PageTableBaseAddress:40; // Page Table Base Address + uint64_t AvabilableHigh:11; // Available for use by system software + uint64_t Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + uint64_t Uint64; +} X64_PAGE_TABLE_ENTRY_4K; + + +// +// Page Table Entry 2MB +// +typedef union { + struct { + uint64_t Present:1; // 0 = Not present in memory, 1 = Present in memory + uint64_t ReadWrite:1; // 0 = Read-Only, 1= Read/Write + uint64_t UserSupervisor:1; // 0 = Supervisor, 1=User + uint64_t WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + uint64_t CacheDisabled:1; // 0 = Cached, 1=Non-Cached + uint64_t Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + uint64_t Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + uint64_t MustBe1:1; // Must be 1 + uint64_t Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + uint64_t Available:3; // Available for use by system software + uint64_t PAT:1; // + uint64_t MustBeZero:8; // Must be zero; + uint64_t PageTableBaseAddress:31; // Page Table Base Address + uint64_t AvabilableHigh:11; // Available for use by system software + uint64_t Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + uint64_t Uint64; +} X64_PAGE_TABLE_ENTRY_2M; + +#pragma pack() + +#endif diff --git a/Utilities/BaseTools/bin.Darwin/EfiLdrImage b/Utilities/BaseTools/bin.Darwin/EfiLdrImage new file mode 100755 index 0000000000000000000000000000000000000000..f0b89af7b97e70e77fc566853ad5bf27c90e7f2e Binary files /dev/null and b/Utilities/BaseTools/bin.Darwin/EfiLdrImage differ diff --git a/Utilities/BaseTools/bin.Darwin/GenPage b/Utilities/BaseTools/bin.Darwin/GenPage new file mode 100755 index 0000000000000000000000000000000000000000..77b653addc2ff6d820c0ac8980c776288cd76431 Binary files /dev/null and b/Utilities/BaseTools/bin.Darwin/GenPage differ diff --git a/Utilities/BaseTools/bin.Linux/EfiLdrImage b/Utilities/BaseTools/bin.Linux/EfiLdrImage new file mode 100755 index 0000000000000000000000000000000000000000..2d562ea6b2fe0e9de690f57648704c54292c351b Binary files /dev/null and b/Utilities/BaseTools/bin.Linux/EfiLdrImage differ diff --git a/Utilities/BaseTools/bin.Linux/GenPage b/Utilities/BaseTools/bin.Linux/GenPage new file mode 100755 index 0000000000000000000000000000000000000000..35eebed30e13afcd4debd2ed44ba51b4fae6f999 Binary files /dev/null and b/Utilities/BaseTools/bin.Linux/GenPage differ diff --git a/Utilities/LegacyBoot/BootInstall.command b/Utilities/LegacyBoot/BootInstall.command new file mode 100755 index 0000000000000000000000000000000000000000..161e4b458e6423a57ffed663dcd78404f9d85af0 --- /dev/null +++ b/Utilities/LegacyBoot/BootInstall.command @@ -0,0 +1,47 @@ +#!/bin/bash + +# Install booter on physical disk. + +cd "$(dirname "$0")" || exit +diskutil list +echo "Enter disk number to install to:" +read -r N + +if [[ ! $(diskutil info disk"${N}" | sed -n 's/.*Device Node: *//p') ]] +then + echo Disk "$N" not found + exit +fi + +FS=$(diskutil info disk"${N}"s1 | sed -n 's/.*File System Personality: *//p') +echo "$FS" + +if [ "$FS" != "MS-DOS FAT32" ] +then + echo "No FAT32 partition to install" + exit +fi + +# Write MBR +sudo fdisk -f boot0 -u /dev/rdisk"${N}" + +diskutil umount disk"${N}"s1 +sudo dd if=/dev/rdisk"${N}"s1 count=1 of=origbs +cp -v boot1f32 newbs +sudo dd if=origbs of=newbs skip=3 seek=3 bs=1 count=87 conv=notrunc +dd if=/dev/random of=newbs skip=496 seek=496 bs=1 count=14 conv=notrunc +sudo dd if=newbs of=/dev/rdisk"${N}"s1 +diskutil mount disk"${N}"s1 + +cp -v boot "$(diskutil info disk"${N}"s1 | sed -n 's/.*Mount Point: *//p')" + +if [ "$(diskutil info disk"${N}" | sed -n 's/.*Content (IOContent): *//p')" == "FDisk_partition_scheme" ] +then +sudo fdisk -e /dev/rdisk"$N" <<-MAKEACTIVE +p +f 1 +w +y +q +MAKEACTIVE +fi diff --git a/Utilities/LegacyBoot/QemuBuild.command b/Utilities/LegacyBoot/QemuBuild.command new file mode 100755 index 0000000000000000000000000000000000000000..cfae2b25deb3ef56a84256df2322648446fe349c --- /dev/null +++ b/Utilities/LegacyBoot/QemuBuild.command @@ -0,0 +1,74 @@ +#!/bin/bash + +# Build QEMU image, example: +# qemu-system-x86_64 -drive file=$QEMU_IMAGE/OpenCore.RO.raw -serial stdio \ +# -usb -device usb-kbd -device usb-mouse -s -m 8192 + +cd "$(dirname "$0")" || exit + +if [ "$(which qemu-img)" = "" ]; then + echo "QEMU installation missing" + exit 1 +fi + +if [ ! -d ROOT ]; then + echo "No ROOT directory with ESP partition contents" + exit 1 +fi + +rm -f OpenCore.dmg.sparseimage OpenCore.RO.raw OpenCore.RO.dmg +hdiutil create -size 200m -layout "UNIVERSAL HD" -type SPARSE -o OpenCore.dmg +newDevice=$(hdiutil attach -nomount OpenCore.dmg.sparseimage |head -n 1 | awk '{print $1}') +echo newdevice "$newDevice" + +diskutil partitionDisk "${newDevice}" 1 MBR fat32 TEST R + +# boot install script +diskutil list +N=$(echo "$newDevice" | tr -dc '0-9') +echo "Will be installed to Disk ${N}" + + +if [[ ! $(diskutil info disk"${N}" | sed -n 's/.*Device Node: *//p') ]] +then + echo Disk "$N" not found + exit +fi + +FS=$(diskutil info disk"${N}"s1 | sed -n 's/.*File System Personality: *//p') +echo "$FS" + +if [ "$FS" != "MS-DOS FAT32" ] +then + echo "No FAT32 partition to install" + exit +fi + +# Write MBR +sudo fdisk -f boot0 -u /dev/rdisk"${N}" + +diskutil umount disk"${N}"s1 +sudo dd if=/dev/rdisk"${N}"s1 count=1 of=origbs +cp -v boot1f32 newbs +sudo dd if=origbs of=newbs skip=3 seek=3 bs=1 count=87 conv=notrunc +dd if=/dev/random of=newbs skip=496 seek=496 bs=1 count=14 conv=notrunc +sudo dd if=newbs of=/dev/rdisk"${N}"s1 +diskutil mount disk"${N}"s1 + +cp -v boot "$(diskutil info disk"${N}"s1 | sed -n 's/.*Mount Point: *//p')" +cp -rv ROOT/* "$(diskutil info disk"${N}"s1 | sed -n 's/.*Mount Point: *//p')" + +if [ "$(diskutil info disk"${N}" | sed -n 's/.*Content (IOContent): *//p')" == "FDisk_partition_scheme" ] +then +sudo fdisk -e /dev/rdisk"$N" <<-MAKEACTIVE +p +f 1 +w +y +q +MAKEACTIVE +fi + +hdiutil detach "$newDevice" +hdiutil convert -format UDRO OpenCore.dmg.sparseimage -o OpenCore.RO.dmg +qemu-img convert -f dmg -O raw OpenCore.RO.dmg OpenCore.RO.raw diff --git a/Utilities/LegacyBoot/README.md b/Utilities/LegacyBoot/README.md new file mode 100644 index 0000000000000000000000000000000000000000..ee7aac5e9831201c9b116372343be181d0c3376f --- /dev/null +++ b/Utilities/LegacyBoot/README.md @@ -0,0 +1,7 @@ +BootInstall +=========== + +This tool installs legacy DuetPkg environment on GPT-formatted disk +to enable UEFI environment on BIOS-based systems. + +Source code: https://github.com/acidanthera/DuetPkg diff --git a/Utilities/LegacyBoot/boot b/Utilities/LegacyBoot/boot new file mode 100644 index 0000000000000000000000000000000000000000..73ef72acbf8dae41d02925f74d961385f68ecc48 Binary files /dev/null and b/Utilities/LegacyBoot/boot differ diff --git a/Utilities/LegacyBoot/boot0 b/Utilities/LegacyBoot/boot0 new file mode 100644 index 0000000000000000000000000000000000000000..cc32f83ad55e4dc384b7ba42e71ae3f3057ed96d Binary files /dev/null and b/Utilities/LegacyBoot/boot0 differ diff --git a/Utilities/LegacyBoot/boot1f32 b/Utilities/LegacyBoot/boot1f32 new file mode 100644 index 0000000000000000000000000000000000000000..f519ef06863ab903361c4e460f71b76b2d6f610a Binary files /dev/null and b/Utilities/LegacyBoot/boot1f32 differ diff --git a/build_duet.tool b/build_duet.tool new file mode 100755 index 0000000000000000000000000000000000000000..d79b99a01803b65c9e14d307e84909d15bb50831 --- /dev/null +++ b/build_duet.tool @@ -0,0 +1,125 @@ +#!/bin/bash + +imgbuild() { + echo "Compressing DUETEFIMainFv.FV..." + LzmaCompress -e -o "${BUILD_DIR}/FV/DUETEFIMAINFV${TARGETARCH}.z" \ + "${BUILD_DIR}/FV/DUETEFIMAINFV${TARGETARCH}.Fv" || exit 1 + + echo "Compressing DxeCore.efi..." + LzmaCompress -e -o "${BUILD_DIR}/FV/DxeMain${TARGETARCH}.z" \ + "${BUILD_DIR_ARCH}/DxeCore.efi" || exit 1 + + echo "Compressing DxeIpl.efi..." + LzmaCompress -e -o "${BUILD_DIR}/FV/DxeIpl${TARGETARCH}.z" \ + "$BUILD_DIR_ARCH/DxeIpl.efi" || exit 1 + + echo "Generating Loader Image..." + + GenFw --rebase 0x10000 -o "${BUILD_DIR_ARCH}/EfiLoaderRebased.efi" \ + "${BUILD_DIR_ARCH}/EfiLoader.efi" || exit 1 + "${FV_TOOLS}/EfiLdrImage" -o "${BUILD_DIR}/FV/Efildr${TARGETARCH}" \ + "${BUILD_DIR_ARCH}/EfiLoaderRebased.efi" "${BUILD_DIR}/FV/DxeIpl${TARGETARCH}.z" \ + "${BUILD_DIR}/FV/DxeMain${TARGETARCH}.z" "${BUILD_DIR}/FV/DUETEFIMAINFV${TARGETARCH}.z" || exit 1 + + # Calculate page table location for 64-bit builds. + # Page table must be 4K aligned, bootsectors are 4K each, and 0x20000 is base address. + if [ "${TARGETARCH}" = "X64" ]; then + if [ "$(uname)" = "Darwin" ]; then + EL_SIZE=$(stat -f "%z" "${BUILD_DIR}/FV/Efildr${TARGETARCH}") + else + EL_SIZE=$(stat --printf="%s\n" "${BUILD_DIR}/FV/Efildr${TARGETARCH}") + fi + PAGE_TABLE_OFF=$( printf "0x%x" $(( (EL_SIZE + 0x2000 + 0xFFF) & ~0xFFF )) ) + PAGE_TABLE=$( printf "0x%x" $(( PAGE_TABLE_OFF + 0x20000 )) ) + + export PAGE_TABLE_OFF + export PAGE_TABLE + + BOOTSECTOR_SUFFIX="_${PAGE_TABLE}" + else + BOOTSECTOR_SUFFIX="" + fi + + # Build bootsectors. + mkdir -p "${BOOTSECTORS}" || exit 1 + cd "${BOOTSECTORS}"/.. || exit 1 + make || exit 1 + cd - || exit 1 + + # Concatenate bootsector into the resulting image. + cat "${BOOTSECTORS}/Start${TARGETARCH}${BOOTSECTOR_SUFFIX}.com" "${BOOTSECTORS}/Efi${TARGETARCH}.com" \ + "${BUILD_DIR}/FV/Efildr${TARGETARCH}" > "${BUILD_DIR}/FV/Efildr${TARGETARCH}Pure" || exit 1 + + # Append page table and skip empty data in 64-bit mode. + if [ "${TARGETARCH}" = "X64" ]; then + "${FV_TOOLS}/GenPage" "${BUILD_DIR}/FV/Efildr${TARGETARCH}Pure" \ + -b "${PAGE_TABLE}" -f "${PAGE_TABLE_OFF}" \ + -o "${BUILD_DIR}/FV/Efildr${TARGETARCH}Out" || exit 1 + + dd if="${BUILD_DIR}/FV/Efildr${TARGETARCH}Out" of="${BUILD_DIR_ARCH}/boot" bs=512 skip=1 || exit 1 + else + cp "${BUILD_DIR}/FV/Efildr${TARGETARCH}Pure" "${BUILD_DIR_ARCH}/boot" || exit 1 + fi +} + +package() { + if [ ! -d "$1" ]; then + echo "Missing package directory $1" + exit 1 + fi + + if [ ! -d "$1"/../FV ]; then + echo "Missing FV directory $1/../FV" + exit 1 + fi + + pushd "$1" || exit 1 + cd -P . || exit 1 + BUILD_DIR_ARCH=$(pwd) + cd -P .. || exit 1 + BUILD_DIR=$(pwd) + popd || exit 1 + + imgbuild +} + +cd "$(dirname "$0")" || exit 1 + +BOOTSECTORS="$(pwd)/Legacy/BootSector/bin" +FV_TOOLS="$(pwd)/Utilities/BaseTools/bin.$(uname)" + +if [ ! -d "${FV_TOOLS}" ]; then + echo "ERROR: You need to compile BaseTools for your platform!" + exit 1 +fi + +if [ "${TARGETARCH}" = "" ]; then + TARGETARCH="X64" +fi + +if [ "${TARGET}" = "" ]; then + TARGET="RELEASE" +fi + +if [ "${INTREE}" != "" ]; then + # In-tree compilation is merely for packing. + cd .. || exit 1 + + build -a "${TARGETARCH}" -b "${TARGET}" -t XCODE5 -p OpenCorePkg/OpenDuetPkg.dsc || exit 1 + + BUILD_DIR="${WORKSPACE}/Build/OpenDuetPkg/${TARGET}_XCODE5" + BUILD_DIR_ARCH="${BUILD_DIR}/${TARGETARCH}" + imgbuild +else + TARGETS=(DEBUG RELEASE) + ARCHS=(X64 IA32) + SELFPKG_DIR="OpenCorePkg" + SELFPKG=OpenDuetPkg + + export TARGETS + export ARCHS + export SELFPKG_DIR + export SELFPKG + + src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/ocbuild/master/efibuild.sh) && eval "$src" || exit 1 +fi diff --git a/macbuild.tool b/build_oc.tool similarity index 94% rename from macbuild.tool rename to build_oc.tool index 19459f193242f8241c052e7db965653c2bd9e253..521e032a0b8f19c7c62562d90192f3552db290cc 100755 --- a/macbuild.tool +++ b/build_oc.tool @@ -62,7 +62,7 @@ package() { cp "${selfdir}/Docs/SampleFull.plist" tmp/Docs/ || exit 1 cp "${selfdir}/Changelog.md" tmp/Docs/ || exit 1 cp -r "${selfdir}/Docs/AcpiSamples/" tmp/Docs/AcpiSamples/ || exit 1 - cp -r "${selfdir}/UDK/DuetPkg/BootLoader/bin" tmp/Utilities/BootInstall || exit 1 + cp -r "${selfdir}/Utilities/LegacyBoot" tmp/Utilities/ || exit 1 cp -r "${selfdir}/Utilities/CreateVault" tmp/Utilities/ || exit 1 cp -r "${selfdir}/Utilities/LogoutHook" tmp/Utilities/ || exit 1 cp -r "${selfdir}/Utilities/macrecovery" tmp/Utilities/ || exit 1 @@ -82,17 +82,9 @@ package() { cd "$(dirname "$0")" || exit 1 ARCHS=(X64 IA32) SELFPKG=OpenCorePkg -DEPNAMES=('DuetPkg') -DEPURLS=( - 'https://github.com/acidanthera/DuetPkg' -) -DEPBRANCHES=('master') export ARCHS export SELFPKG -export DEPNAMES -export DEPURLS -export DEPBRANCHES ./Utilities/macserial/build.tool || exit 1